mirror of
https://github.com/nginx/nginx.git
synced 2025-06-08 02:02:38 +08:00
HTTP CONNECT proxy.
HTTP CONNECT method is now supported in HTTP/1 connections. It's disabled in all currently existing standard modules. A new variable $port is added that contains the port passed by client in HTTP CONNECT. The $host variable contains the host part. A new module ngx_http_tunnel module is added which establishes a tunnel to a backend. It supports the newly added HTTP CONNECT method and can be used to set up an HTTP CONNECT proxy. As recommended by RFC 9110, proxy target should be restricted to ensure safe proxying: : Proxies that support CONNECT SHOULD restrict its use to a limited set : of known ports or a configurable list of safe request targets. Example config: server { listen 8000; resolver dns.example.com; map $port $tun_port { 80 1; 443 1; } map $host $tun_host { hostnames; example.com 1; *.example.org 1; } map $tun_port$tun_host $tun { 11 $host:$port; } location / { tunnel_pass $tun; } } Request: $ curl -px 127.0.0.1:8000 http://example.com
This commit is contained in:
parent
6a134dfd48
commit
d76e3d3016
11
auto/modules
11
auto/modules
@ -781,6 +781,17 @@ if [ $HTTP = YES ]; then
|
|||||||
. auto/module
|
. auto/module
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $HTTP_TUNNEL = YES ]; then
|
||||||
|
ngx_module_name=ngx_http_tunnel_module
|
||||||
|
ngx_module_incs=
|
||||||
|
ngx_module_deps=
|
||||||
|
ngx_module_srcs=src/http/modules/ngx_http_tunnel_module.c
|
||||||
|
ngx_module_libs=
|
||||||
|
ngx_module_link=$HTTP_TUNNEL
|
||||||
|
|
||||||
|
. auto/module
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $HTTP_PERL != NO ]; then
|
if [ $HTTP_PERL != NO ]; then
|
||||||
ngx_module_name=ngx_http_perl_module
|
ngx_module_name=ngx_http_perl_module
|
||||||
ngx_module_incs=src/http/modules/perl
|
ngx_module_incs=src/http/modules/perl
|
||||||
|
@ -89,6 +89,7 @@ HTTP_FASTCGI=YES
|
|||||||
HTTP_UWSGI=YES
|
HTTP_UWSGI=YES
|
||||||
HTTP_SCGI=YES
|
HTTP_SCGI=YES
|
||||||
HTTP_GRPC=YES
|
HTTP_GRPC=YES
|
||||||
|
HTTP_TUNNEL=YES
|
||||||
HTTP_PERL=NO
|
HTTP_PERL=NO
|
||||||
HTTP_MEMCACHED=YES
|
HTTP_MEMCACHED=YES
|
||||||
HTTP_LIMIT_CONN=YES
|
HTTP_LIMIT_CONN=YES
|
||||||
@ -279,6 +280,7 @@ $0: warning: the \"--with-ipv6\" option is deprecated"
|
|||||||
--without-http_uwsgi_module) HTTP_UWSGI=NO ;;
|
--without-http_uwsgi_module) HTTP_UWSGI=NO ;;
|
||||||
--without-http_scgi_module) HTTP_SCGI=NO ;;
|
--without-http_scgi_module) HTTP_SCGI=NO ;;
|
||||||
--without-http_grpc_module) HTTP_GRPC=NO ;;
|
--without-http_grpc_module) HTTP_GRPC=NO ;;
|
||||||
|
--without-http_tunnel_module) HTTP_TUNNEL=NO ;;
|
||||||
--without-http_memcached_module) HTTP_MEMCACHED=NO ;;
|
--without-http_memcached_module) HTTP_MEMCACHED=NO ;;
|
||||||
--without-http_limit_conn_module) HTTP_LIMIT_CONN=NO ;;
|
--without-http_limit_conn_module) HTTP_LIMIT_CONN=NO ;;
|
||||||
--without-http_limit_req_module) HTTP_LIMIT_REQ=NO ;;
|
--without-http_limit_req_module) HTTP_LIMIT_REQ=NO ;;
|
||||||
|
@ -71,6 +71,13 @@ ngx_http_chunked_header_filter(ngx_http_request_t *r)
|
|||||||
return ngx_http_next_header_filter(r);
|
return ngx_http_next_header_filter(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r->method == NGX_HTTP_CONNECT
|
||||||
|
&& r->headers_out.status >= NGX_HTTP_OK
|
||||||
|
&& r->headers_out.status < NGX_HTTP_SPECIAL_RESPONSE)
|
||||||
|
{
|
||||||
|
return ngx_http_next_header_filter(r);
|
||||||
|
}
|
||||||
|
|
||||||
if (r->headers_out.content_length_n == -1
|
if (r->headers_out.content_length_n == -1
|
||||||
|| r->expect_trailers)
|
|| r->expect_trailers)
|
||||||
{
|
{
|
||||||
|
@ -688,6 +688,10 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
|
|||||||
ngx_http_fastcgi_main_conf_t *fmcf;
|
ngx_http_fastcgi_main_conf_t *fmcf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (r->method == NGX_HTTP_CONNECT) {
|
||||||
|
return NGX_HTTP_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_http_upstream_create(r) != NGX_OK) {
|
if (ngx_http_upstream_create(r) != NGX_OK) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -552,6 +552,10 @@ ngx_http_grpc_handler(ngx_http_request_t *r)
|
|||||||
ngx_http_grpc_ctx_t *ctx;
|
ngx_http_grpc_ctx_t *ctx;
|
||||||
ngx_http_grpc_loc_conf_t *glcf;
|
ngx_http_grpc_loc_conf_t *glcf;
|
||||||
|
|
||||||
|
if (r->method == NGX_HTTP_CONNECT) {
|
||||||
|
return NGX_HTTP_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_http_upstream_create(r) != NGX_OK) {
|
if (ngx_http_upstream_create(r) != NGX_OK) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -485,6 +485,10 @@ ngx_http_scgi_handler(ngx_http_request_t *r)
|
|||||||
ngx_http_scgi_main_conf_t *smcf;
|
ngx_http_scgi_main_conf_t *smcf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (r->method == NGX_HTTP_CONNECT) {
|
||||||
|
return NGX_HTTP_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_http_upstream_create(r) != NGX_OK) {
|
if (ngx_http_upstream_create(r) != NGX_OK) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
513
src/http/modules/ngx_http_tunnel_module.c
Normal file
513
src/http/modules/ngx_http_tunnel_module.c
Normal file
@ -0,0 +1,513 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Roman Arutyunyan
|
||||||
|
* Copyright (C) Nginx, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_core.h>
|
||||||
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_http_upstream_conf_t upstream;
|
||||||
|
|
||||||
|
ngx_array_t *tunnel_lengths;
|
||||||
|
ngx_array_t *tunnel_values;
|
||||||
|
} ngx_http_tunnel_loc_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_tunnel_eval(ngx_http_request_t *r,
|
||||||
|
ngx_http_tunnel_loc_conf_t *tlcf);
|
||||||
|
static ngx_int_t ngx_http_tunnel_create_request(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_tunnel_reinit_request(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_tunnel_process_header(ngx_http_request_t *r);
|
||||||
|
static void ngx_http_tunnel_abort_request(ngx_http_request_t *r);
|
||||||
|
static void ngx_http_tunnel_finalize_request(ngx_http_request_t *r,
|
||||||
|
ngx_int_t rc);
|
||||||
|
|
||||||
|
static void *ngx_http_tunnel_create_loc_conf(ngx_conf_t *cf);
|
||||||
|
static char *ngx_http_tunnel_merge_loc_conf(ngx_conf_t *cf,
|
||||||
|
void *parent, void *child);
|
||||||
|
|
||||||
|
static char *ngx_http_tunnel_pass(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
|
void *conf);
|
||||||
|
|
||||||
|
static char *ngx_http_tunnel_lowat_check(ngx_conf_t *cf, void *post, void *data);
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_conf_post_t ngx_http_tunnel_lowat_post =
|
||||||
|
{ ngx_http_tunnel_lowat_check };
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_conf_bitmask_t ngx_http_tunnel_next_upstream_masks[] = {
|
||||||
|
{ ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
|
||||||
|
{ ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
|
||||||
|
{ ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
|
||||||
|
{ ngx_null_string, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_module_t ngx_http_tunnel_module;
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_command_t ngx_http_tunnel_commands[] = {
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_pass"),
|
||||||
|
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_http_tunnel_pass,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_bind"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
|
||||||
|
ngx_http_upstream_bind_set_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.local),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_socket_keepalive"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||||
|
ngx_conf_set_flag_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.socket_keepalive),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_connect_timeout"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_msec_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.connect_timeout),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_send_timeout"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_msec_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.send_timeout),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_send_lowat"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_size_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.send_lowat),
|
||||||
|
&ngx_http_tunnel_lowat_post },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_buffer_size"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_size_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.buffer_size),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_read_timeout"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_msec_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.read_timeout),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_next_upstream"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
|
||||||
|
ngx_conf_set_bitmask_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.next_upstream),
|
||||||
|
&ngx_http_tunnel_next_upstream_masks },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_next_upstream_tries"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_num_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.next_upstream_tries),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("tunnel_next_upstream_timeout"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_msec_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_tunnel_loc_conf_t, upstream.next_upstream_timeout),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
ngx_null_command
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_module_t ngx_http_tunnel_module_ctx = {
|
||||||
|
NULL, /* preconfiguration */
|
||||||
|
NULL, /* postconfiguration */
|
||||||
|
|
||||||
|
NULL, /* create main configuration */
|
||||||
|
NULL, /* init main configuration */
|
||||||
|
|
||||||
|
NULL, /* create server configuration */
|
||||||
|
NULL, /* merge server configuration */
|
||||||
|
|
||||||
|
ngx_http_tunnel_create_loc_conf, /* create location configuration */
|
||||||
|
ngx_http_tunnel_merge_loc_conf /* merge location configuration */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_module_t ngx_http_tunnel_module = {
|
||||||
|
NGX_MODULE_V1,
|
||||||
|
&ngx_http_tunnel_module_ctx, /* module context */
|
||||||
|
ngx_http_tunnel_commands, /* module directives */
|
||||||
|
NGX_HTTP_MODULE, /* module type */
|
||||||
|
NULL, /* init master */
|
||||||
|
NULL, /* init module */
|
||||||
|
NULL, /* init process */
|
||||||
|
NULL, /* init thread */
|
||||||
|
NULL, /* exit thread */
|
||||||
|
NULL, /* exit process */
|
||||||
|
NULL, /* exit master */
|
||||||
|
NGX_MODULE_V1_PADDING
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_tunnel_handler(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
ngx_http_tunnel_loc_conf_t *tlcf;
|
||||||
|
|
||||||
|
if (r->method != NGX_HTTP_CONNECT) {
|
||||||
|
return NGX_HTTP_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_upstream_create(r) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
tlcf = ngx_http_get_module_loc_conf(r, ngx_http_tunnel_module);
|
||||||
|
|
||||||
|
if (tlcf->tunnel_lengths) {
|
||||||
|
if (ngx_http_tunnel_eval(r, tlcf) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
u->conf = &tlcf->upstream;
|
||||||
|
|
||||||
|
u->create_request = ngx_http_tunnel_create_request;
|
||||||
|
u->reinit_request = ngx_http_tunnel_reinit_request;
|
||||||
|
u->process_header = ngx_http_tunnel_process_header;
|
||||||
|
u->abort_request = ngx_http_tunnel_abort_request;
|
||||||
|
u->finalize_request = ngx_http_tunnel_finalize_request;
|
||||||
|
r->state = 0;
|
||||||
|
|
||||||
|
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
|
||||||
|
|
||||||
|
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_tunnel_eval(ngx_http_request_t *r, ngx_http_tunnel_loc_conf_t *tlcf)
|
||||||
|
{
|
||||||
|
ngx_url_t url;
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
|
||||||
|
ngx_memzero(&url, sizeof(ngx_url_t));
|
||||||
|
|
||||||
|
if (ngx_http_script_run(r, &url.url, tlcf->tunnel_lengths->elts, 0,
|
||||||
|
tlcf->tunnel_values->elts)
|
||||||
|
== NULL)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
url.no_resolve = 1;
|
||||||
|
|
||||||
|
if (ngx_parse_url(r->pool, &url) != NGX_OK) {
|
||||||
|
if (url.err) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"%s in upstream \"%V\"", url.err, &url.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
|
||||||
|
if (u->resolved == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.addrs) {
|
||||||
|
u->resolved->sockaddr = url.addrs[0].sockaddr;
|
||||||
|
u->resolved->socklen = url.addrs[0].socklen;
|
||||||
|
u->resolved->name = url.addrs[0].name;
|
||||||
|
u->resolved->naddrs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u->resolved->host = url.host;
|
||||||
|
u->resolved->port = url.port;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_tunnel_create_request(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
/* u->request_bufs = NULL */
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_tunnel_reinit_request(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
r->state = 0;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_tunnel_process_header(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
u->headers_in.status_n = NGX_HTTP_OK;
|
||||||
|
ngx_str_set(&u->headers_in.status_line, "200 OK");
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http tunnel status %ui \"%V\"",
|
||||||
|
u->headers_in.status_n, &u->headers_in.status_line);
|
||||||
|
|
||||||
|
u->keepalive = 0;
|
||||||
|
u->upgrade = 1;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_http_tunnel_abort_request(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"abort http tunnel request");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_http_tunnel_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
|
||||||
|
{
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"finalize http tunnel request");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
ngx_http_tunnel_create_loc_conf(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_tunnel_loc_conf_t *conf;
|
||||||
|
|
||||||
|
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_tunnel_loc_conf_t));
|
||||||
|
if (conf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set by ngx_pcalloc():
|
||||||
|
*
|
||||||
|
* conf->upstream.next_upstream = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
|
||||||
|
|
||||||
|
conf->upstream.local = NGX_CONF_UNSET_PTR;
|
||||||
|
conf->upstream.socket_keepalive = NGX_CONF_UNSET;
|
||||||
|
|
||||||
|
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
|
||||||
|
conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
|
||||||
|
conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
|
||||||
|
conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
|
||||||
|
|
||||||
|
conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
|
||||||
|
conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
|
||||||
|
|
||||||
|
conf->upstream.ignore_input = 1;
|
||||||
|
|
||||||
|
ngx_str_set(&conf->upstream.module, "tunnel");
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_tunnel_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
|
{
|
||||||
|
ngx_http_tunnel_loc_conf_t *prev = parent;
|
||||||
|
ngx_http_tunnel_loc_conf_t *conf = child;
|
||||||
|
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
|
||||||
|
ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
|
||||||
|
prev->upstream.next_upstream_tries, 0);
|
||||||
|
|
||||||
|
ngx_conf_merge_ptr_value(conf->upstream.local,
|
||||||
|
prev->upstream.local, NULL);
|
||||||
|
|
||||||
|
ngx_conf_merge_value(conf->upstream.socket_keepalive,
|
||||||
|
prev->upstream.socket_keepalive, 0);
|
||||||
|
|
||||||
|
ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
|
||||||
|
prev->upstream.connect_timeout, 60000);
|
||||||
|
|
||||||
|
ngx_conf_merge_msec_value(conf->upstream.send_timeout,
|
||||||
|
prev->upstream.send_timeout, 60000);
|
||||||
|
|
||||||
|
ngx_conf_merge_msec_value(conf->upstream.read_timeout,
|
||||||
|
prev->upstream.read_timeout, 60000);
|
||||||
|
|
||||||
|
ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
|
||||||
|
prev->upstream.next_upstream_timeout, 0);
|
||||||
|
|
||||||
|
ngx_conf_merge_size_value(conf->upstream.send_lowat,
|
||||||
|
prev->upstream.send_lowat, 0);
|
||||||
|
|
||||||
|
ngx_conf_merge_size_value(conf->upstream.buffer_size,
|
||||||
|
prev->upstream.buffer_size,
|
||||||
|
(size_t) ngx_pagesize);
|
||||||
|
|
||||||
|
ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
|
||||||
|
prev->upstream.next_upstream,
|
||||||
|
(NGX_CONF_BITMASK_SET
|
||||||
|
|NGX_HTTP_UPSTREAM_FT_ERROR
|
||||||
|
|NGX_HTTP_UPSTREAM_FT_TIMEOUT));
|
||||||
|
|
||||||
|
if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
|
||||||
|
conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
|
||||||
|
|NGX_HTTP_UPSTREAM_FT_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
|
||||||
|
|
||||||
|
if (clcf->noname
|
||||||
|
&& conf->upstream.upstream == NULL && conf->tunnel_lengths == NULL)
|
||||||
|
{
|
||||||
|
conf->upstream.upstream = prev->upstream.upstream;
|
||||||
|
|
||||||
|
conf->tunnel_lengths = prev->tunnel_lengths;
|
||||||
|
conf->tunnel_values = prev->tunnel_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clcf->lmt_excpt && clcf->handler == NULL
|
||||||
|
&& (conf->upstream.upstream || conf->tunnel_lengths))
|
||||||
|
{
|
||||||
|
clcf->handler = ngx_http_tunnel_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_tunnel_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
ngx_http_tunnel_loc_conf_t *tlcf = conf;
|
||||||
|
|
||||||
|
ngx_url_t u;
|
||||||
|
ngx_str_t *value, *url;
|
||||||
|
ngx_uint_t n;
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
ngx_http_script_compile_t sc;
|
||||||
|
|
||||||
|
if (tlcf->upstream.upstream || tlcf->tunnel_lengths) {
|
||||||
|
return "is duplicate";
|
||||||
|
}
|
||||||
|
|
||||||
|
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
|
||||||
|
|
||||||
|
clcf->handler = ngx_http_tunnel_handler;
|
||||||
|
|
||||||
|
if (clcf->name.len && clcf->name.data[clcf->name.len - 1] == '/') {
|
||||||
|
clcf->auto_redirect = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = cf->args->elts;
|
||||||
|
|
||||||
|
url = &value[1];
|
||||||
|
|
||||||
|
n = ngx_http_script_variables_count(url);
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
|
||||||
|
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
|
||||||
|
|
||||||
|
sc.cf = cf;
|
||||||
|
sc.source = url;
|
||||||
|
sc.lengths = &tlcf->tunnel_lengths;
|
||||||
|
sc.values = &tlcf->tunnel_values;
|
||||||
|
sc.variables = n;
|
||||||
|
sc.complete_lengths = 1;
|
||||||
|
sc.complete_values = 1;
|
||||||
|
|
||||||
|
if (ngx_http_script_compile(&sc) != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||||
|
|
||||||
|
u.url = *url;
|
||||||
|
u.no_resolve = 1;
|
||||||
|
|
||||||
|
tlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
|
||||||
|
if (tlcf->upstream.upstream == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_tunnel_lowat_check(ngx_conf_t *cf, void *post, void *data)
|
||||||
|
{
|
||||||
|
#if (NGX_FREEBSD)
|
||||||
|
ssize_t *np = data;
|
||||||
|
|
||||||
|
if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"\"tunnel_send_lowat\" must be less than %d "
|
||||||
|
"(sysctl net.inet.tcp.sendspace)",
|
||||||
|
ngx_freebsd_net_inet_tcp_sendspace);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif !(NGX_HAVE_SO_SNDLOWAT)
|
||||||
|
ssize_t *np = data;
|
||||||
|
|
||||||
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
|
"\"tunnel_send_lowat\" is not supported, ignored");
|
||||||
|
|
||||||
|
*np = 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
@ -661,6 +661,10 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
|
|||||||
ngx_http_uwsgi_main_conf_t *uwmcf;
|
ngx_http_uwsgi_main_conf_t *uwmcf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (r->method == NGX_HTTP_CONNECT) {
|
||||||
|
return NGX_HTTP_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_http_upstream_create(r) != NGX_OK) {
|
if (ngx_http_upstream_create(r) != NGX_OK) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -4615,6 +4615,7 @@ static ngx_http_method_name_t ngx_methods_names[] = {
|
|||||||
{ (u_char *) "LOCK", (uint32_t) ~NGX_HTTP_LOCK },
|
{ (u_char *) "LOCK", (uint32_t) ~NGX_HTTP_LOCK },
|
||||||
{ (u_char *) "UNLOCK", (uint32_t) ~NGX_HTTP_UNLOCK },
|
{ (u_char *) "UNLOCK", (uint32_t) ~NGX_HTTP_UNLOCK },
|
||||||
{ (u_char *) "PATCH", (uint32_t) ~NGX_HTTP_PATCH },
|
{ (u_char *) "PATCH", (uint32_t) ~NGX_HTTP_PATCH },
|
||||||
|
{ (u_char *) "CONNECT", (uint32_t) ~NGX_HTTP_CONNECT },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -116,6 +116,13 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
sw_host_end,
|
sw_host_end,
|
||||||
sw_host_ip_literal,
|
sw_host_ip_literal,
|
||||||
sw_port,
|
sw_port,
|
||||||
|
sw_spaces_before_connect_host,
|
||||||
|
sw_connect_host_start,
|
||||||
|
sw_connect_host,
|
||||||
|
sw_connect_host_end,
|
||||||
|
sw_connect_port_start,
|
||||||
|
sw_connect_port,
|
||||||
|
sw_connect_host_ip_literal,
|
||||||
sw_after_slash_in_uri,
|
sw_after_slash_in_uri,
|
||||||
sw_check_uri,
|
sw_check_uri,
|
||||||
sw_uri,
|
sw_uri,
|
||||||
@ -158,6 +165,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
if (ch == ' ') {
|
if (ch == ' ') {
|
||||||
r->method_end = p - 1;
|
r->method_end = p - 1;
|
||||||
m = r->request_start;
|
m = r->request_start;
|
||||||
|
state = sw_spaces_before_uri;
|
||||||
|
|
||||||
switch (p - m) {
|
switch (p - m) {
|
||||||
|
|
||||||
@ -247,6 +255,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' '))
|
if (ngx_str7_cmp(m, 'C', 'O', 'N', 'N', 'E', 'C', 'T', ' '))
|
||||||
{
|
{
|
||||||
r->method = NGX_HTTP_CONNECT;
|
r->method = NGX_HTTP_CONNECT;
|
||||||
|
state = sw_spaces_before_connect_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -269,7 +278,6 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = sw_spaces_before_uri;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,6 +638,117 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sw_spaces_before_connect_host:
|
||||||
|
|
||||||
|
if (ch == ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case sw_connect_host_start:
|
||||||
|
|
||||||
|
r->host_start = p;
|
||||||
|
|
||||||
|
if (ch == '[') {
|
||||||
|
state = sw_connect_host_ip_literal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = sw_connect_host;
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case sw_connect_host:
|
||||||
|
|
||||||
|
c = (u_char) (ch | 0x20);
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case sw_connect_host_end:
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case ':':
|
||||||
|
r->host_end = p;
|
||||||
|
state = sw_connect_port_start;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sw_connect_port_start:
|
||||||
|
|
||||||
|
r->port_start = p;
|
||||||
|
state = sw_connect_port;
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case sw_connect_port:
|
||||||
|
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->port_end = p;
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case ' ':
|
||||||
|
state = sw_http_09;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sw_connect_host_ip_literal:
|
||||||
|
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = (u_char) (ch | 0x20);
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case ':':
|
||||||
|
break;
|
||||||
|
case ']':
|
||||||
|
state = sw_connect_host_end;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
case '.':
|
||||||
|
case '_':
|
||||||
|
case '~':
|
||||||
|
/* unreserved */
|
||||||
|
break;
|
||||||
|
case '!':
|
||||||
|
case '$':
|
||||||
|
case '&':
|
||||||
|
case '\'':
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '*':
|
||||||
|
case '+':
|
||||||
|
case ',':
|
||||||
|
case ';':
|
||||||
|
case '=':
|
||||||
|
/* sub-delims */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
/* space+ after URI */
|
/* space+ after URI */
|
||||||
case sw_http_09:
|
case sw_http_09:
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
@ -1192,6 +1192,20 @@ ngx_http_process_request_line(ngx_event_t *rev)
|
|||||||
r->headers_in.server = host;
|
r->headers_in.server = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r->port_end) {
|
||||||
|
rc = ngx_atoi(r->port_start, r->port_end - r->port_start);
|
||||||
|
|
||||||
|
if (rc < 1 || rc > 65535) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
|
"client sent invalid port in request line");
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->headers_in.port.len = r->port_end - r->port_start;
|
||||||
|
r->headers_in.port.data = r->port_start;
|
||||||
|
}
|
||||||
|
|
||||||
if (r->http_version < NGX_HTTP_VERSION_10) {
|
if (r->http_version < NGX_HTTP_VERSION_10) {
|
||||||
|
|
||||||
if (r->headers_in.server.len == 0
|
if (r->headers_in.server.len == 0
|
||||||
@ -1271,6 +1285,11 @@ ngx_http_process_request_uri(ngx_http_request_t *r)
|
|||||||
{
|
{
|
||||||
ngx_http_core_srv_conf_t *cscf;
|
ngx_http_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
|
if (r->uri_end == NULL) {
|
||||||
|
r->uri_start = (u_char *) "/";
|
||||||
|
r->uri_end = r->uri_start + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (r->args_start) {
|
if (r->args_start) {
|
||||||
r->uri.len = r->args_start - 1 - r->uri_start;
|
r->uri.len = r->args_start - 1 - r->uri_start;
|
||||||
} else {
|
} else {
|
||||||
@ -1768,6 +1787,13 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r->port_end) {
|
||||||
|
r->port_start = new + (r->port_start - old);
|
||||||
|
if (r->port_end) {
|
||||||
|
r->port_end = new + (r->port_end - old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (r->uri_ext) {
|
if (r->uri_ext) {
|
||||||
r->uri_ext = new + (r->uri_ext - old);
|
r->uri_ext = new + (r->uri_ext - old);
|
||||||
}
|
}
|
||||||
@ -2055,13 +2081,6 @@ ngx_http_process_request_header(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->method == NGX_HTTP_CONNECT) {
|
|
||||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
|
||||||
"client sent CONNECT method");
|
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r->method == NGX_HTTP_TRACE) {
|
if (r->method == NGX_HTTP_TRACE) {
|
||||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
"client sent TRACE method");
|
"client sent TRACE method");
|
||||||
|
@ -238,6 +238,7 @@ typedef struct {
|
|||||||
ngx_str_t passwd;
|
ngx_str_t passwd;
|
||||||
|
|
||||||
ngx_str_t server;
|
ngx_str_t server;
|
||||||
|
ngx_str_t port;
|
||||||
off_t content_length_n;
|
off_t content_length_n;
|
||||||
time_t keep_alive_n;
|
time_t keep_alive_n;
|
||||||
|
|
||||||
@ -600,6 +601,8 @@ struct ngx_http_request_s {
|
|||||||
u_char *schema_end;
|
u_char *schema_end;
|
||||||
u_char *host_start;
|
u_char *host_start;
|
||||||
u_char *host_end;
|
u_char *host_end;
|
||||||
|
u_char *port_start;
|
||||||
|
u_char *port_end;
|
||||||
|
|
||||||
unsigned http_minor:16;
|
unsigned http_minor:16;
|
||||||
unsigned http_major:16;
|
unsigned http_major:16;
|
||||||
|
@ -2221,6 +2221,11 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (u->conf->ignore_input) {
|
||||||
|
ngx_http_upstream_process_header(r, u);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ngx_add_timer(c->read, u->conf->read_timeout);
|
ngx_add_timer(c->read, u->conf->read_timeout);
|
||||||
|
|
||||||
if (c->read->ready) {
|
if (c->read->ready) {
|
||||||
@ -2476,6 +2481,11 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (u->conf->ignore_input) {
|
||||||
|
rc = u->process_header(r);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
|
|
||||||
n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
|
n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
|
||||||
@ -2533,6 +2543,8 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
|
if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
|
||||||
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
|
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
|
||||||
return;
|
return;
|
||||||
|
@ -234,6 +234,7 @@ typedef struct {
|
|||||||
unsigned intercept_404:1;
|
unsigned intercept_404:1;
|
||||||
unsigned change_buffering:1;
|
unsigned change_buffering:1;
|
||||||
unsigned preserve_output:1;
|
unsigned preserve_output:1;
|
||||||
|
unsigned ignore_input:1;
|
||||||
|
|
||||||
#if (NGX_HTTP_SSL || NGX_COMPAT)
|
#if (NGX_HTTP_SSL || NGX_COMPAT)
|
||||||
ngx_ssl_t *ssl;
|
ngx_ssl_t *ssl;
|
||||||
|
@ -51,6 +51,8 @@ static ngx_int_t ngx_http_variable_content_length(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_host(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_variable_host(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_port(ngx_http_request_t *r,
|
||||||
|
ngx_http_variable_value_t *v, uintptr_t data);
|
||||||
static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_variable_binary_remote_addr(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_remote_addr(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
|
||||||
@ -192,6 +194,7 @@ static ngx_http_variable_t ngx_http_core_variables[] = {
|
|||||||
offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },
|
offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },
|
{ ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },
|
||||||
|
{ ngx_string("port"), NULL, ngx_http_variable_port, 0, 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("binary_remote_addr"), NULL,
|
{ ngx_string("binary_remote_addr"), NULL,
|
||||||
ngx_http_variable_binary_remote_addr, 0, 0, 0 },
|
ngx_http_variable_binary_remote_addr, 0, 0, 0 },
|
||||||
@ -1244,6 +1247,20 @@ ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_variable_port(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||||
|
uintptr_t data)
|
||||||
|
{
|
||||||
|
v->len = r->headers_in.port.len;
|
||||||
|
v->valid = 1;
|
||||||
|
v->no_cacheable = 0;
|
||||||
|
v->not_found = 0;
|
||||||
|
v->data = r->headers_in.port.data;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
|
ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
|
||||||
ngx_http_variable_value_t *v, uintptr_t data)
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
|
Loading…
Reference in New Issue
Block a user