11270Sigor@sysoev.ru 21270Sigor@sysoev.ru /* 31270Sigor@sysoev.ru * Copyright (C) Igor Sysoev 41270Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 51270Sigor@sysoev.ru */ 61270Sigor@sysoev.ru 71270Sigor@sysoev.ru #include <nxt_router.h> 81270Sigor@sysoev.ru #include <nxt_http.h> 9*1394Sigor@sysoev.ru #include <nxt_upstream.h> 101270Sigor@sysoev.ru 111270Sigor@sysoev.ru 12*1394Sigor@sysoev.ru struct nxt_upstream_proxy_s { 13*1394Sigor@sysoev.ru nxt_sockaddr_t *sockaddr; 14*1394Sigor@sysoev.ru uint8_t protocol; 151270Sigor@sysoev.ru }; 161270Sigor@sysoev.ru 171270Sigor@sysoev.ru 18*1394Sigor@sysoev.ru static void nxt_http_proxy_server_get(nxt_task_t *task, 19*1394Sigor@sysoev.ru nxt_upstream_server_t *us); 20*1394Sigor@sysoev.ru static void nxt_http_proxy_upstream_ready(nxt_task_t *task, 21*1394Sigor@sysoev.ru nxt_upstream_server_t *us); 22*1394Sigor@sysoev.ru static void nxt_http_proxy_upstream_error(nxt_task_t *task, 23*1394Sigor@sysoev.ru nxt_upstream_server_t *us); 241270Sigor@sysoev.ru static nxt_http_action_t *nxt_http_proxy_handler(nxt_task_t *task, 251270Sigor@sysoev.ru nxt_http_request_t *r, nxt_http_action_t *action); 261270Sigor@sysoev.ru static void nxt_http_proxy_header_send(nxt_task_t *task, void *obj, void *data); 271270Sigor@sysoev.ru static void nxt_http_proxy_header_sent(nxt_task_t *task, void *obj, void *data); 281270Sigor@sysoev.ru static void nxt_http_proxy_header_read(nxt_task_t *task, void *obj, void *data); 291270Sigor@sysoev.ru static void nxt_http_proxy_send_body(nxt_task_t *task, void *obj, void *data); 301271Sigor@sysoev.ru static void nxt_http_proxy_request_send(nxt_task_t *task, 311271Sigor@sysoev.ru nxt_http_request_t *r, nxt_buf_t *out); 321270Sigor@sysoev.ru static void nxt_http_proxy_read(nxt_task_t *task, void *obj, void *data); 331270Sigor@sysoev.ru static void nxt_http_proxy_buf_mem_completion(nxt_task_t *task, void *obj, 341270Sigor@sysoev.ru void *data); 351270Sigor@sysoev.ru static void nxt_http_proxy_error(nxt_task_t *task, void *obj, void *data); 361270Sigor@sysoev.ru 371270Sigor@sysoev.ru 381270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_send_state; 391270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_sent_state; 401270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_read_state; 411270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_read_state; 421270Sigor@sysoev.ru 431270Sigor@sysoev.ru 44*1394Sigor@sysoev.ru static const nxt_upstream_server_proto_t nxt_upstream_simple_proto = { 45*1394Sigor@sysoev.ru .get = nxt_http_proxy_server_get, 46*1394Sigor@sysoev.ru }; 47*1394Sigor@sysoev.ru 48*1394Sigor@sysoev.ru 49*1394Sigor@sysoev.ru static const nxt_upstream_peer_state_t nxt_upstream_proxy_state = { 50*1394Sigor@sysoev.ru .ready = nxt_http_proxy_upstream_ready, 51*1394Sigor@sysoev.ru .error = nxt_http_proxy_upstream_error, 52*1394Sigor@sysoev.ru }; 53*1394Sigor@sysoev.ru 54*1394Sigor@sysoev.ru 551270Sigor@sysoev.ru nxt_int_t 561270Sigor@sysoev.ru nxt_http_proxy_create(nxt_mp_t *mp, nxt_http_action_t *action) 571270Sigor@sysoev.ru { 58*1394Sigor@sysoev.ru nxt_str_t name; 59*1394Sigor@sysoev.ru nxt_sockaddr_t *sa; 60*1394Sigor@sysoev.ru nxt_upstream_t *up; 61*1394Sigor@sysoev.ru nxt_upstream_proxy_t *proxy; 621270Sigor@sysoev.ru 631270Sigor@sysoev.ru sa = NULL; 641270Sigor@sysoev.ru name = action->name; 651270Sigor@sysoev.ru 661270Sigor@sysoev.ru if (nxt_str_start(&name, "http://", 7)) { 671270Sigor@sysoev.ru name.length -= 7; 681270Sigor@sysoev.ru name.start += 7; 691270Sigor@sysoev.ru 701270Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name); 711270Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 721270Sigor@sysoev.ru return NXT_ERROR; 731270Sigor@sysoev.ru } 741270Sigor@sysoev.ru 751270Sigor@sysoev.ru sa->type = SOCK_STREAM; 761270Sigor@sysoev.ru } 771270Sigor@sysoev.ru 781270Sigor@sysoev.ru if (sa != NULL) { 79*1394Sigor@sysoev.ru up = nxt_mp_alloc(mp, sizeof(nxt_upstream_t)); 80*1394Sigor@sysoev.ru if (nxt_slow_path(up == NULL)) { 811270Sigor@sysoev.ru return NXT_ERROR; 821270Sigor@sysoev.ru } 831270Sigor@sysoev.ru 84*1394Sigor@sysoev.ru up->name.length = sa->length; 85*1394Sigor@sysoev.ru up->name.start = nxt_sockaddr_start(sa); 86*1394Sigor@sysoev.ru up->proto = &nxt_upstream_simple_proto; 871270Sigor@sysoev.ru 88*1394Sigor@sysoev.ru proxy = nxt_mp_alloc(mp, sizeof(nxt_upstream_proxy_t)); 89*1394Sigor@sysoev.ru if (nxt_slow_path(proxy == NULL)) { 90*1394Sigor@sysoev.ru return NXT_ERROR; 91*1394Sigor@sysoev.ru } 92*1394Sigor@sysoev.ru 93*1394Sigor@sysoev.ru proxy->sockaddr = sa; 94*1394Sigor@sysoev.ru proxy->protocol = NXT_HTTP_PROTO_H1; 95*1394Sigor@sysoev.ru up->type.proxy = proxy; 96*1394Sigor@sysoev.ru 97*1394Sigor@sysoev.ru action->u.upstream = up; 981270Sigor@sysoev.ru action->handler = nxt_http_proxy_handler; 991270Sigor@sysoev.ru } 1001270Sigor@sysoev.ru 1011270Sigor@sysoev.ru return NXT_OK; 1021270Sigor@sysoev.ru } 1031270Sigor@sysoev.ru 1041270Sigor@sysoev.ru 1051270Sigor@sysoev.ru static nxt_http_action_t * 1061270Sigor@sysoev.ru nxt_http_proxy_handler(nxt_task_t *task, nxt_http_request_t *r, 1071270Sigor@sysoev.ru nxt_http_action_t *action) 1081270Sigor@sysoev.ru { 109*1394Sigor@sysoev.ru return nxt_upstream_proxy_handler(task, r, action->u.upstream); 110*1394Sigor@sysoev.ru } 111*1394Sigor@sysoev.ru 112*1394Sigor@sysoev.ru 113*1394Sigor@sysoev.ru nxt_http_action_t * 114*1394Sigor@sysoev.ru nxt_upstream_proxy_handler(nxt_task_t *task, nxt_http_request_t *r, 115*1394Sigor@sysoev.ru nxt_upstream_t *upstream) 116*1394Sigor@sysoev.ru { 117*1394Sigor@sysoev.ru nxt_http_peer_t *peer; 118*1394Sigor@sysoev.ru nxt_upstream_server_t *us; 119*1394Sigor@sysoev.ru 120*1394Sigor@sysoev.ru us = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_upstream_server_t)); 121*1394Sigor@sysoev.ru if (nxt_slow_path(us == NULL)) { 122*1394Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 123*1394Sigor@sysoev.ru return NULL; 124*1394Sigor@sysoev.ru } 1251270Sigor@sysoev.ru 1261270Sigor@sysoev.ru peer = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_http_peer_t)); 1271270Sigor@sysoev.ru if (nxt_slow_path(peer == NULL)) { 1281270Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 1291270Sigor@sysoev.ru return NULL; 1301270Sigor@sysoev.ru } 1311270Sigor@sysoev.ru 1321270Sigor@sysoev.ru peer->request = r; 1331270Sigor@sysoev.ru r->peer = peer; 1341270Sigor@sysoev.ru 1351270Sigor@sysoev.ru nxt_mp_retain(r->mem_pool); 1361270Sigor@sysoev.ru 137*1394Sigor@sysoev.ru us->state = &nxt_upstream_proxy_state; 138*1394Sigor@sysoev.ru us->peer.http = peer; 139*1394Sigor@sysoev.ru peer->server = us; 140*1394Sigor@sysoev.ru 141*1394Sigor@sysoev.ru us->upstream = upstream; 142*1394Sigor@sysoev.ru upstream->proto->get(task, us); 1431270Sigor@sysoev.ru 1441270Sigor@sysoev.ru return NULL; 1451270Sigor@sysoev.ru } 1461270Sigor@sysoev.ru 1471270Sigor@sysoev.ru 1481270Sigor@sysoev.ru static void 149*1394Sigor@sysoev.ru nxt_http_proxy_server_get(nxt_task_t *task, nxt_upstream_server_t *us) 1501270Sigor@sysoev.ru { 151*1394Sigor@sysoev.ru nxt_upstream_proxy_t *proxy; 152*1394Sigor@sysoev.ru 153*1394Sigor@sysoev.ru proxy = us->upstream->type.proxy; 154*1394Sigor@sysoev.ru 155*1394Sigor@sysoev.ru us->sockaddr = proxy->sockaddr; 156*1394Sigor@sysoev.ru us->protocol = proxy->protocol; 157*1394Sigor@sysoev.ru 158*1394Sigor@sysoev.ru us->state->ready(task, us); 159*1394Sigor@sysoev.ru } 160*1394Sigor@sysoev.ru 161*1394Sigor@sysoev.ru 162*1394Sigor@sysoev.ru static void 163*1394Sigor@sysoev.ru nxt_http_proxy_upstream_ready(nxt_task_t *task, nxt_upstream_server_t *us) 164*1394Sigor@sysoev.ru { 165*1394Sigor@sysoev.ru nxt_http_peer_t *peer; 166*1394Sigor@sysoev.ru 167*1394Sigor@sysoev.ru peer = us->peer.http; 168*1394Sigor@sysoev.ru 169*1394Sigor@sysoev.ru peer->protocol = us->protocol; 1701270Sigor@sysoev.ru 1711270Sigor@sysoev.ru peer->request->state = &nxt_http_proxy_header_send_state; 1721270Sigor@sysoev.ru 1731270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_connect(task, peer); 1741270Sigor@sysoev.ru } 1751270Sigor@sysoev.ru 1761270Sigor@sysoev.ru 177*1394Sigor@sysoev.ru static void 178*1394Sigor@sysoev.ru nxt_http_proxy_upstream_error(nxt_task_t *task, nxt_upstream_server_t *us) 179*1394Sigor@sysoev.ru { 180*1394Sigor@sysoev.ru nxt_http_request_t *r; 181*1394Sigor@sysoev.ru 182*1394Sigor@sysoev.ru r = us->peer.http->request; 183*1394Sigor@sysoev.ru 184*1394Sigor@sysoev.ru nxt_mp_release(r->mem_pool); 185*1394Sigor@sysoev.ru 186*1394Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_BAD_GATEWAY); 187*1394Sigor@sysoev.ru } 188*1394Sigor@sysoev.ru 189*1394Sigor@sysoev.ru 1901270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_send_state 1911270Sigor@sysoev.ru nxt_aligned(64) = 1921270Sigor@sysoev.ru { 1931270Sigor@sysoev.ru .ready_handler = nxt_http_proxy_header_send, 1941270Sigor@sysoev.ru .error_handler = nxt_http_proxy_error, 1951270Sigor@sysoev.ru }; 1961270Sigor@sysoev.ru 1971270Sigor@sysoev.ru 1981270Sigor@sysoev.ru static void 1991270Sigor@sysoev.ru nxt_http_proxy_header_send(nxt_task_t *task, void *obj, void *data) 2001270Sigor@sysoev.ru { 2011270Sigor@sysoev.ru nxt_http_peer_t *peer; 2021270Sigor@sysoev.ru nxt_http_request_t *r; 2031270Sigor@sysoev.ru 2041270Sigor@sysoev.ru r = obj; 2051270Sigor@sysoev.ru peer = data; 2061270Sigor@sysoev.ru r->state = &nxt_http_proxy_header_sent_state; 2071270Sigor@sysoev.ru 2081270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_header_send(task, peer); 2091270Sigor@sysoev.ru } 2101270Sigor@sysoev.ru 2111270Sigor@sysoev.ru 2121270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_sent_state 2131270Sigor@sysoev.ru nxt_aligned(64) = 2141270Sigor@sysoev.ru { 2151270Sigor@sysoev.ru .ready_handler = nxt_http_proxy_header_sent, 2161270Sigor@sysoev.ru .error_handler = nxt_http_proxy_error, 2171270Sigor@sysoev.ru }; 2181270Sigor@sysoev.ru 2191270Sigor@sysoev.ru 2201270Sigor@sysoev.ru static void 2211270Sigor@sysoev.ru nxt_http_proxy_header_sent(nxt_task_t *task, void *obj, void *data) 2221270Sigor@sysoev.ru { 2231270Sigor@sysoev.ru nxt_http_peer_t *peer; 2241270Sigor@sysoev.ru nxt_http_request_t *r; 2251270Sigor@sysoev.ru 2261270Sigor@sysoev.ru r = obj; 2271270Sigor@sysoev.ru peer = data; 2281270Sigor@sysoev.ru r->state = &nxt_http_proxy_header_read_state; 2291270Sigor@sysoev.ru 2301270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_header_read(task, peer); 2311270Sigor@sysoev.ru } 2321270Sigor@sysoev.ru 2331270Sigor@sysoev.ru 2341270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_read_state 2351270Sigor@sysoev.ru nxt_aligned(64) = 2361270Sigor@sysoev.ru { 2371270Sigor@sysoev.ru .ready_handler = nxt_http_proxy_header_read, 2381270Sigor@sysoev.ru .error_handler = nxt_http_proxy_error, 2391270Sigor@sysoev.ru }; 2401270Sigor@sysoev.ru 2411270Sigor@sysoev.ru 2421270Sigor@sysoev.ru static void 2431270Sigor@sysoev.ru nxt_http_proxy_header_read(nxt_task_t *task, void *obj, void *data) 2441270Sigor@sysoev.ru { 2451270Sigor@sysoev.ru nxt_http_peer_t *peer; 2461270Sigor@sysoev.ru nxt_http_field_t *f, *field; 2471270Sigor@sysoev.ru nxt_http_request_t *r; 2481270Sigor@sysoev.ru 2491270Sigor@sysoev.ru r = obj; 2501270Sigor@sysoev.ru peer = data; 2511270Sigor@sysoev.ru 2521270Sigor@sysoev.ru r->status = peer->status; 2531270Sigor@sysoev.ru 2541270Sigor@sysoev.ru nxt_debug(task, "http proxy status: %d", peer->status); 2551270Sigor@sysoev.ru 2561271Sigor@sysoev.ru if (r->resp.content_length_n > 0) { 2571271Sigor@sysoev.ru peer->remainder = r->resp.content_length_n; 2581271Sigor@sysoev.ru } 2591271Sigor@sysoev.ru 2601270Sigor@sysoev.ru nxt_list_each(field, peer->fields) { 2611270Sigor@sysoev.ru 2621270Sigor@sysoev.ru nxt_debug(task, "http proxy header: \"%*s: %*s\"", 2631270Sigor@sysoev.ru (size_t) field->name_length, field->name, 2641270Sigor@sysoev.ru (size_t) field->value_length, field->value); 2651270Sigor@sysoev.ru 2661270Sigor@sysoev.ru if (!field->skip) { 2671270Sigor@sysoev.ru f = nxt_list_add(r->resp.fields); 2681270Sigor@sysoev.ru if (nxt_slow_path(f == NULL)) { 2691270Sigor@sysoev.ru nxt_http_proxy_error(task, r, peer); 2701270Sigor@sysoev.ru return; 2711270Sigor@sysoev.ru } 2721270Sigor@sysoev.ru 2731270Sigor@sysoev.ru *f = *field; 2741270Sigor@sysoev.ru } 2751270Sigor@sysoev.ru 2761270Sigor@sysoev.ru } nxt_list_loop; 2771270Sigor@sysoev.ru 2781270Sigor@sysoev.ru nxt_http_request_header_send(task, r, nxt_http_proxy_send_body, peer); 2791270Sigor@sysoev.ru } 2801270Sigor@sysoev.ru 2811270Sigor@sysoev.ru 2821270Sigor@sysoev.ru static void 2831270Sigor@sysoev.ru nxt_http_proxy_send_body(nxt_task_t *task, void *obj, void *data) 2841270Sigor@sysoev.ru { 2851270Sigor@sysoev.ru nxt_buf_t *out; 2861270Sigor@sysoev.ru nxt_http_peer_t *peer; 2871270Sigor@sysoev.ru nxt_http_request_t *r; 2881270Sigor@sysoev.ru 2891270Sigor@sysoev.ru r = obj; 2901270Sigor@sysoev.ru peer = data; 2911270Sigor@sysoev.ru out = peer->body; 2921270Sigor@sysoev.ru 2931270Sigor@sysoev.ru if (out != NULL) { 2941270Sigor@sysoev.ru peer->body = NULL; 2951271Sigor@sysoev.ru nxt_http_proxy_request_send(task, r, out); 2961270Sigor@sysoev.ru } 2971270Sigor@sysoev.ru 2981270Sigor@sysoev.ru r->state = &nxt_http_proxy_read_state; 2991270Sigor@sysoev.ru 3001270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_read(task, peer); 3011270Sigor@sysoev.ru } 3021270Sigor@sysoev.ru 3031270Sigor@sysoev.ru 3041271Sigor@sysoev.ru static void 3051271Sigor@sysoev.ru nxt_http_proxy_request_send(nxt_task_t *task, nxt_http_request_t *r, 3061271Sigor@sysoev.ru nxt_buf_t *out) 3071271Sigor@sysoev.ru { 3081271Sigor@sysoev.ru size_t length; 3091271Sigor@sysoev.ru 3101271Sigor@sysoev.ru if (r->peer->remainder > 0) { 3111271Sigor@sysoev.ru length = nxt_buf_chain_length(out); 3121271Sigor@sysoev.ru r->peer->remainder -= length; 3131271Sigor@sysoev.ru } 3141271Sigor@sysoev.ru 3151271Sigor@sysoev.ru nxt_http_request_send(task, r, out); 3161271Sigor@sysoev.ru } 3171271Sigor@sysoev.ru 3181271Sigor@sysoev.ru 3191270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_read_state 3201270Sigor@sysoev.ru nxt_aligned(64) = 3211270Sigor@sysoev.ru { 3221270Sigor@sysoev.ru .ready_handler = nxt_http_proxy_read, 3231270Sigor@sysoev.ru .error_handler = nxt_http_proxy_error, 3241270Sigor@sysoev.ru }; 3251270Sigor@sysoev.ru 3261270Sigor@sysoev.ru 3271270Sigor@sysoev.ru static void 3281270Sigor@sysoev.ru nxt_http_proxy_read(nxt_task_t *task, void *obj, void *data) 3291270Sigor@sysoev.ru { 3301270Sigor@sysoev.ru nxt_buf_t *out; 3311270Sigor@sysoev.ru nxt_bool_t last; 3321270Sigor@sysoev.ru nxt_http_peer_t *peer; 3331270Sigor@sysoev.ru nxt_http_request_t *r; 3341270Sigor@sysoev.ru 3351270Sigor@sysoev.ru r = obj; 3361270Sigor@sysoev.ru peer = data; 3371270Sigor@sysoev.ru out = peer->body; 3381270Sigor@sysoev.ru peer->body = NULL; 3391270Sigor@sysoev.ru last = nxt_buf_is_last(out); 3401270Sigor@sysoev.ru 3411271Sigor@sysoev.ru nxt_http_proxy_request_send(task, r, out); 3421270Sigor@sysoev.ru 3431270Sigor@sysoev.ru if (!last) { 3441270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_read(task, peer); 3451270Sigor@sysoev.ru 3461270Sigor@sysoev.ru } else { 3471271Sigor@sysoev.ru r->inconsistent = (peer->remainder != 0); 3481271Sigor@sysoev.ru 3491270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_close(task, peer); 3501270Sigor@sysoev.ru 3511270Sigor@sysoev.ru nxt_mp_release(r->mem_pool); 3521270Sigor@sysoev.ru } 3531270Sigor@sysoev.ru } 3541270Sigor@sysoev.ru 3551270Sigor@sysoev.ru 3561270Sigor@sysoev.ru nxt_buf_t * 3571270Sigor@sysoev.ru nxt_http_proxy_buf_mem_alloc(nxt_task_t *task, nxt_http_request_t *r, 3581270Sigor@sysoev.ru size_t size) 3591270Sigor@sysoev.ru { 3601270Sigor@sysoev.ru nxt_buf_t *b; 3611270Sigor@sysoev.ru 3621270Sigor@sysoev.ru b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size); 3631270Sigor@sysoev.ru if (nxt_fast_path(b != NULL)) { 3641270Sigor@sysoev.ru b->completion_handler = nxt_http_proxy_buf_mem_completion; 3651270Sigor@sysoev.ru b->parent = r; 3661270Sigor@sysoev.ru nxt_mp_retain(r->mem_pool); 3671270Sigor@sysoev.ru 3681270Sigor@sysoev.ru } else { 3691270Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 3701270Sigor@sysoev.ru } 3711270Sigor@sysoev.ru 3721270Sigor@sysoev.ru return b; 3731270Sigor@sysoev.ru } 3741270Sigor@sysoev.ru 3751270Sigor@sysoev.ru 3761270Sigor@sysoev.ru static void 3771270Sigor@sysoev.ru nxt_http_proxy_buf_mem_completion(nxt_task_t *task, void *obj, void *data) 3781270Sigor@sysoev.ru { 3791270Sigor@sysoev.ru nxt_buf_t *b, *next; 3801270Sigor@sysoev.ru nxt_http_peer_t *peer; 3811270Sigor@sysoev.ru nxt_http_request_t *r; 3821270Sigor@sysoev.ru 3831270Sigor@sysoev.ru b = obj; 3841270Sigor@sysoev.ru r = data; 3851270Sigor@sysoev.ru 3861270Sigor@sysoev.ru peer = r->peer; 3871270Sigor@sysoev.ru 3881270Sigor@sysoev.ru do { 3891270Sigor@sysoev.ru next = b->next; 3901270Sigor@sysoev.ru 3911270Sigor@sysoev.ru nxt_http_proxy_buf_mem_free(task, r, b); 3921270Sigor@sysoev.ru 3931270Sigor@sysoev.ru b = next; 3941270Sigor@sysoev.ru } while (b != NULL); 3951270Sigor@sysoev.ru 3961270Sigor@sysoev.ru if (!peer->closed) { 3971270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_read(task, peer); 3981270Sigor@sysoev.ru } 3991270Sigor@sysoev.ru } 4001270Sigor@sysoev.ru 4011270Sigor@sysoev.ru 4021270Sigor@sysoev.ru void 4031270Sigor@sysoev.ru nxt_http_proxy_buf_mem_free(nxt_task_t *task, nxt_http_request_t *r, 4041270Sigor@sysoev.ru nxt_buf_t *b) 4051270Sigor@sysoev.ru { 4061270Sigor@sysoev.ru nxt_event_engine_buf_mem_free(task->thread->engine, b); 4071270Sigor@sysoev.ru 4081270Sigor@sysoev.ru nxt_mp_release(r->mem_pool); 4091270Sigor@sysoev.ru } 4101270Sigor@sysoev.ru 4111270Sigor@sysoev.ru 4121270Sigor@sysoev.ru static void 4131270Sigor@sysoev.ru nxt_http_proxy_error(nxt_task_t *task, void *obj, void *data) 4141270Sigor@sysoev.ru { 4151270Sigor@sysoev.ru nxt_http_peer_t *peer; 4161270Sigor@sysoev.ru nxt_http_request_t *r; 4171270Sigor@sysoev.ru 4181270Sigor@sysoev.ru r = obj; 4191270Sigor@sysoev.ru peer = r->peer; 4201270Sigor@sysoev.ru 4211270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_close(task, peer); 4221270Sigor@sysoev.ru 4231270Sigor@sysoev.ru nxt_mp_release(r->mem_pool); 4241270Sigor@sysoev.ru 4251270Sigor@sysoev.ru nxt_http_request_error(task, r, peer->status); 4261270Sigor@sysoev.ru } 4271270Sigor@sysoev.ru 4281270Sigor@sysoev.ru 4291270Sigor@sysoev.ru nxt_int_t 4301270Sigor@sysoev.ru nxt_http_proxy_date(void *ctx, nxt_http_field_t *field, uintptr_t data) 4311270Sigor@sysoev.ru { 4321270Sigor@sysoev.ru nxt_http_request_t *r; 4331270Sigor@sysoev.ru 4341270Sigor@sysoev.ru r = ctx; 4351270Sigor@sysoev.ru 4361270Sigor@sysoev.ru r->resp.date = field; 4371270Sigor@sysoev.ru 4381270Sigor@sysoev.ru return NXT_OK; 4391270Sigor@sysoev.ru } 4401270Sigor@sysoev.ru 4411270Sigor@sysoev.ru 4421270Sigor@sysoev.ru nxt_int_t 4431270Sigor@sysoev.ru nxt_http_proxy_content_length(void *ctx, nxt_http_field_t *field, 4441270Sigor@sysoev.ru uintptr_t data) 4451270Sigor@sysoev.ru { 4461270Sigor@sysoev.ru nxt_off_t n; 4471270Sigor@sysoev.ru nxt_http_request_t *r; 4481270Sigor@sysoev.ru 4491270Sigor@sysoev.ru r = ctx; 4501270Sigor@sysoev.ru 4511270Sigor@sysoev.ru r->resp.content_length = field; 4521270Sigor@sysoev.ru 4531270Sigor@sysoev.ru n = nxt_off_t_parse(field->value, field->value_length); 4541270Sigor@sysoev.ru 4551270Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) { 4561270Sigor@sysoev.ru r->resp.content_length_n = n; 4571270Sigor@sysoev.ru } 4581270Sigor@sysoev.ru 4591270Sigor@sysoev.ru return NXT_OK; 4601270Sigor@sysoev.ru } 4611270Sigor@sysoev.ru 4621270Sigor@sysoev.ru 4631270Sigor@sysoev.ru nxt_int_t 4641270Sigor@sysoev.ru nxt_http_proxy_skip(void *ctx, nxt_http_field_t *field, uintptr_t data) 4651270Sigor@sysoev.ru { 4661270Sigor@sysoev.ru field->skip = 1; 4671270Sigor@sysoev.ru 4681270Sigor@sysoev.ru return NXT_OK; 4691270Sigor@sysoev.ru } 470