Added $request_port and $is_request_port variables.

The $request_port variable contains the port passed by the client in the
request line (for HTTP/1.x) or ":authority" pseudo-header (for HTTP/2 and
HTTP/3).  If the request line contains no host, or ":authority" is missing,
then $request_port is taken from the "Host" header, similar to the $host
variable.

The $is_request_port variable contains ":" if $request_port is non-empty,
and is empty otherwise.
This commit is contained in:
Roman Arutyunyan 2025-09-29 20:47:27 +04:00 committed by Roman Arutyunyan
parent 78d1ab5a2c
commit c8c7beb96f
6 changed files with 98 additions and 3 deletions

View File

@ -446,6 +446,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case sw_port: case sw_port:
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
if (r->port >= 6553 && (r->port > 6553 || (ch - '0') > 5)) {
return NGX_HTTP_PARSE_INVALID_REQUEST;
}
r->port = r->port * 10 + (ch - '0');
break; break;
} }

View File

@ -1846,8 +1846,9 @@ static ngx_int_t
ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset) ngx_uint_t offset)
{ {
ngx_int_t rc; u_char *p;
ngx_str_t host; ngx_int_t rc;
ngx_str_t host;
if (r->headers_in.host) { if (r->headers_in.host) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
@ -1888,6 +1889,17 @@ ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
r->headers_in.server = host; r->headers_in.server = host;
p = ngx_strlchr(h->value.data + host.len,
h->value.data + h->value.len, ':');
if (p) {
rc = ngx_atoi(p + 1, h->value.data + h->value.len - p - 1);
if (rc > 0 && rc < 65536) {
r->port = rc;
}
}
return NGX_OK; return NGX_OK;
} }

View File

@ -461,6 +461,8 @@ struct ngx_http_request_s {
ngx_http_cleanup_t *cleanup; ngx_http_cleanup_t *cleanup;
in_port_t port;
unsigned count:16; unsigned count:16;
unsigned subrequests:8; unsigned subrequests:8;
unsigned blocked:8; unsigned blocked:8;

View File

@ -71,6 +71,10 @@ static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data); ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r, static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data); ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_is_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static void ngx_http_variable_set_args(ngx_http_request_t *r, static void ngx_http_variable_set_args(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data); ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r, static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
@ -231,6 +235,12 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 }, { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 },
{ ngx_string("request_port"), NULL,
ngx_http_variable_request_port, 0, 0, 0 },
{ ngx_string("is_request_port"), NULL,
ngx_http_variable_is_request_port, 0, 0, 0 },
{ ngx_string("request_uri"), NULL, ngx_http_variable_request, { ngx_string("request_uri"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, unparsed_uri), 0, 0 }, offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
@ -1540,6 +1550,51 @@ ngx_http_variable_https(ngx_http_request_t *r,
} }
static ngx_int_t
ngx_http_variable_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_uint_t port;
v->len = 0;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
if (v->data == NULL) {
return NGX_ERROR;
}
port = r->port;
if (port > 0 && port < 65536) {
v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
}
return NGX_OK;
}
static ngx_int_t
ngx_http_variable_is_request_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
if (r->port == 0) {
*v = ngx_http_variable_null_value;
return NGX_OK;
}
v->len = 1;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = (u_char *) ":";
return NGX_OK;
}
static void static void
ngx_http_variable_set_args(ngx_http_request_t *r, ngx_http_variable_set_args(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data) ngx_http_variable_value_t *v, uintptr_t data)

View File

@ -3518,7 +3518,8 @@ ngx_http_v2_parse_scheme(ngx_http_request_t *r, ngx_str_t *value)
static ngx_int_t static ngx_int_t
ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
{ {
ngx_int_t rc; u_char *p;
ngx_int_t rc;
if (r->host_start) { if (r->host_start) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
@ -3552,6 +3553,16 @@ ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
r->headers_in.server = *value; r->headers_in.server = *value;
p = ngx_strlchr(r->host_start + value->len, r->host_end, ':');
if (p) {
rc = ngx_atoi(p + 1, r->host_end - p - 1);
if (rc > 0 && rc < 65536) {
r->port = rc;
}
}
return NGX_OK; return NGX_OK;
} }

View File

@ -979,6 +979,16 @@ ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r)
} }
r->headers_in.server = host; r->headers_in.server = host;
p = ngx_strlchr(r->host_start + host.len, r->host_end, ':');
if (p) {
rc = ngx_atoi(p + 1, r->host_end - p - 1);
if (rc > 0 && rc < 65536) {
r->port = rc;
}
}
} }
if (ngx_list_init(&r->headers_in.headers, r->pool, 20, if (ngx_list_init(&r->headers_in.headers, r->pool, 20,