| 128 if(!proxy->response_started) { |
128 if(!proxy->response_started) { |
| 129 protocol_status(proxy->sn, proxy->rq, 502, NULL); |
129 protocol_status(proxy->sn, proxy->rq, 502, NULL); |
| 130 ret = REQ_ABORTED; |
130 ret = REQ_ABORTED; |
| 131 } |
131 } |
| 132 |
132 |
| |
133 if(client->last_event != &proxy->event && proxy->event.fn != NULL) { |
| |
134 if(!ev_remove_poll(client->ev, proxy->event.object)) { |
| |
135 proxy_unref(proxy); |
| |
136 } else { |
| |
137 log_ereport(LOG_FAILURE, "proxy_response_finished: cannot remove poll"); |
| |
138 } |
| |
139 proxy->event.finish = NULL; |
| |
140 } |
| |
141 |
| |
142 // return to nsapi threadpool |
| |
143 net_setnonblock(proxy->sn->csd, 0); |
| 133 nsapi_function_return(proxy->sn, proxy->rq, ret); |
144 nsapi_function_return(proxy->sn, proxy->rq, ret); |
| 134 |
145 |
| 135 proxy_unref(proxy); |
146 proxy_unref(proxy); |
| 136 } |
147 } |
| 137 |
148 |
| 138 static int proxy_request_read_event(EventHandler *eh, Event *event) { |
149 static int proxy_request_read_event(EventHandler *eh, Event *event) { |
| 139 ProxyRequest *proxy = event->cookie; |
150 ProxyRequest *proxy = event->cookie; |
| 140 if(http_client_process(proxy->client)) { |
151 if(http_client_process(proxy->client, event)) { |
| 141 if(proxy->client->error == 0) { |
152 if(proxy->client->error == 0) { |
| 142 return 1; |
153 return 1; |
| 143 } |
154 } |
| 144 } |
155 } |
| 145 return 0; |
156 return 0; |
| 159 } else if(ret < 0) { |
170 } else if(ret < 0) { |
| 160 IOStream *st = proxy->sn->csd; |
171 IOStream *st = proxy->sn->csd; |
| 161 if(st->io_errno == EWOULDBLOCK) { |
172 if(st->io_errno == EWOULDBLOCK) { |
| 162 ret = HTTP_CLIENT_CALLBACK_WOULD_BLOCK; |
173 ret = HTTP_CLIENT_CALLBACK_WOULD_BLOCK; |
| 163 // is there already an poll event for csd? |
174 // is there already an poll event for csd? |
| 164 if(!proxy->event.cookie) { |
175 if(!proxy->event.fn) { |
| 165 proxy->ref++; |
176 proxy->ref++; |
| 166 proxy->event.cookie = proxy; |
177 proxy->event.cookie = proxy; |
| 167 proxy->event.fn = proxy_request_read_event; |
178 proxy->event.fn = proxy_request_read_event; |
| 168 proxy->event.finish = proxy_request_read_finished; |
179 proxy->event.finish = proxy_request_read_finished; |
| 169 if(event_pollin(client->ev, st, &proxy->event)) { |
180 if(event_pollin(client->ev, st, &proxy->event)) { |
| 179 } |
190 } |
| 180 |
191 |
| 181 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) { |
192 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) { |
| 182 ProxyRequest *proxy = userdata; |
193 ProxyRequest *proxy = userdata; |
| 183 ssize_t ret = net_write(proxy->sn->csd, buf, nbytes); |
194 ssize_t ret = net_write(proxy->sn->csd, buf, nbytes); |
| 184 // TODO: handle errors |
195 if(ret == NETBUF_EOF) { |
| |
196 ret = HTTP_CLIENT_CALLBACK_ERROR; |
| |
197 } else if(ret < 0) { |
| |
198 IOStream *st = proxy->sn->csd; |
| |
199 if(st->io_errno == EWOULDBLOCK) { |
| |
200 // Is there already an poll event for csd? |
| |
201 if(client->last_event == &proxy->event) { |
| |
202 // Yes, there is already an event, and it even is the event that triggert this call. |
| |
203 // Make sure it is a write event |
| |
204 proxy->event.events = EVENT_POLLOUT; |
| |
205 return HTTP_CLIENT_CALLBACK_WOULD_BLOCK; |
| |
206 } else if(proxy->event.fn != NULL) { |
| |
207 // There is an inactive event, probably a read event |
| |
208 // Remove the old event before we add a write event |
| |
209 if(ev_remove_poll(client->ev, proxy->event.object)) { |
| |
210 log_ereport(LOG_FAILURE, "proxy_response_write: cannot remove poll"); |
| |
211 return HTTP_CLIENT_CALLBACK_ERROR; |
| |
212 } |
| |
213 } else { |
| |
214 proxy->ref++; |
| |
215 proxy->event.cookie = proxy; |
| |
216 proxy->event.fn = proxy_request_read_event; |
| |
217 proxy->event.finish = proxy_request_read_finished; |
| |
218 } |
| |
219 // Add write event |
| |
220 if(event_pollout(client->ev, proxy->sn->csd, &proxy->event)) { |
| |
221 proxy_unref(proxy); |
| |
222 log_ereport(LOG_FAILURE, "proxy_response_write: cannot add write poll"); |
| |
223 } |
| |
224 return HTTP_CLIENT_CALLBACK_ERROR; |
| |
225 } |
| |
226 } |
| 185 return ret; |
227 return ret; |
| 186 } |
|
| 187 |
|
| 188 static void proxy_request_finished(HttpClient *client, void *userdata) { |
|
| 189 ProxyRequest *proxy = userdata; |
|
| 190 net_setnonblock(proxy->sn->csd, 0); |
|
| 191 nsapi_saf_return(proxy->sn, proxy->rq, REQ_PROCEED); |
|
| 192 } |
228 } |
| 193 |
229 |
| 194 int http_reverse_proxy_service(pblock *param, Session *sn, Request *rq) { |
230 int http_reverse_proxy_service(pblock *param, Session *sn, Request *rq) { |
| 195 EventHandler *ev = sn->ev; |
231 EventHandler *ev = sn->ev; |
| 196 const char *method = pblock_findkeyval(pb_key_method, rq->reqpb); |
232 const char *method = pblock_findkeyval(pb_key_method, rq->reqpb); |
| 394 client->request_body_read_userdata = proxy; |
430 client->request_body_read_userdata = proxy; |
| 395 client->response_start = proxy_response_start; |
431 client->response_start = proxy_response_start; |
| 396 client->response_start_userdata = proxy; |
432 client->response_start_userdata = proxy; |
| 397 client->response_body_write = proxy_response_write; |
433 client->response_body_write = proxy_response_write; |
| 398 client->response_body_write_userdata = proxy; |
434 client->response_body_write_userdata = proxy; |
| 399 client->response_finished = proxy_request_finished; |
435 client->response_finished = proxy_response_finished; |
| 400 client->response_finished_userdata = proxy; |
436 client->response_finished_userdata = proxy; |
| 401 |
437 |
| 402 net_setnonblock(sn->csd, 1); |
438 net_setnonblock(sn->csd, 1); |
| 403 if(http_client_start(client)) { |
439 if(http_client_start(client)) { |
| 404 net_setnonblock(sn->csd, 0); |
440 net_setnonblock(sn->csd, 0); |