From a4dbee147cc13c9eef1f6cb209b4651a1419d17d Mon Sep 17 00:00:00 2001 From: Zhidao HONG Date: Wed, 10 Apr 2024 14:00:39 +0800 Subject: HTTP: Rewrote url target section in nxt_h1p_peer_header_send() Previously, proxy request was constructed based on the `r->target` field. However, r->target will remain unchanged in the future, even in cases of URL rewriting because of the requirement change for $request_uri that will be changed to constant. To accommodate this, the r->target should be designed to be constant, but Unit needs to pass a changeable URL to the upstream server. Based on the above, the proxy module can't depend on r->target. --- src/nxt_h1proto.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++---- src/nxt_http.h | 2 ++ src/nxt_http_rewrite.c | 3 ++ 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 1dfe4b6e..c3a65679 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -90,6 +90,8 @@ static void nxt_h1p_peer_connect(nxt_task_t *task, nxt_http_peer_t *peer); static void nxt_h1p_peer_connected(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_refused(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer); +static nxt_int_t nxt_h1p_peer_request_target(nxt_http_request_t *r, + nxt_str_t *target); static void nxt_h1p_peer_header_sent(nxt_task_t *task, void *obj, void *data); static void nxt_h1p_peer_header_read(nxt_task_t *task, nxt_http_peer_t *peer); static ssize_t nxt_h1p_peer_io_read_handler(nxt_task_t *task, nxt_conn_t *c); @@ -654,6 +656,8 @@ nxt_h1p_header_process(nxt_task_t *task, nxt_h1proto_t *h1p, r->target.start = h1p->parser.target_start; r->target.length = h1p->parser.target_end - h1p->parser.target_start; + r->quoted_target = h1p->parser.quoted_target; + if (h1p->parser.version.ui64 != 0) { r->version.start = h1p->parser.version.str; r->version.length = sizeof(h1p->parser.version.str); @@ -2263,6 +2267,8 @@ nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) { u_char *p; size_t size; + nxt_int_t ret; + nxt_str_t target; nxt_buf_t *header, *body; nxt_conn_t *c; nxt_http_field_t *field; @@ -2272,7 +2278,12 @@ nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) r = peer->request; - size = r->method->length + sizeof(" ") + r->target.length + ret = nxt_h1p_peer_request_target(r, &target); + if (nxt_slow_path(ret != NXT_OK)) { + goto fail; + } + + size = r->method->length + sizeof(" ") + target.length + sizeof(" HTTP/1.1\r\n") + sizeof("Connection: close\r\n") + sizeof("\r\n"); @@ -2288,8 +2299,7 @@ nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) header = nxt_http_buf_mem(task, r, size); if (nxt_slow_path(header == NULL)) { - r->state->error_handler(task, r, peer); - return; + goto fail; } p = header->mem.free; @@ -2328,8 +2338,7 @@ nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) } if (nxt_slow_path(body == NULL)) { - r->state->error_handler(task, r, peer); - return; + goto fail; } header->next = body; @@ -2353,6 +2362,61 @@ nxt_h1p_peer_header_send(nxt_task_t *task, nxt_http_peer_t *peer) } nxt_conn_write(task->thread->engine, c); + + return; + +fail: + + r->state->error_handler(task, r, peer); +} + + +static nxt_int_t +nxt_h1p_peer_request_target(nxt_http_request_t *r, nxt_str_t *target) +{ + u_char *p; + size_t size, encode; + + if (!r->uri_changed) { + *target = r->target; + return NXT_OK; + } + + if (!r->quoted_target && r->args->length == 0) { + *target = *r->path; + return NXT_OK; + } + + if (r->quoted_target) { + encode = nxt_encode_complex_uri(NULL, r->path->start, + r->path->length); + } else { + encode = 0; + } + + size = r->path->length + encode * 2 + 1 + r->args->length; + + target->start = nxt_mp_nget(r->mem_pool, size); + if (target->start == NULL) { + return NXT_ERROR; + } + + if (r->quoted_target) { + p = (u_char *) nxt_encode_complex_uri(target->start, r->path->start, + r->path->length); + + } else { + p = nxt_cpymem(target->start, r->path->start, r->path->length); + } + + if (r->args->length > 0) { + *p++ = '?'; + p = nxt_cpymem(p, r->args->start, r->args->length); + } + + target->length = p - target->start; + + return NXT_OK; } diff --git a/src/nxt_http.h b/src/nxt_http.h index e812bd0d..23d86b91 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -192,6 +192,8 @@ struct nxt_http_request_s { nxt_http_status_t status:16; uint8_t log_route; /* 1 bit */ + uint8_t quoted_target; /* 1 bit */ + uint8_t uri_changed; /* 1 bit */ uint8_t pass_count; /* 8 bits */ uint8_t app_target; diff --git a/src/nxt_http_rewrite.c b/src/nxt_http_rewrite.c index fb216eeb..ff465ecc 100644 --- a/src/nxt_http_rewrite.c +++ b/src/nxt_http_rewrite.c @@ -103,6 +103,9 @@ nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r) *r->path = rp.path; + r->uri_changed = 1; + r->quoted_target = rp.quoted_target; + if (nxt_slow_path(r->log_route)) { nxt_log(task, NXT_LOG_NOTICE, "URI rewritten to \"%V\"", &r->target); } -- cgit