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>
91394Sigor@sysoev.ru #include <nxt_upstream.h>
101270Sigor@sysoev.ru
111270Sigor@sysoev.ru
121394Sigor@sysoev.ru struct nxt_upstream_proxy_s {
131394Sigor@sysoev.ru nxt_sockaddr_t *sockaddr;
141394Sigor@sysoev.ru uint8_t protocol;
151270Sigor@sysoev.ru };
161270Sigor@sysoev.ru
171270Sigor@sysoev.ru
181394Sigor@sysoev.ru static void nxt_http_proxy_server_get(nxt_task_t *task,
191394Sigor@sysoev.ru nxt_upstream_server_t *us);
201394Sigor@sysoev.ru static void nxt_http_proxy_upstream_ready(nxt_task_t *task,
211394Sigor@sysoev.ru nxt_upstream_server_t *us);
221394Sigor@sysoev.ru static void nxt_http_proxy_upstream_error(nxt_task_t *task,
231394Sigor@sysoev.ru nxt_upstream_server_t *us);
24*1924Sz.hong@f5.com static nxt_http_action_t *nxt_http_proxy(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);
301270Sigor@sysoev.ru static void nxt_http_proxy_buf_mem_completion(nxt_task_t *task, void *obj,
311270Sigor@sysoev.ru void *data);
321270Sigor@sysoev.ru static void nxt_http_proxy_error(nxt_task_t *task, void *obj, void *data);
331270Sigor@sysoev.ru
341270Sigor@sysoev.ru
351270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_send_state;
361270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_sent_state;
371270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_read_state;
381270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_read_state;
391270Sigor@sysoev.ru
401270Sigor@sysoev.ru
411394Sigor@sysoev.ru static const nxt_upstream_server_proto_t nxt_upstream_simple_proto = {
421394Sigor@sysoev.ru .get = nxt_http_proxy_server_get,
431394Sigor@sysoev.ru };
441394Sigor@sysoev.ru
451394Sigor@sysoev.ru
461394Sigor@sysoev.ru static const nxt_upstream_peer_state_t nxt_upstream_proxy_state = {
471394Sigor@sysoev.ru .ready = nxt_http_proxy_upstream_ready,
481394Sigor@sysoev.ru .error = nxt_http_proxy_upstream_error,
491394Sigor@sysoev.ru };
501394Sigor@sysoev.ru
511394Sigor@sysoev.ru
521270Sigor@sysoev.ru nxt_int_t
nxt_http_proxy_init(nxt_mp_t * mp,nxt_http_action_t * action,nxt_http_action_conf_t * acf)53*1924Sz.hong@f5.com nxt_http_proxy_init(nxt_mp_t *mp, nxt_http_action_t *action,
54*1924Sz.hong@f5.com nxt_http_action_conf_t *acf)
551270Sigor@sysoev.ru {
561394Sigor@sysoev.ru nxt_str_t name;
571394Sigor@sysoev.ru nxt_sockaddr_t *sa;
581394Sigor@sysoev.ru nxt_upstream_t *up;
591394Sigor@sysoev.ru nxt_upstream_proxy_t *proxy;
601270Sigor@sysoev.ru
611270Sigor@sysoev.ru sa = NULL;
62*1924Sz.hong@f5.com nxt_conf_get_string(acf->proxy, &name);
631270Sigor@sysoev.ru
641270Sigor@sysoev.ru if (nxt_str_start(&name, "http://", 7)) {
651270Sigor@sysoev.ru name.length -= 7;
661270Sigor@sysoev.ru name.start += 7;
671270Sigor@sysoev.ru
681270Sigor@sysoev.ru sa = nxt_sockaddr_parse(mp, &name);
691270Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) {
701270Sigor@sysoev.ru return NXT_ERROR;
711270Sigor@sysoev.ru }
721270Sigor@sysoev.ru
731270Sigor@sysoev.ru sa->type = SOCK_STREAM;
741270Sigor@sysoev.ru }
751270Sigor@sysoev.ru
761270Sigor@sysoev.ru if (sa != NULL) {
771394Sigor@sysoev.ru up = nxt_mp_alloc(mp, sizeof(nxt_upstream_t));
781394Sigor@sysoev.ru if (nxt_slow_path(up == NULL)) {
791270Sigor@sysoev.ru return NXT_ERROR;
801270Sigor@sysoev.ru }
811270Sigor@sysoev.ru
821394Sigor@sysoev.ru up->name.length = sa->length;
831394Sigor@sysoev.ru up->name.start = nxt_sockaddr_start(sa);
841394Sigor@sysoev.ru up->proto = &nxt_upstream_simple_proto;
851270Sigor@sysoev.ru
861394Sigor@sysoev.ru proxy = nxt_mp_alloc(mp, sizeof(nxt_upstream_proxy_t));
871394Sigor@sysoev.ru if (nxt_slow_path(proxy == NULL)) {
881394Sigor@sysoev.ru return NXT_ERROR;
891394Sigor@sysoev.ru }
901394Sigor@sysoev.ru
911394Sigor@sysoev.ru proxy->sockaddr = sa;
921394Sigor@sysoev.ru proxy->protocol = NXT_HTTP_PROTO_H1;
931394Sigor@sysoev.ru up->type.proxy = proxy;
941394Sigor@sysoev.ru
951394Sigor@sysoev.ru action->u.upstream = up;
96*1924Sz.hong@f5.com action->handler = nxt_http_proxy;
971270Sigor@sysoev.ru }
981270Sigor@sysoev.ru
991270Sigor@sysoev.ru return NXT_OK;
1001270Sigor@sysoev.ru }
1011270Sigor@sysoev.ru
1021270Sigor@sysoev.ru
1031270Sigor@sysoev.ru static nxt_http_action_t *
nxt_http_proxy(nxt_task_t * task,nxt_http_request_t * r,nxt_http_action_t * action)104*1924Sz.hong@f5.com nxt_http_proxy(nxt_task_t *task, nxt_http_request_t *r,
1051270Sigor@sysoev.ru nxt_http_action_t *action)
1061270Sigor@sysoev.ru {
107*1924Sz.hong@f5.com nxt_upstream_t *u;
108*1924Sz.hong@f5.com
109*1924Sz.hong@f5.com u = action->u.upstream;
110*1924Sz.hong@f5.com
111*1924Sz.hong@f5.com nxt_debug(task, "http proxy: \"%V\"", &u->name);
112*1924Sz.hong@f5.com
113*1924Sz.hong@f5.com return nxt_upstream_proxy_handler(task, r, u);
1141394Sigor@sysoev.ru }
1151394Sigor@sysoev.ru
1161394Sigor@sysoev.ru
1171394Sigor@sysoev.ru nxt_http_action_t *
nxt_upstream_proxy_handler(nxt_task_t * task,nxt_http_request_t * r,nxt_upstream_t * upstream)1181394Sigor@sysoev.ru nxt_upstream_proxy_handler(nxt_task_t *task, nxt_http_request_t *r,
1191394Sigor@sysoev.ru nxt_upstream_t *upstream)
1201394Sigor@sysoev.ru {
1211394Sigor@sysoev.ru nxt_http_peer_t *peer;
1221394Sigor@sysoev.ru nxt_upstream_server_t *us;
1231394Sigor@sysoev.ru
1241394Sigor@sysoev.ru us = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_upstream_server_t));
1251394Sigor@sysoev.ru if (nxt_slow_path(us == NULL)) {
1261394Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
1271394Sigor@sysoev.ru return NULL;
1281394Sigor@sysoev.ru }
1291270Sigor@sysoev.ru
1301270Sigor@sysoev.ru peer = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_http_peer_t));
1311270Sigor@sysoev.ru if (nxt_slow_path(peer == NULL)) {
1321270Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
1331270Sigor@sysoev.ru return NULL;
1341270Sigor@sysoev.ru }
1351270Sigor@sysoev.ru
1361270Sigor@sysoev.ru peer->request = r;
1371270Sigor@sysoev.ru r->peer = peer;
1381270Sigor@sysoev.ru
1391270Sigor@sysoev.ru nxt_mp_retain(r->mem_pool);
1401270Sigor@sysoev.ru
1411394Sigor@sysoev.ru us->state = &nxt_upstream_proxy_state;
1421394Sigor@sysoev.ru us->peer.http = peer;
1431394Sigor@sysoev.ru peer->server = us;
1441394Sigor@sysoev.ru
1451394Sigor@sysoev.ru us->upstream = upstream;
1461394Sigor@sysoev.ru upstream->proto->get(task, us);
1471270Sigor@sysoev.ru
1481270Sigor@sysoev.ru return NULL;
1491270Sigor@sysoev.ru }
1501270Sigor@sysoev.ru
1511270Sigor@sysoev.ru
1521270Sigor@sysoev.ru static void
nxt_http_proxy_server_get(nxt_task_t * task,nxt_upstream_server_t * us)1531394Sigor@sysoev.ru nxt_http_proxy_server_get(nxt_task_t *task, nxt_upstream_server_t *us)
1541270Sigor@sysoev.ru {
1551394Sigor@sysoev.ru nxt_upstream_proxy_t *proxy;
1561394Sigor@sysoev.ru
1571394Sigor@sysoev.ru proxy = us->upstream->type.proxy;
1581394Sigor@sysoev.ru
1591394Sigor@sysoev.ru us->sockaddr = proxy->sockaddr;
1601394Sigor@sysoev.ru us->protocol = proxy->protocol;
1611394Sigor@sysoev.ru
1621394Sigor@sysoev.ru us->state->ready(task, us);
1631394Sigor@sysoev.ru }
1641394Sigor@sysoev.ru
1651394Sigor@sysoev.ru
1661394Sigor@sysoev.ru static void
nxt_http_proxy_upstream_ready(nxt_task_t * task,nxt_upstream_server_t * us)1671394Sigor@sysoev.ru nxt_http_proxy_upstream_ready(nxt_task_t *task, nxt_upstream_server_t *us)
1681394Sigor@sysoev.ru {
1691394Sigor@sysoev.ru nxt_http_peer_t *peer;
1701394Sigor@sysoev.ru
1711394Sigor@sysoev.ru peer = us->peer.http;
1721394Sigor@sysoev.ru
1731394Sigor@sysoev.ru peer->protocol = us->protocol;
1741270Sigor@sysoev.ru
1751270Sigor@sysoev.ru peer->request->state = &nxt_http_proxy_header_send_state;
1761270Sigor@sysoev.ru
1771270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_connect(task, peer);
1781270Sigor@sysoev.ru }
1791270Sigor@sysoev.ru
1801270Sigor@sysoev.ru
1811394Sigor@sysoev.ru static void
nxt_http_proxy_upstream_error(nxt_task_t * task,nxt_upstream_server_t * us)1821394Sigor@sysoev.ru nxt_http_proxy_upstream_error(nxt_task_t *task, nxt_upstream_server_t *us)
1831394Sigor@sysoev.ru {
1841394Sigor@sysoev.ru nxt_http_request_t *r;
1851394Sigor@sysoev.ru
1861394Sigor@sysoev.ru r = us->peer.http->request;
1871394Sigor@sysoev.ru
1881394Sigor@sysoev.ru nxt_mp_release(r->mem_pool);
1891394Sigor@sysoev.ru
1901394Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_BAD_GATEWAY);
1911394Sigor@sysoev.ru }
1921394Sigor@sysoev.ru
1931394Sigor@sysoev.ru
1941270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_send_state
1951270Sigor@sysoev.ru nxt_aligned(64) =
1961270Sigor@sysoev.ru {
1971270Sigor@sysoev.ru .ready_handler = nxt_http_proxy_header_send,
1981270Sigor@sysoev.ru .error_handler = nxt_http_proxy_error,
1991270Sigor@sysoev.ru };
2001270Sigor@sysoev.ru
2011270Sigor@sysoev.ru
2021270Sigor@sysoev.ru static void
nxt_http_proxy_header_send(nxt_task_t * task,void * obj,void * data)2031270Sigor@sysoev.ru nxt_http_proxy_header_send(nxt_task_t *task, void *obj, void *data)
2041270Sigor@sysoev.ru {
2051270Sigor@sysoev.ru nxt_http_peer_t *peer;
2061270Sigor@sysoev.ru nxt_http_request_t *r;
2071270Sigor@sysoev.ru
2081270Sigor@sysoev.ru r = obj;
2091270Sigor@sysoev.ru peer = data;
2101270Sigor@sysoev.ru r->state = &nxt_http_proxy_header_sent_state;
2111270Sigor@sysoev.ru
2121270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_header_send(task, peer);
2131270Sigor@sysoev.ru }
2141270Sigor@sysoev.ru
2151270Sigor@sysoev.ru
2161270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_sent_state
2171270Sigor@sysoev.ru nxt_aligned(64) =
2181270Sigor@sysoev.ru {
2191270Sigor@sysoev.ru .ready_handler = nxt_http_proxy_header_sent,
2201270Sigor@sysoev.ru .error_handler = nxt_http_proxy_error,
2211270Sigor@sysoev.ru };
2221270Sigor@sysoev.ru
2231270Sigor@sysoev.ru
2241270Sigor@sysoev.ru static void
nxt_http_proxy_header_sent(nxt_task_t * task,void * obj,void * data)2251270Sigor@sysoev.ru nxt_http_proxy_header_sent(nxt_task_t *task, void *obj, void *data)
2261270Sigor@sysoev.ru {
2271270Sigor@sysoev.ru nxt_http_peer_t *peer;
2281270Sigor@sysoev.ru nxt_http_request_t *r;
2291270Sigor@sysoev.ru
2301270Sigor@sysoev.ru r = obj;
2311270Sigor@sysoev.ru peer = data;
2321270Sigor@sysoev.ru r->state = &nxt_http_proxy_header_read_state;
2331270Sigor@sysoev.ru
2341270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_header_read(task, peer);
2351270Sigor@sysoev.ru }
2361270Sigor@sysoev.ru
2371270Sigor@sysoev.ru
2381270Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_header_read_state
2391270Sigor@sysoev.ru nxt_aligned(64) =
2401270Sigor@sysoev.ru {
2411270Sigor@sysoev.ru .ready_handler = nxt_http_proxy_header_read,
2421270Sigor@sysoev.ru .error_handler = nxt_http_proxy_error,
2431270Sigor@sysoev.ru };
2441270Sigor@sysoev.ru
2451270Sigor@sysoev.ru
2461270Sigor@sysoev.ru static void
nxt_http_proxy_header_read(nxt_task_t * task,void * obj,void * data)2471270Sigor@sysoev.ru nxt_http_proxy_header_read(nxt_task_t *task, void *obj, void *data)
2481270Sigor@sysoev.ru {
2491270Sigor@sysoev.ru nxt_http_peer_t *peer;
2501270Sigor@sysoev.ru nxt_http_field_t *f, *field;
2511270Sigor@sysoev.ru nxt_http_request_t *r;
2521270Sigor@sysoev.ru
2531270Sigor@sysoev.ru r = obj;
2541270Sigor@sysoev.ru peer = data;
2551270Sigor@sysoev.ru
2561270Sigor@sysoev.ru r->status = peer->status;
2571270Sigor@sysoev.ru
2581270Sigor@sysoev.ru nxt_debug(task, "http proxy status: %d", peer->status);
2591270Sigor@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
2781505Sigor@sysoev.ru r->state = &nxt_http_proxy_read_state;
2791505Sigor@sysoev.ru
2801270Sigor@sysoev.ru nxt_http_request_header_send(task, r, nxt_http_proxy_send_body, peer);
2811270Sigor@sysoev.ru }
2821270Sigor@sysoev.ru
2831270Sigor@sysoev.ru
2841589Sigor@sysoev.ru static const nxt_http_request_state_t nxt_http_proxy_read_state
2851589Sigor@sysoev.ru nxt_aligned(64) =
2861589Sigor@sysoev.ru {
2871589Sigor@sysoev.ru .ready_handler = nxt_http_proxy_send_body,
2881589Sigor@sysoev.ru .error_handler = nxt_http_proxy_error,
2891589Sigor@sysoev.ru };
2901589Sigor@sysoev.ru
2911589Sigor@sysoev.ru
2921270Sigor@sysoev.ru static void
nxt_http_proxy_send_body(nxt_task_t * task,void * obj,void * data)2931270Sigor@sysoev.ru nxt_http_proxy_send_body(nxt_task_t *task, void *obj, void *data)
2941270Sigor@sysoev.ru {
2951270Sigor@sysoev.ru nxt_buf_t *out;
2961270Sigor@sysoev.ru nxt_http_peer_t *peer;
2971270Sigor@sysoev.ru nxt_http_request_t *r;
2981270Sigor@sysoev.ru
2991270Sigor@sysoev.ru r = obj;
3001270Sigor@sysoev.ru peer = data;
3011270Sigor@sysoev.ru out = peer->body;
3021270Sigor@sysoev.ru
3031270Sigor@sysoev.ru if (out != NULL) {
3041270Sigor@sysoev.ru peer->body = NULL;
3051505Sigor@sysoev.ru nxt_http_request_send(task, r, out);
3061505Sigor@sysoev.ru }
3071270Sigor@sysoev.ru
3081505Sigor@sysoev.ru if (!peer->closed) {
3091270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_read(task, peer);
3101270Sigor@sysoev.ru
3111270Sigor@sysoev.ru } else {
3121270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_close(task, peer);
3131270Sigor@sysoev.ru
3141270Sigor@sysoev.ru nxt_mp_release(r->mem_pool);
3151270Sigor@sysoev.ru }
3161270Sigor@sysoev.ru }
3171270Sigor@sysoev.ru
3181270Sigor@sysoev.ru
3191270Sigor@sysoev.ru nxt_buf_t *
nxt_http_proxy_buf_mem_alloc(nxt_task_t * task,nxt_http_request_t * r,size_t size)3201270Sigor@sysoev.ru nxt_http_proxy_buf_mem_alloc(nxt_task_t *task, nxt_http_request_t *r,
3211270Sigor@sysoev.ru size_t size)
3221270Sigor@sysoev.ru {
3231270Sigor@sysoev.ru nxt_buf_t *b;
3241270Sigor@sysoev.ru
3251270Sigor@sysoev.ru b = nxt_event_engine_buf_mem_alloc(task->thread->engine, size);
3261270Sigor@sysoev.ru if (nxt_fast_path(b != NULL)) {
3271270Sigor@sysoev.ru b->completion_handler = nxt_http_proxy_buf_mem_completion;
3281270Sigor@sysoev.ru b->parent = r;
3291270Sigor@sysoev.ru nxt_mp_retain(r->mem_pool);
3301270Sigor@sysoev.ru
3311270Sigor@sysoev.ru } else {
3321270Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
3331270Sigor@sysoev.ru }
3341270Sigor@sysoev.ru
3351270Sigor@sysoev.ru return b;
3361270Sigor@sysoev.ru }
3371270Sigor@sysoev.ru
3381270Sigor@sysoev.ru
3391270Sigor@sysoev.ru static void
nxt_http_proxy_buf_mem_completion(nxt_task_t * task,void * obj,void * data)3401270Sigor@sysoev.ru nxt_http_proxy_buf_mem_completion(nxt_task_t *task, void *obj, void *data)
3411270Sigor@sysoev.ru {
3421270Sigor@sysoev.ru nxt_buf_t *b, *next;
3431270Sigor@sysoev.ru nxt_http_peer_t *peer;
3441270Sigor@sysoev.ru nxt_http_request_t *r;
3451270Sigor@sysoev.ru
3461270Sigor@sysoev.ru b = obj;
3471270Sigor@sysoev.ru r = data;
3481270Sigor@sysoev.ru
3491270Sigor@sysoev.ru peer = r->peer;
3501270Sigor@sysoev.ru
3511270Sigor@sysoev.ru do {
3521270Sigor@sysoev.ru next = b->next;
3531270Sigor@sysoev.ru
3541270Sigor@sysoev.ru nxt_http_proxy_buf_mem_free(task, r, b);
3551270Sigor@sysoev.ru
3561270Sigor@sysoev.ru b = next;
3571270Sigor@sysoev.ru } while (b != NULL);
3581270Sigor@sysoev.ru
3591270Sigor@sysoev.ru if (!peer->closed) {
3601270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_read(task, peer);
3611270Sigor@sysoev.ru }
3621270Sigor@sysoev.ru }
3631270Sigor@sysoev.ru
3641270Sigor@sysoev.ru
3651270Sigor@sysoev.ru void
nxt_http_proxy_buf_mem_free(nxt_task_t * task,nxt_http_request_t * r,nxt_buf_t * b)3661270Sigor@sysoev.ru nxt_http_proxy_buf_mem_free(nxt_task_t *task, nxt_http_request_t *r,
3671270Sigor@sysoev.ru nxt_buf_t *b)
3681270Sigor@sysoev.ru {
3691270Sigor@sysoev.ru nxt_event_engine_buf_mem_free(task->thread->engine, b);
3701270Sigor@sysoev.ru
3711270Sigor@sysoev.ru nxt_mp_release(r->mem_pool);
3721270Sigor@sysoev.ru }
3731270Sigor@sysoev.ru
3741270Sigor@sysoev.ru
3751270Sigor@sysoev.ru static void
nxt_http_proxy_error(nxt_task_t * task,void * obj,void * data)3761270Sigor@sysoev.ru nxt_http_proxy_error(nxt_task_t *task, void *obj, void *data)
3771270Sigor@sysoev.ru {
3781270Sigor@sysoev.ru nxt_http_peer_t *peer;
3791270Sigor@sysoev.ru nxt_http_request_t *r;
3801270Sigor@sysoev.ru
3811270Sigor@sysoev.ru r = obj;
3821270Sigor@sysoev.ru peer = r->peer;
3831270Sigor@sysoev.ru
3841270Sigor@sysoev.ru nxt_http_proto[peer->protocol].peer_close(task, peer);
3851270Sigor@sysoev.ru
3861270Sigor@sysoev.ru nxt_mp_release(r->mem_pool);
3871270Sigor@sysoev.ru
3881505Sigor@sysoev.ru nxt_http_request_error(&r->task, r, peer->status);
3891270Sigor@sysoev.ru }
3901270Sigor@sysoev.ru
3911270Sigor@sysoev.ru
3921270Sigor@sysoev.ru nxt_int_t
nxt_http_proxy_date(void * ctx,nxt_http_field_t * field,uintptr_t data)3931270Sigor@sysoev.ru nxt_http_proxy_date(void *ctx, nxt_http_field_t *field, uintptr_t data)
3941270Sigor@sysoev.ru {
3951270Sigor@sysoev.ru nxt_http_request_t *r;
3961270Sigor@sysoev.ru
3971270Sigor@sysoev.ru r = ctx;
3981270Sigor@sysoev.ru
3991270Sigor@sysoev.ru r->resp.date = field;
4001270Sigor@sysoev.ru
4011270Sigor@sysoev.ru return NXT_OK;
4021270Sigor@sysoev.ru }
4031270Sigor@sysoev.ru
4041270Sigor@sysoev.ru
4051270Sigor@sysoev.ru nxt_int_t
nxt_http_proxy_content_length(void * ctx,nxt_http_field_t * field,uintptr_t data)4061270Sigor@sysoev.ru nxt_http_proxy_content_length(void *ctx, nxt_http_field_t *field,
4071270Sigor@sysoev.ru uintptr_t data)
4081270Sigor@sysoev.ru {
4091270Sigor@sysoev.ru nxt_off_t n;
4101270Sigor@sysoev.ru nxt_http_request_t *r;
4111270Sigor@sysoev.ru
4121270Sigor@sysoev.ru r = ctx;
4131270Sigor@sysoev.ru
4141270Sigor@sysoev.ru r->resp.content_length = field;
4151270Sigor@sysoev.ru
4161270Sigor@sysoev.ru n = nxt_off_t_parse(field->value, field->value_length);
4171270Sigor@sysoev.ru
4181270Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) {
4191270Sigor@sysoev.ru r->resp.content_length_n = n;
4201270Sigor@sysoev.ru }
4211270Sigor@sysoev.ru
4221270Sigor@sysoev.ru return NXT_OK;
4231270Sigor@sysoev.ru }
4241270Sigor@sysoev.ru
4251270Sigor@sysoev.ru
4261270Sigor@sysoev.ru nxt_int_t
nxt_http_proxy_skip(void * ctx,nxt_http_field_t * field,uintptr_t data)4271270Sigor@sysoev.ru nxt_http_proxy_skip(void *ctx, nxt_http_field_t *field, uintptr_t data)
4281270Sigor@sysoev.ru {
4291270Sigor@sysoev.ru field->skip = 1;
4301270Sigor@sysoev.ru
4311270Sigor@sysoev.ru return NXT_OK;
4321270Sigor@sysoev.ru }
433