| 35 #include <ctype.h> |
35 #include <ctype.h> |
| 36 #include <string.h> |
36 #include <string.h> |
| 37 |
37 |
| 38 #include "../util/pblock.h" |
38 #include "../util/pblock.h" |
| 39 #include "../util/util.h" |
39 #include "../util/util.h" |
| |
40 #include "../util/io.h" |
| 40 #include "../proxy/httpclient.h" |
41 #include "../proxy/httpclient.h" |
| 41 |
42 |
| 42 |
43 |
| 43 typedef struct ProxyRequest { |
44 typedef struct ProxyRequest { |
| 44 Session *sn; |
45 Session *sn; |
| 45 Request *rq; |
46 Request *rq; |
| |
47 |
| |
48 HttpClient *client; |
| 46 |
49 |
| 47 /* |
50 /* |
| 48 * request header rewrite map |
51 * request header rewrite map |
| 49 * name: header name |
52 * name: header name |
| 50 * value: header value or an empty string, if the header should be removed |
53 * value: header value or an empty string, if the header should be removed |
| 57 * value: header value or an empty string, if the header should be removed |
60 * value: header value or an empty string, if the header should be removed |
| 58 */ |
61 */ |
| 59 pblock *response_header_rewrite; |
62 pblock *response_header_rewrite; |
| 60 |
63 |
| 61 /* |
64 /* |
| |
65 * event structure for sn->csd |
| |
66 */ |
| |
67 Event event; |
| |
68 |
| |
69 /* |
| 62 * Has the response started (proxy_response_start called) |
70 * Has the response started (proxy_response_start called) |
| 63 */ |
71 */ |
| 64 int response_started; |
72 int response_started; |
| |
73 |
| |
74 /* |
| |
75 * reference counter |
| |
76 */ |
| |
77 int ref; |
| 65 } ProxyRequest; |
78 } ProxyRequest; |
| |
79 |
| |
80 static void proxy_unref(ProxyRequest *proxy) { |
| |
81 if(--proxy->ref == 0) { |
| |
82 http_client_free(proxy->client); |
| |
83 free(proxy); |
| |
84 } |
| |
85 } |
| 66 |
86 |
| 67 static int proxy_response_start(HttpClient *client, int status, char *message, void *userdata) { |
87 static int proxy_response_start(HttpClient *client, int status, char *message, void *userdata) { |
| 68 ProxyRequest *proxy = userdata; |
88 ProxyRequest *proxy = userdata; |
| 69 |
89 |
| 70 HeaderArray *headers = client->response_headers; |
90 HeaderArray *headers = client->response_headers; |
| 108 if(!proxy->response_started) { |
128 if(!proxy->response_started) { |
| 109 protocol_status(proxy->sn, proxy->rq, 502, NULL); |
129 protocol_status(proxy->sn, proxy->rq, 502, NULL); |
| 110 ret = REQ_ABORTED; |
130 ret = REQ_ABORTED; |
| 111 } |
131 } |
| 112 |
132 |
| 113 http_client_free(client); |
|
| 114 |
|
| 115 nsapi_function_return(proxy->sn, proxy->rq, ret); |
133 nsapi_function_return(proxy->sn, proxy->rq, ret); |
| |
134 |
| |
135 proxy_unref(proxy); |
| |
136 } |
| |
137 |
| |
138 static int proxy_request_read_event(EventHandler *eh, Event *event) { |
| |
139 ProxyRequest *proxy = event->cookie; |
| |
140 if(http_client_process(proxy->client)) { |
| |
141 if(proxy->client->error == 0) { |
| |
142 return 1; |
| |
143 } |
| |
144 } |
| |
145 return 0; |
| |
146 } |
| |
147 |
| |
148 static int proxy_request_read_finished(EventHandler *eh, Event *event) { |
| |
149 ProxyRequest *proxy = event->cookie; |
| |
150 proxy_unref(proxy); |
| |
151 return 0; |
| 116 } |
152 } |
| 117 |
153 |
| 118 static ssize_t proxy_request_read(HttpClient *client, void *buf, size_t nbytes, void *userdata) { |
154 static ssize_t proxy_request_read(HttpClient *client, void *buf, size_t nbytes, void *userdata) { |
| 119 ProxyRequest *proxy = userdata; |
155 ProxyRequest *proxy = userdata; |
| 120 int ret = netbuf_getbytes(proxy->sn->inbuf, buf, nbytes); |
156 int ret = netbuf_getbytes(proxy->sn->inbuf, buf, nbytes); |
| 121 if(ret == NETBUF_EOF) { |
157 if(ret == NETBUF_EOF) { |
| 122 ret = 0; |
158 ret = 0; |
| 123 } |
159 } else if(ret < 0) { |
| 124 // TODO: handle errors |
160 IOStream *st = proxy->sn->csd; |
| |
161 if(st->io_errno == EWOULDBLOCK) { |
| |
162 ret = HTTP_CLIENT_CALLBACK_WOULD_BLOCK; |
| |
163 // is there already an poll event for csd? |
| |
164 if(!proxy->event.cookie) { |
| |
165 proxy->ref++; |
| |
166 proxy->event.cookie = proxy; |
| |
167 proxy->event.fn = proxy_request_read_event; |
| |
168 proxy->event.finish = proxy_request_read_finished; |
| |
169 if(event_pollin(client->ev, st, &proxy->event)) { |
| |
170 ret = HTTP_CLIENT_CALLBACK_ERROR; |
| |
171 } |
| |
172 } |
| |
173 } else { |
| |
174 ret = HTTP_CLIENT_CALLBACK_ERROR; |
| |
175 } |
| |
176 } |
| |
177 |
| 125 return ret; |
178 return ret; |
| 126 } |
179 } |
| 127 |
180 |
| 128 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) { |
181 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) { |
| 129 ProxyRequest *proxy = userdata; |
182 ProxyRequest *proxy = userdata; |
| 226 |
279 |
| 227 // remove some response headers, that were previously set by ObjectType |
280 // remove some response headers, that were previously set by ObjectType |
| 228 // or other SAFs |
281 // or other SAFs |
| 229 pblock_removekey(pb_key_content_type, rq->srvhdrs); |
282 pblock_removekey(pb_key_content_type, rq->srvhdrs); |
| 230 |
283 |
| 231 ProxyRequest *proxy = pool_malloc(sn->pool, sizeof(ProxyRequest)); |
284 ProxyRequest *proxy = malloc(sizeof(ProxyRequest)); |
| 232 proxy->sn = sn; |
285 proxy->sn = sn; |
| 233 proxy->rq = rq; |
286 proxy->rq = rq; |
| 234 proxy->request_header_rewrite = pblock_create_pool(sn->pool, 16); |
287 proxy->request_header_rewrite = pblock_create_pool(sn->pool, 16); |
| 235 proxy->response_header_rewrite = pblock_create_pool(sn->pool, 16); |
288 proxy->response_header_rewrite = pblock_create_pool(sn->pool, 16); |
| 236 proxy->response_started = 0; |
289 proxy->response_started = 0; |
| |
290 proxy->ref = 1; |
| 237 |
291 |
| 238 // Some request/response headers should be removed or altered |
292 // Some request/response headers should be removed or altered |
| 239 // An empty string means, the header should be removed |
293 // An empty string means, the header should be removed |
| 240 pblock_nvinsert("host", "", proxy->request_header_rewrite); |
294 pblock_nvinsert("host", "", proxy->request_header_rewrite); |
| 241 pblock_nvinsert("connection", "", proxy->request_header_rewrite); |
295 pblock_nvinsert("connection", "", proxy->request_header_rewrite); |