mirror of
https://github.com/nginx/nginx.git
synced 2025-08-05 22:26:15 +08:00
Merged with the default branch.
This commit is contained in:
commit
88cb4d3ab0
1
.hgtags
1
.hgtags
@ -452,3 +452,4 @@ c44970de01474f6f3e01b0adea85ec1d03e3a5f2 release-1.17.10
|
||||
cbe6ba650211541310618849168631ce0b788f35 release-1.19.0
|
||||
062920e2f3bf871ef7a3d8496edec1b3065faf80 release-1.19.1
|
||||
a7b46539f507e6c64efa0efda69ad60b6f4ffbce release-1.19.2
|
||||
3cbc2602325f0ac08917a4397d76f5155c34b7b1 release-1.19.3
|
||||
|
10
auto/modules
10
auto/modules
@ -1172,6 +1172,16 @@ if [ $STREAM != NO ]; then
|
||||
. auto/module
|
||||
fi
|
||||
|
||||
if [ $STREAM_SET = YES ]; then
|
||||
ngx_module_name=ngx_stream_set_module
|
||||
ngx_module_deps=
|
||||
ngx_module_srcs=src/stream/ngx_stream_set_module.c
|
||||
ngx_module_libs=
|
||||
ngx_module_link=$STREAM_SET
|
||||
|
||||
. auto/module
|
||||
fi
|
||||
|
||||
if [ $STREAM_UPSTREAM_HASH = YES ]; then
|
||||
ngx_module_name=ngx_stream_upstream_hash_module
|
||||
ngx_module_deps=
|
||||
|
@ -127,6 +127,7 @@ STREAM_GEOIP=NO
|
||||
STREAM_MAP=YES
|
||||
STREAM_SPLIT_CLIENTS=YES
|
||||
STREAM_RETURN=YES
|
||||
STREAM_SET=YES
|
||||
STREAM_UPSTREAM_HASH=YES
|
||||
STREAM_UPSTREAM_LEAST_CONN=YES
|
||||
STREAM_UPSTREAM_RANDOM=YES
|
||||
@ -331,6 +332,7 @@ use the \"--with-mail_ssl_module\" option instead"
|
||||
--without-stream_split_clients_module)
|
||||
STREAM_SPLIT_CLIENTS=NO ;;
|
||||
--without-stream_return_module) STREAM_RETURN=NO ;;
|
||||
--without-stream_set_module) STREAM_SET=NO ;;
|
||||
--without-stream_upstream_hash_module)
|
||||
STREAM_UPSTREAM_HASH=NO ;;
|
||||
--without-stream_upstream_least_conn_module)
|
||||
@ -548,6 +550,7 @@ cat << END
|
||||
--without-stream_split_clients_module
|
||||
disable ngx_stream_split_clients_module
|
||||
--without-stream_return_module disable ngx_stream_return_module
|
||||
--without-stream_set_module disable ngx_stream_set_module
|
||||
--without-stream_upstream_hash_module
|
||||
disable ngx_stream_upstream_hash_module
|
||||
--without-stream_upstream_least_conn_module
|
||||
|
@ -5,6 +5,112 @@
|
||||
<change_log title="nginx">
|
||||
|
||||
|
||||
<changes ver="1.19.3" date="2020-09-29">
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
модуль ngx_stream_set_module.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the ngx_stream_set_module.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
директива proxy_cookie_flags.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "proxy_cookie_flags" directive.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para lang="ru">
|
||||
директива userid_flags.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "userid_flags" directive.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
расширение управления кэшированием stale-if-error
|
||||
ошибочно применялось, если бэкенд возвращал ответ
|
||||
с кодом 500, 502, 503, 504, 403, 404 или 429.
|
||||
</para>
|
||||
<para lang="en">
|
||||
the "stale-if-error" cache control extension
|
||||
was erroneously applied if backend returned a response
|
||||
with status code 500, 502, 503, 504, 403, 404, or 429.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
если использовалось кэширование
|
||||
и бэкенд возвращал ответы с строкой заголовка Vary,
|
||||
в логах могли появляться сообщения "[crit] cache file ... has too long header".
|
||||
</para>
|
||||
<para lang="en">
|
||||
"[crit] cache file ... has too long header" messages might appear in logs
|
||||
if caching was used
|
||||
and the backend returned responses with the "Vary" header line.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="workaround">
|
||||
<para lang="ru">
|
||||
при использовании OpenSSL 1.1.1
|
||||
в логах могли появляться сообщения "[crit] SSL_write() failed".
|
||||
</para>
|
||||
<para lang="en">
|
||||
"[crit] SSL_write() failed" messages might appear in logs
|
||||
when using OpenSSL 1.1.1.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
в логах могли появляться сообщения
|
||||
"SSL_shutdown() failed (SSL: ... bad write retry)";
|
||||
ошибка появилась в 1.19.2.
|
||||
</para>
|
||||
<para lang="en">
|
||||
"SSL_shutdown() failed (SSL: ... bad write retry)"
|
||||
messages might appear in logs;
|
||||
the bug had appeared in 1.19.2.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
при использовании HTTP/2
|
||||
в рабочем процессе мог произойти segmentation fault,
|
||||
если ошибки с кодом 400 с помощью директивы error_page
|
||||
перенаправлялись в проксируемый location.
|
||||
</para>
|
||||
<para lang="en">
|
||||
a segmentation fault might occur in a worker process
|
||||
when using HTTP/2
|
||||
if errors with code 400 were redirected to a proxied location
|
||||
using the "error_page" directive.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="bugfix">
|
||||
<para lang="ru">
|
||||
утечки сокетов при использовании HTTP/2 и подзапросов в модуле njs.
|
||||
</para>
|
||||
<para lang="en">
|
||||
socket leak when using HTTP/2 and subrequests in the njs module.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
</changes>
|
||||
|
||||
|
||||
<changes ver="1.19.2" date="2020-08-11">
|
||||
|
||||
<change type="change">
|
||||
|
@ -6,7 +6,7 @@ TEMP = tmp
|
||||
|
||||
CC = cl
|
||||
OBJS = objs.msvc8
|
||||
OPENSSL = openssl-1.1.1g
|
||||
OPENSSL = openssl-1.1.1h
|
||||
ZLIB = zlib-1.2.11
|
||||
PCRE = pcre-8.44
|
||||
|
||||
|
@ -9,8 +9,8 @@
|
||||
#define _NGINX_H_INCLUDED_
|
||||
|
||||
|
||||
#define nginx_version 1019002
|
||||
#define NGINX_VERSION "1.19.2"
|
||||
#define nginx_version 1019003
|
||||
#define NGINX_VERSION "1.19.3"
|
||||
#define NGINX_VER "nginx/" NGINX_VERSION
|
||||
|
||||
#ifdef NGX_BUILD
|
||||
|
@ -1918,7 +1918,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (rn == NULL) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected response for %V", &name);
|
||||
"unexpected DNS response for %V", &name);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
}
|
||||
@ -1930,7 +1930,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected response for %V", &name);
|
||||
"unexpected DNS response for %V", &name);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
}
|
||||
@ -1949,7 +1949,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (rn->query == NULL || rn->naddrs != (u_short) -1) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected response for %V", &name);
|
||||
"unexpected DNS response for %V", &name);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
}
|
||||
@ -1964,7 +1964,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (ident != qident) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"wrong ident %ui response for %V, expect %ui",
|
||||
"wrong ident %ui in DNS response for %V, expect %ui",
|
||||
ident, &name, qident);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
@ -2149,7 +2149,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (class != 1) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected RR class %ui", class);
|
||||
"unexpected RR class %ui in DNS response", class);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -2218,7 +2218,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
default:
|
||||
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected RR type %ui", type);
|
||||
"unexpected RR type %ui in DNS response", type);
|
||||
}
|
||||
|
||||
i += len;
|
||||
@ -2567,7 +2567,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (rn == NULL || rn->query == NULL) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected response for %V", &name);
|
||||
"unexpected DNS response for %V", &name);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
}
|
||||
@ -2581,7 +2581,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (ident != qident) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"wrong ident %ui response for %V, expect %ui",
|
||||
"wrong ident %ui in DNS response for %V, expect %ui",
|
||||
ident, &name, qident);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
@ -2691,7 +2691,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
|
||||
if (class != 1) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected RR class %ui", class);
|
||||
"unexpected RR class %ui in DNS response", class);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -2734,7 +2734,7 @@ ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
|
||||
default:
|
||||
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected RR type %ui", type);
|
||||
"unexpected RR type %ui in DNS response", type);
|
||||
}
|
||||
|
||||
i += len;
|
||||
@ -3165,7 +3165,7 @@ valid:
|
||||
|
||||
if (rn == NULL || rn->query == NULL) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected response for %V", &name);
|
||||
"unexpected DNS response for %V", &name);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
}
|
||||
@ -3174,7 +3174,7 @@ valid:
|
||||
|
||||
if (ident != qident) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"wrong ident %ui response for %V, expect %ui",
|
||||
"wrong ident %ui in DNS response for %V, expect %ui",
|
||||
ident, &name, qident);
|
||||
ngx_resolver_free(r, name.data);
|
||||
goto failed;
|
||||
@ -3256,7 +3256,7 @@ valid:
|
||||
|
||||
if (class != 1) {
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected RR class %ui", class);
|
||||
"unexpected RR class %ui in DNS response", class);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -3283,7 +3283,7 @@ valid:
|
||||
default:
|
||||
|
||||
ngx_log_error(r->log_level, r->log, 0,
|
||||
"unexpected RR type %ui", type);
|
||||
"unexpected RR type %ui in DNS response", type);
|
||||
}
|
||||
|
||||
i += len;
|
||||
@ -3952,12 +3952,12 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
|
||||
}
|
||||
|
||||
if (p >= last) {
|
||||
err = "name is out of response";
|
||||
err = "name is out of DNS response";
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
|
||||
err = "compression pointers loop";
|
||||
err = "compression pointers loop in DNS response";
|
||||
|
||||
invalid:
|
||||
|
||||
|
@ -2573,6 +2573,18 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
|
||||
|
||||
sslerr = SSL_get_error(c->ssl->connection, n);
|
||||
|
||||
if (sslerr == SSL_ERROR_ZERO_RETURN) {
|
||||
|
||||
/*
|
||||
* OpenSSL 1.1.1 fails to return SSL_ERROR_SYSCALL if an error
|
||||
* happens during SSL_write() after close_notify alert from the
|
||||
* peer, and returns SSL_ERROR_ZERO_RETURN instead,
|
||||
* https://git.openssl.org/?p=openssl.git;a=commitdiff;h=8051ab2
|
||||
*/
|
||||
|
||||
sslerr = SSL_ERROR_SYSCALL;
|
||||
}
|
||||
|
||||
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr);
|
||||
@ -2800,7 +2812,7 @@ ngx_ssl_shutdown(ngx_connection_t *c)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (c->timedout) {
|
||||
if (c->timedout || c->error || c->buffered) {
|
||||
mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN;
|
||||
SSL_set_quiet_shutdown(c->ssl->connection, 1);
|
||||
|
||||
@ -2860,6 +2872,13 @@ ngx_ssl_shutdown(ngx_connection_t *c)
|
||||
c->read->handler = ngx_ssl_shutdown_handler;
|
||||
c->write->handler = ngx_ssl_shutdown_handler;
|
||||
|
||||
if (sslerr == SSL_ERROR_WANT_READ) {
|
||||
c->read->ready = 0;
|
||||
|
||||
} else {
|
||||
c->write->ready = 0;
|
||||
}
|
||||
|
||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
@ -10,6 +10,19 @@
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#define NGX_HTTP_PROXY_COOKIE_SECURE 0x0001
|
||||
#define NGX_HTTP_PROXY_COOKIE_SECURE_ON 0x0002
|
||||
#define NGX_HTTP_PROXY_COOKIE_SECURE_OFF 0x0004
|
||||
#define NGX_HTTP_PROXY_COOKIE_HTTPONLY 0x0008
|
||||
#define NGX_HTTP_PROXY_COOKIE_HTTPONLY_ON 0x0010
|
||||
#define NGX_HTTP_PROXY_COOKIE_HTTPONLY_OFF 0x0020
|
||||
#define NGX_HTTP_PROXY_COOKIE_SAMESITE 0x0040
|
||||
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_STRICT 0x0080
|
||||
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_LAX 0x0100
|
||||
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_NONE 0x0200
|
||||
#define NGX_HTTP_PROXY_COOKIE_SAMESITE_OFF 0x0400
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_array_t caches; /* ngx_http_file_cache_t * */
|
||||
} ngx_http_proxy_main_conf_t;
|
||||
@ -18,7 +31,7 @@ typedef struct {
|
||||
typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t;
|
||||
|
||||
typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, size_t prefix, size_t len,
|
||||
ngx_str_t *value, size_t prefix, size_t len,
|
||||
ngx_http_proxy_rewrite_t *pr);
|
||||
|
||||
struct ngx_http_proxy_rewrite_s {
|
||||
@ -35,6 +48,19 @@ struct ngx_http_proxy_rewrite_s {
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
ngx_http_complex_value_t complex;
|
||||
#if (NGX_PCRE)
|
||||
ngx_http_regex_t *regex;
|
||||
#endif
|
||||
} cookie;
|
||||
|
||||
ngx_uint_t flags;
|
||||
ngx_uint_t regex;
|
||||
} ngx_http_proxy_cookie_flags_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t key_start;
|
||||
ngx_str_t schema;
|
||||
@ -72,6 +98,7 @@ typedef struct {
|
||||
ngx_array_t *redirects;
|
||||
ngx_array_t *cookie_domains;
|
||||
ngx_array_t *cookie_paths;
|
||||
ngx_array_t *cookie_flags;
|
||||
|
||||
ngx_http_complex_value_t *method;
|
||||
ngx_str_t location;
|
||||
@ -158,10 +185,16 @@ static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, size_t prefix);
|
||||
static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h);
|
||||
static ngx_int_t ngx_http_proxy_parse_cookie(ngx_str_t *value,
|
||||
ngx_array_t *attrs);
|
||||
static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, u_char *value, ngx_array_t *rewrites);
|
||||
ngx_str_t *value, ngx_array_t *rewrites);
|
||||
static ngx_int_t ngx_http_proxy_rewrite_cookie_flags(ngx_http_request_t *r,
|
||||
ngx_array_t *attrs, ngx_array_t *flags);
|
||||
static ngx_int_t ngx_http_proxy_edit_cookie_flags(ngx_http_request_t *r,
|
||||
ngx_array_t *attrs, ngx_uint_t flags);
|
||||
static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement);
|
||||
ngx_str_t *value, size_t prefix, size_t len, ngx_str_t *replacement);
|
||||
|
||||
static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
|
||||
static void *ngx_http_proxy_create_main_conf(ngx_conf_t *cf);
|
||||
@ -180,6 +213,8 @@ static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_proxy_cookie_flags(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
#if (NGX_HTTP_CACHE)
|
||||
@ -282,6 +317,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
|
||||
0,
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_cookie_flags"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
|
||||
ngx_http_proxy_cookie_flags,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
0,
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_store"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_http_proxy_store,
|
||||
@ -845,6 +887,36 @@ static ngx_path_init_t ngx_http_proxy_temp_path = {
|
||||
};
|
||||
|
||||
|
||||
static ngx_conf_bitmask_t ngx_http_proxy_cookie_flags_masks[] = {
|
||||
|
||||
{ ngx_string("secure"),
|
||||
NGX_HTTP_PROXY_COOKIE_SECURE|NGX_HTTP_PROXY_COOKIE_SECURE_ON },
|
||||
|
||||
{ ngx_string("nosecure"),
|
||||
NGX_HTTP_PROXY_COOKIE_SECURE|NGX_HTTP_PROXY_COOKIE_SECURE_OFF },
|
||||
|
||||
{ ngx_string("httponly"),
|
||||
NGX_HTTP_PROXY_COOKIE_HTTPONLY|NGX_HTTP_PROXY_COOKIE_HTTPONLY_ON },
|
||||
|
||||
{ ngx_string("nohttponly"),
|
||||
NGX_HTTP_PROXY_COOKIE_HTTPONLY|NGX_HTTP_PROXY_COOKIE_HTTPONLY_OFF },
|
||||
|
||||
{ ngx_string("samesite=strict"),
|
||||
NGX_HTTP_PROXY_COOKIE_SAMESITE|NGX_HTTP_PROXY_COOKIE_SAMESITE_STRICT },
|
||||
|
||||
{ ngx_string("samesite=lax"),
|
||||
NGX_HTTP_PROXY_COOKIE_SAMESITE|NGX_HTTP_PROXY_COOKIE_SAMESITE_LAX },
|
||||
|
||||
{ ngx_string("samesite=none"),
|
||||
NGX_HTTP_PROXY_COOKIE_SAMESITE|NGX_HTTP_PROXY_COOKIE_SAMESITE_NONE },
|
||||
|
||||
{ ngx_string("nosamesite"),
|
||||
NGX_HTTP_PROXY_COOKIE_SAMESITE|NGX_HTTP_PROXY_COOKIE_SAMESITE_OFF },
|
||||
|
||||
{ ngx_null_string, 0 }
|
||||
};
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
{
|
||||
@ -906,7 +978,7 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
|
||||
}
|
||||
|
||||
if (plcf->cookie_domains || plcf->cookie_paths) {
|
||||
if (plcf->cookie_domains || plcf->cookie_paths || plcf->cookie_flags) {
|
||||
u->rewrite_cookie = ngx_http_proxy_rewrite_cookie;
|
||||
}
|
||||
|
||||
@ -2584,7 +2656,7 @@ ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
len = h->value.len - prefix;
|
||||
|
||||
for (i = 0; i < plcf->redirects->nelts; i++) {
|
||||
rc = pr[i].handler(r, h, prefix, len, &pr[i]);
|
||||
rc = pr[i].handler(r, &h->value, prefix, len, &pr[i]);
|
||||
|
||||
if (rc != NGX_DECLINED) {
|
||||
return rc;
|
||||
@ -2598,27 +2670,43 @@ ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
|
||||
{
|
||||
size_t prefix;
|
||||
u_char *p;
|
||||
size_t len;
|
||||
ngx_int_t rc, rv;
|
||||
ngx_str_t *key, *value;
|
||||
ngx_uint_t i;
|
||||
ngx_array_t attrs;
|
||||
ngx_keyval_t *attr;
|
||||
ngx_http_proxy_loc_conf_t *plcf;
|
||||
|
||||
p = (u_char *) ngx_strchr(h->value.data, ';');
|
||||
if (p == NULL) {
|
||||
return NGX_DECLINED;
|
||||
if (ngx_array_init(&attrs, r->pool, 2, sizeof(ngx_keyval_t)) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
prefix = p + 1 - h->value.data;
|
||||
if (ngx_http_proxy_parse_cookie(&h->value, &attrs) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
attr = attrs.elts;
|
||||
|
||||
if (attr[0].value.data == NULL) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
rv = NGX_DECLINED;
|
||||
|
||||
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
|
||||
|
||||
if (plcf->cookie_domains) {
|
||||
p = ngx_strcasestrn(h->value.data + prefix, "domain=", 7 - 1);
|
||||
for (i = 1; i < attrs.nelts; i++) {
|
||||
|
||||
if (p) {
|
||||
rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 7,
|
||||
key = &attr[i].key;
|
||||
value = &attr[i].value;
|
||||
|
||||
if (plcf->cookie_domains && key->len == 6
|
||||
&& ngx_strncasecmp(key->data, (u_char *) "domain", 6) == 0
|
||||
&& value->data)
|
||||
{
|
||||
rc = ngx_http_proxy_rewrite_cookie_value(r, value,
|
||||
plcf->cookie_domains);
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
@ -2628,13 +2716,12 @@ ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
|
||||
rv = rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (plcf->cookie_paths) {
|
||||
p = ngx_strcasestrn(h->value.data + prefix, "path=", 5 - 1);
|
||||
|
||||
if (p) {
|
||||
rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 5,
|
||||
if (plcf->cookie_paths && key->len == 4
|
||||
&& ngx_strncasecmp(key->data, (u_char *) "path", 4) == 0
|
||||
&& value->data)
|
||||
{
|
||||
rc = ngx_http_proxy_rewrite_cookie_value(r, value,
|
||||
plcf->cookie_paths);
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
@ -2646,30 +2733,153 @@ ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
if (plcf->cookie_flags) {
|
||||
rc = ngx_http_proxy_rewrite_cookie_flags(r, &attrs,
|
||||
plcf->cookie_flags);
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (rc != NGX_DECLINED) {
|
||||
rv = rc;
|
||||
}
|
||||
|
||||
attr = attrs.elts;
|
||||
}
|
||||
|
||||
if (rv != NGX_OK) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
|
||||
for (i = 0; i < attrs.nelts; i++) {
|
||||
|
||||
if (attr[i].key.data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
len += 2;
|
||||
}
|
||||
|
||||
len += attr[i].key.len;
|
||||
|
||||
if (attr[i].value.data) {
|
||||
len += 1 + attr[i].value.len;
|
||||
}
|
||||
}
|
||||
|
||||
p = ngx_pnalloc(r->pool, len + 1);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
h->value.data = p;
|
||||
h->value.len = len;
|
||||
|
||||
for (i = 0; i < attrs.nelts; i++) {
|
||||
|
||||
if (attr[i].key.data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
*p++ = ';';
|
||||
*p++ = ' ';
|
||||
}
|
||||
|
||||
p = ngx_cpymem(p, attr[i].key.data, attr[i].key.len);
|
||||
|
||||
if (attr[i].value.data) {
|
||||
*p++ = '=';
|
||||
p = ngx_cpymem(p, attr[i].value.data, attr[i].value.len);
|
||||
}
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
u_char *value, ngx_array_t *rewrites)
|
||||
ngx_http_proxy_parse_cookie(ngx_str_t *value, ngx_array_t *attrs)
|
||||
{
|
||||
u_char *start, *end, *p, *last;
|
||||
ngx_str_t name, val;
|
||||
ngx_keyval_t *attr;
|
||||
|
||||
start = value->data;
|
||||
end = value->data + value->len;
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
last = (u_char *) ngx_strchr(start, ';');
|
||||
|
||||
if (last == NULL) {
|
||||
last = end;
|
||||
}
|
||||
|
||||
while (start < last && *start == ' ') { start++; }
|
||||
|
||||
for (p = start; p < last && *p != '='; p++) { /* void */ }
|
||||
|
||||
name.data = start;
|
||||
name.len = p - start;
|
||||
|
||||
while (name.len && name.data[name.len - 1] == ' ') {
|
||||
name.len--;
|
||||
}
|
||||
|
||||
if (p < last) {
|
||||
|
||||
p++;
|
||||
|
||||
while (p < last && *p == ' ') { p++; }
|
||||
|
||||
val.data = p;
|
||||
val.len = last - val.data;
|
||||
|
||||
while (val.len && val.data[val.len - 1] == ' ') {
|
||||
val.len--;
|
||||
}
|
||||
|
||||
} else {
|
||||
ngx_str_null(&val);
|
||||
}
|
||||
|
||||
attr = ngx_array_push(attrs);
|
||||
if (attr == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
attr->key = name;
|
||||
attr->value = val;
|
||||
|
||||
if (last == end) {
|
||||
break;
|
||||
}
|
||||
|
||||
start = last + 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_str_t *value,
|
||||
ngx_array_t *rewrites)
|
||||
{
|
||||
size_t len, prefix;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t i;
|
||||
ngx_http_proxy_rewrite_t *pr;
|
||||
|
||||
prefix = value - h->value.data;
|
||||
|
||||
p = (u_char *) ngx_strchr(value, ';');
|
||||
|
||||
len = p ? (size_t) (p - value) : (h->value.len - prefix);
|
||||
|
||||
pr = rewrites->elts;
|
||||
|
||||
for (i = 0; i < rewrites->nelts; i++) {
|
||||
rc = pr[i].handler(r, h, prefix, len, &pr[i]);
|
||||
rc = pr[i].handler(r, value, 0, value->len, &pr[i]);
|
||||
|
||||
if (rc != NGX_DECLINED) {
|
||||
return rc;
|
||||
@ -2681,8 +2891,194 @@ ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
|
||||
ngx_http_proxy_rewrite_cookie_flags(ngx_http_request_t *r, ngx_array_t *attrs,
|
||||
ngx_array_t *flags)
|
||||
{
|
||||
ngx_str_t pattern;
|
||||
#if (NGX_PCRE)
|
||||
ngx_int_t rc;
|
||||
#endif
|
||||
ngx_uint_t i;
|
||||
ngx_keyval_t *attr;
|
||||
ngx_http_proxy_cookie_flags_t *pcf;
|
||||
|
||||
attr = attrs->elts;
|
||||
pcf = flags->elts;
|
||||
|
||||
for (i = 0; i < flags->nelts; i++) {
|
||||
|
||||
#if (NGX_PCRE)
|
||||
if (pcf[i].regex) {
|
||||
rc = ngx_http_regex_exec(r, pcf[i].cookie.regex, &attr[0].key);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* NGX_DECLINED */
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ngx_http_complex_value(r, &pcf[i].cookie.complex, &pattern)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (pattern.len == attr[0].key.len
|
||||
&& ngx_strncasecmp(attr[0].key.data, pattern.data, pattern.len)
|
||||
== 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == flags->nelts) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
return ngx_http_proxy_edit_cookie_flags(r, attrs, pcf[i].flags);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_edit_cookie_flags(ngx_http_request_t *r, ngx_array_t *attrs,
|
||||
ngx_uint_t flags)
|
||||
{
|
||||
ngx_str_t *key, *value;
|
||||
ngx_uint_t i;
|
||||
ngx_keyval_t *attr;
|
||||
|
||||
attr = attrs->elts;
|
||||
|
||||
for (i = 1; i < attrs->nelts; i++) {
|
||||
key = &attr[i].key;
|
||||
|
||||
if (key->len == 6
|
||||
&& ngx_strncasecmp(key->data, (u_char *) "secure", 6) == 0)
|
||||
{
|
||||
if (flags & NGX_HTTP_PROXY_COOKIE_SECURE_ON) {
|
||||
flags &= ~NGX_HTTP_PROXY_COOKIE_SECURE_ON;
|
||||
|
||||
} else if (flags & NGX_HTTP_PROXY_COOKIE_SECURE_OFF) {
|
||||
key->data = NULL;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key->len == 8
|
||||
&& ngx_strncasecmp(key->data, (u_char *) "httponly", 8) == 0)
|
||||
{
|
||||
if (flags & NGX_HTTP_PROXY_COOKIE_HTTPONLY_ON) {
|
||||
flags &= ~NGX_HTTP_PROXY_COOKIE_HTTPONLY_ON;
|
||||
|
||||
} else if (flags & NGX_HTTP_PROXY_COOKIE_HTTPONLY_OFF) {
|
||||
key->data = NULL;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key->len == 8
|
||||
&& ngx_strncasecmp(key->data, (u_char *) "samesite", 8) == 0)
|
||||
{
|
||||
value = &attr[i].value;
|
||||
|
||||
if (flags & NGX_HTTP_PROXY_COOKIE_SAMESITE_STRICT) {
|
||||
flags &= ~NGX_HTTP_PROXY_COOKIE_SAMESITE_STRICT;
|
||||
|
||||
if (value->len != 6
|
||||
|| ngx_strncasecmp(value->data, (u_char *) "strict", 6)
|
||||
!= 0)
|
||||
{
|
||||
ngx_str_set(key, "SameSite");
|
||||
ngx_str_set(value, "Strict");
|
||||
}
|
||||
|
||||
} else if (flags & NGX_HTTP_PROXY_COOKIE_SAMESITE_LAX) {
|
||||
flags &= ~NGX_HTTP_PROXY_COOKIE_SAMESITE_LAX;
|
||||
|
||||
if (value->len != 3
|
||||
|| ngx_strncasecmp(value->data, (u_char *) "lax", 3) != 0)
|
||||
{
|
||||
ngx_str_set(key, "SameSite");
|
||||
ngx_str_set(value, "Lax");
|
||||
}
|
||||
|
||||
} else if (flags & NGX_HTTP_PROXY_COOKIE_SAMESITE_NONE) {
|
||||
flags &= ~NGX_HTTP_PROXY_COOKIE_SAMESITE_NONE;
|
||||
|
||||
if (value->len != 4
|
||||
|| ngx_strncasecmp(value->data, (u_char *) "none", 4) != 0)
|
||||
{
|
||||
ngx_str_set(key, "SameSite");
|
||||
ngx_str_set(value, "None");
|
||||
}
|
||||
|
||||
} else if (flags & NGX_HTTP_PROXY_COOKIE_SAMESITE_OFF) {
|
||||
key->data = NULL;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & NGX_HTTP_PROXY_COOKIE_SECURE_ON) {
|
||||
attr = ngx_array_push(attrs);
|
||||
if (attr == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_str_set(&attr->key, "Secure");
|
||||
ngx_str_null(&attr->value);
|
||||
}
|
||||
|
||||
if (flags & NGX_HTTP_PROXY_COOKIE_HTTPONLY_ON) {
|
||||
attr = ngx_array_push(attrs);
|
||||
if (attr == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_str_set(&attr->key, "HttpOnly");
|
||||
ngx_str_null(&attr->value);
|
||||
}
|
||||
|
||||
if (flags & (NGX_HTTP_PROXY_COOKIE_SAMESITE_STRICT
|
||||
|NGX_HTTP_PROXY_COOKIE_SAMESITE_LAX
|
||||
|NGX_HTTP_PROXY_COOKIE_SAMESITE_NONE))
|
||||
{
|
||||
attr = ngx_array_push(attrs);
|
||||
if (attr == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_str_set(&attr->key, "SameSite");
|
||||
|
||||
if (flags & NGX_HTTP_PROXY_COOKIE_SAMESITE_STRICT) {
|
||||
ngx_str_set(&attr->value, "Strict");
|
||||
|
||||
} else if (flags & NGX_HTTP_PROXY_COOKIE_SAMESITE_LAX) {
|
||||
ngx_str_set(&attr->value, "Lax");
|
||||
|
||||
} else {
|
||||
ngx_str_set(&attr->value, "None");
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r, ngx_str_t *value,
|
||||
size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
|
||||
{
|
||||
ngx_str_t pattern, replacement;
|
||||
|
||||
@ -2691,8 +3087,7 @@ ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
|
||||
}
|
||||
|
||||
if (pattern.len > len
|
||||
|| ngx_rstrncmp(h->value.data + prefix, pattern.data,
|
||||
pattern.len) != 0)
|
||||
|| ngx_rstrncmp(value->data + prefix, pattern.data, pattern.len) != 0)
|
||||
{
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
@ -2701,20 +3096,20 @@ ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return ngx_http_proxy_rewrite(r, h, prefix, pattern.len, &replacement);
|
||||
return ngx_http_proxy_rewrite(r, value, prefix, pattern.len, &replacement);
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_PCRE)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_str_t *value,
|
||||
size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
|
||||
{
|
||||
ngx_str_t pattern, replacement;
|
||||
|
||||
pattern.len = len;
|
||||
pattern.data = h->value.data + prefix;
|
||||
pattern.data = value->data + prefix;
|
||||
|
||||
if (ngx_http_regex_exec(r, pr->pattern.regex, &pattern) != NGX_OK) {
|
||||
return NGX_DECLINED;
|
||||
@ -2724,20 +3119,15 @@ ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (prefix == 0 && h->value.len == len) {
|
||||
h->value = replacement;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
|
||||
return ngx_http_proxy_rewrite(r, value, prefix, len, &replacement);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
|
||||
ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r, ngx_str_t *value,
|
||||
size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
|
||||
{
|
||||
u_char *p;
|
||||
ngx_str_t pattern, replacement;
|
||||
@ -2746,9 +3136,9 @@ ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
p = h->value.data + prefix;
|
||||
p = value->data + prefix;
|
||||
|
||||
if (p[0] == '.') {
|
||||
if (len && p[0] == '.') {
|
||||
p++;
|
||||
prefix++;
|
||||
len--;
|
||||
@ -2762,18 +3152,23 @@ ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
|
||||
return ngx_http_proxy_rewrite(r, value, prefix, len, &replacement);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix,
|
||||
ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_str_t *value, size_t prefix,
|
||||
size_t len, ngx_str_t *replacement)
|
||||
{
|
||||
u_char *p, *data;
|
||||
size_t new_len;
|
||||
|
||||
new_len = replacement->len + h->value.len - len;
|
||||
if (len == value->len) {
|
||||
*value = *replacement;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
new_len = replacement->len + value->len - len;
|
||||
|
||||
if (replacement->len > len) {
|
||||
|
||||
@ -2782,23 +3177,22 @@ ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix,
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
p = ngx_copy(data, h->value.data, prefix);
|
||||
p = ngx_copy(data, value->data, prefix);
|
||||
p = ngx_copy(p, replacement->data, replacement->len);
|
||||
|
||||
ngx_memcpy(p, h->value.data + prefix + len,
|
||||
h->value.len - len - prefix + 1);
|
||||
ngx_memcpy(p, value->data + prefix + len,
|
||||
value->len - len - prefix + 1);
|
||||
|
||||
h->value.data = data;
|
||||
value->data = data;
|
||||
|
||||
} else {
|
||||
p = ngx_copy(h->value.data + prefix, replacement->data,
|
||||
replacement->len);
|
||||
p = ngx_copy(value->data + prefix, replacement->data, replacement->len);
|
||||
|
||||
ngx_memmove(p, h->value.data + prefix + len,
|
||||
h->value.len - len - prefix + 1);
|
||||
ngx_memmove(p, value->data + prefix + len,
|
||||
value->len - len - prefix + 1);
|
||||
}
|
||||
|
||||
h->value.len = new_len;
|
||||
value->len = new_len;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
@ -2957,6 +3351,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
||||
|
||||
conf->cookie_domains = NGX_CONF_UNSET_PTR;
|
||||
conf->cookie_paths = NGX_CONF_UNSET_PTR;
|
||||
conf->cookie_flags = NGX_CONF_UNSET_PTR;
|
||||
|
||||
conf->http_version = NGX_CONF_UNSET_UINT;
|
||||
|
||||
@ -3352,6 +3747,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL);
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->cookie_flags, prev->cookie_flags, NULL);
|
||||
|
||||
ngx_conf_merge_uint_value(conf->http_version, prev->http_version,
|
||||
NGX_HTTP_VERSION_10);
|
||||
|
||||
@ -3766,7 +4163,7 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
ngx_http_compile_complex_value_t ccv;
|
||||
|
||||
if (plcf->redirect == 0) {
|
||||
return NGX_CONF_OK;
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
plcf->redirect = 1;
|
||||
@ -3775,16 +4172,12 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
|
||||
if (cf->args->nelts == 2) {
|
||||
if (ngx_strcmp(value[1].data, "off") == 0) {
|
||||
plcf->redirect = 0;
|
||||
plcf->redirects = NULL;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[1].data, "false") == 0) {
|
||||
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
|
||||
"invalid parameter \"false\", use \"off\" instead");
|
||||
if (plcf->redirects) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
plcf->redirect = 0;
|
||||
plcf->redirects = NULL;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
@ -3808,7 +4201,9 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[1].data, "default") == 0) {
|
||||
if (cf->args->nelts == 2
|
||||
&& ngx_strcmp(value[1].data, "default") == 0)
|
||||
{
|
||||
if (plcf->proxy_lengths) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"\"proxy_redirect default\" cannot be used "
|
||||
@ -3911,7 +4306,7 @@ ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
ngx_http_compile_complex_value_t ccv;
|
||||
|
||||
if (plcf->cookie_domains == NULL) {
|
||||
return NGX_CONF_OK;
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
@ -3919,6 +4314,11 @@ ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
if (cf->args->nelts == 2) {
|
||||
|
||||
if (ngx_strcmp(value[1].data, "off") == 0) {
|
||||
|
||||
if (plcf->cookie_domains != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
plcf->cookie_domains = NULL;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
@ -3998,7 +4398,7 @@ ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
ngx_http_compile_complex_value_t ccv;
|
||||
|
||||
if (plcf->cookie_paths == NULL) {
|
||||
return NGX_CONF_OK;
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
@ -4006,6 +4406,11 @@ ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
if (cf->args->nelts == 2) {
|
||||
|
||||
if (ngx_strcmp(value[1].data, "off") == 0) {
|
||||
|
||||
if (plcf->cookie_paths != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
plcf->cookie_paths = NULL;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
@ -4075,6 +4480,131 @@ ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_proxy_cookie_flags(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_proxy_loc_conf_t *plcf = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
ngx_uint_t i, m;
|
||||
ngx_conf_bitmask_t *mask;
|
||||
ngx_http_proxy_cookie_flags_t *pcf;
|
||||
ngx_http_compile_complex_value_t ccv;
|
||||
#if (NGX_PCRE)
|
||||
ngx_regex_compile_t rc;
|
||||
u_char errstr[NGX_MAX_CONF_ERRSTR];
|
||||
#endif
|
||||
|
||||
if (plcf->cookie_flags == NULL) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
if (cf->args->nelts == 2) {
|
||||
|
||||
if (ngx_strcmp(value[1].data, "off") == 0) {
|
||||
|
||||
if (plcf->cookie_flags != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
plcf->cookie_flags = NULL;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid parameter \"%V\"", &value[1]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (plcf->cookie_flags == NGX_CONF_UNSET_PTR) {
|
||||
plcf->cookie_flags = ngx_array_create(cf->pool, 1,
|
||||
sizeof(ngx_http_proxy_cookie_flags_t));
|
||||
if (plcf->cookie_flags == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
pcf = ngx_array_push(plcf->cookie_flags);
|
||||
if (pcf == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
pcf->regex = 0;
|
||||
|
||||
if (value[1].data[0] == '~') {
|
||||
value[1].len--;
|
||||
value[1].data++;
|
||||
|
||||
#if (NGX_PCRE)
|
||||
ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
|
||||
|
||||
rc.pattern = value[1];
|
||||
rc.err.len = NGX_MAX_CONF_ERRSTR;
|
||||
rc.err.data = errstr;
|
||||
rc.options = NGX_REGEX_CASELESS;
|
||||
|
||||
pcf->cookie.regex = ngx_http_regex_compile(cf, &rc);
|
||||
if (pcf->cookie.regex == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
pcf->regex = 1;
|
||||
#else
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"using regex \"%V\" requires PCRE library",
|
||||
&value[1]);
|
||||
return NGX_CONF_ERROR;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||
|
||||
ccv.cf = cf;
|
||||
ccv.value = &value[1];
|
||||
ccv.complex_value = &pcf->cookie.complex;
|
||||
|
||||
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
mask = ngx_http_proxy_cookie_flags_masks;
|
||||
pcf->flags = 0;
|
||||
|
||||
for (i = 2; i < cf->args->nelts; i++) {
|
||||
for (m = 0; mask[m].name.len != 0; m++) {
|
||||
|
||||
if (mask[m].name.len != value[i].len
|
||||
|| ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pcf->flags & mask[m].mask) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"duplicate parameter \"%V\"", &value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
pcf->flags |= mask[m].mask;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (mask[m].name.len == 0) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid parameter \"%V\"", &value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr,
|
||||
ngx_str_t *regex, ngx_uint_t caseless)
|
||||
|
@ -15,12 +15,21 @@
|
||||
#define NGX_HTTP_USERID_V1 2
|
||||
#define NGX_HTTP_USERID_ON 3
|
||||
|
||||
#define NGX_HTTP_USERID_COOKIE_OFF 0x0002
|
||||
#define NGX_HTTP_USERID_COOKIE_SECURE 0x0004
|
||||
#define NGX_HTTP_USERID_COOKIE_HTTPONLY 0x0008
|
||||
#define NGX_HTTP_USERID_COOKIE_SAMESITE 0x0010
|
||||
#define NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT 0x0020
|
||||
#define NGX_HTTP_USERID_COOKIE_SAMESITE_LAX 0x0040
|
||||
#define NGX_HTTP_USERID_COOKIE_SAMESITE_NONE 0x0080
|
||||
|
||||
/* 31 Dec 2037 23:55:55 GMT */
|
||||
#define NGX_HTTP_USERID_MAX_EXPIRES 2145916555
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_uint_t enable;
|
||||
ngx_uint_t flags;
|
||||
|
||||
ngx_int_t service;
|
||||
|
||||
@ -88,6 +97,20 @@ static ngx_conf_enum_t ngx_http_userid_state[] = {
|
||||
};
|
||||
|
||||
|
||||
static ngx_conf_bitmask_t ngx_http_userid_flags[] = {
|
||||
{ ngx_string("off"), NGX_HTTP_USERID_COOKIE_OFF },
|
||||
{ ngx_string("secure"), NGX_HTTP_USERID_COOKIE_SECURE },
|
||||
{ ngx_string("httponly"), NGX_HTTP_USERID_COOKIE_HTTPONLY },
|
||||
{ ngx_string("samesite=strict"),
|
||||
NGX_HTTP_USERID_COOKIE_SAMESITE|NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT },
|
||||
{ ngx_string("samesite=lax"),
|
||||
NGX_HTTP_USERID_COOKIE_SAMESITE|NGX_HTTP_USERID_COOKIE_SAMESITE_LAX },
|
||||
{ ngx_string("samesite=none"),
|
||||
NGX_HTTP_USERID_COOKIE_SAMESITE|NGX_HTTP_USERID_COOKIE_SAMESITE_NONE },
|
||||
{ ngx_null_string, 0 }
|
||||
};
|
||||
|
||||
|
||||
static ngx_conf_post_handler_pt ngx_http_userid_domain_p =
|
||||
ngx_http_userid_domain;
|
||||
static ngx_conf_post_handler_pt ngx_http_userid_path_p = ngx_http_userid_path;
|
||||
@ -138,6 +161,13 @@ static ngx_command_t ngx_http_userid_commands[] = {
|
||||
0,
|
||||
NULL },
|
||||
|
||||
{ ngx_string("userid_flags"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
|
||||
ngx_conf_set_bitmask_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_userid_conf_t, flags),
|
||||
&ngx_http_userid_flags },
|
||||
|
||||
{ ngx_string("userid_p3p"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
@ -383,6 +413,26 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
|
||||
len += conf->domain.len;
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SECURE) {
|
||||
len += sizeof("; secure") - 1;
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_HTTPONLY) {
|
||||
len += sizeof("; httponly") - 1;
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT) {
|
||||
len += sizeof("; samesite=strict") - 1;
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_LAX) {
|
||||
len += sizeof("; samesite=lax") - 1;
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_NONE) {
|
||||
len += sizeof("; samesite=none") - 1;
|
||||
}
|
||||
|
||||
cookie = ngx_pnalloc(r->pool, len);
|
||||
if (cookie == NULL) {
|
||||
return NGX_ERROR;
|
||||
@ -422,6 +472,26 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
|
||||
|
||||
p = ngx_copy(p, conf->path.data, conf->path.len);
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SECURE) {
|
||||
p = ngx_cpymem(p, "; secure", sizeof("; secure") - 1);
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_HTTPONLY) {
|
||||
p = ngx_cpymem(p, "; httponly", sizeof("; httponly") - 1);
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_STRICT) {
|
||||
p = ngx_cpymem(p, "; samesite=strict", sizeof("; samesite=strict") - 1);
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_LAX) {
|
||||
p = ngx_cpymem(p, "; samesite=lax", sizeof("; samesite=lax") - 1);
|
||||
}
|
||||
|
||||
if (conf->flags & NGX_HTTP_USERID_COOKIE_SAMESITE_NONE) {
|
||||
p = ngx_cpymem(p, "; samesite=none", sizeof("; samesite=none") - 1);
|
||||
}
|
||||
|
||||
set_cookie = ngx_list_push(&r->headers_out.headers);
|
||||
if (set_cookie == NULL) {
|
||||
return NGX_ERROR;
|
||||
@ -658,6 +728,7 @@ ngx_http_userid_create_conf(ngx_conf_t *cf)
|
||||
/*
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* conf->flags = 0;
|
||||
* conf->name = { 0, NULL };
|
||||
* conf->domain = { 0, NULL };
|
||||
* conf->path = { 0, NULL };
|
||||
@ -682,6 +753,9 @@ ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_conf_merge_uint_value(conf->enable, prev->enable,
|
||||
NGX_HTTP_USERID_OFF);
|
||||
|
||||
ngx_conf_merge_bitmask_value(conf->flags, prev->flags,
|
||||
(NGX_CONF_BITMASK_SET|NGX_HTTP_USERID_COOKIE_OFF));
|
||||
|
||||
ngx_conf_merge_str_value(conf->name, prev->name, "uid");
|
||||
ngx_conf_merge_str_value(conf->domain, prev->domain, "");
|
||||
ngx_conf_merge_str_value(conf->path, prev->path, "; path=/");
|
||||
|
@ -80,6 +80,7 @@ struct ngx_http_cache_s {
|
||||
ngx_str_t vary;
|
||||
u_char variant[NGX_HTTP_CACHE_KEY_LEN];
|
||||
|
||||
size_t buffer_size;
|
||||
size_t header_start;
|
||||
size_t body_start;
|
||||
off_t length;
|
||||
@ -116,6 +117,7 @@ struct ngx_http_cache_s {
|
||||
unsigned purged:1;
|
||||
unsigned reading:1;
|
||||
unsigned secondary:1;
|
||||
unsigned update_variant:1;
|
||||
unsigned background:1;
|
||||
|
||||
unsigned stale_updating:1;
|
||||
|
@ -294,6 +294,8 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
|
||||
cln->data = c;
|
||||
}
|
||||
|
||||
c->buffer_size = c->body_start;
|
||||
|
||||
rc = ngx_http_file_cache_exists(cache, c);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
@ -852,7 +854,7 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
|
||||
if (fcn->exists || fcn->uses >= c->min_uses) {
|
||||
|
||||
c->exists = fcn->exists;
|
||||
if (fcn->body_start) {
|
||||
if (fcn->body_start && !c->update_variant) {
|
||||
c->body_start = fcn->body_start;
|
||||
}
|
||||
|
||||
@ -1230,7 +1232,7 @@ ngx_http_file_cache_reopen(ngx_http_request_t *r, ngx_http_cache_t *c)
|
||||
|
||||
c->secondary = 1;
|
||||
c->file.name.len = 0;
|
||||
c->body_start = c->buf->end - c->buf->start;
|
||||
c->body_start = c->buffer_size;
|
||||
|
||||
ngx_memcpy(c->key, c->variant, NGX_HTTP_CACHE_KEY_LEN);
|
||||
|
||||
@ -1337,6 +1339,7 @@ ngx_http_file_cache_update_variant(ngx_http_request_t *r, ngx_http_cache_t *c)
|
||||
ngx_shmtx_unlock(&cache->shpool->mutex);
|
||||
|
||||
c->file.name.len = 0;
|
||||
c->update_variant = 1;
|
||||
|
||||
ngx_memcpy(c->key, c->main, NGX_HTTP_CACHE_KEY_LEN);
|
||||
|
||||
|
@ -988,7 +988,10 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
||||
c->ssl->buffer_size = sscf->buffer_size;
|
||||
|
||||
if (sscf->ssl.ctx) {
|
||||
SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
|
||||
if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
|
||||
*ad = SSL_AD_INTERNAL_ERROR;
|
||||
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSL_set_SSL_CTX() only changes certs as of 1.0.0d
|
||||
|
@ -2486,7 +2486,7 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
|
||||
&& ((u->conf->cache_use_stale & un->mask) || r->cache->stale_error))
|
||||
&& (u->conf->cache_use_stale & un->mask))
|
||||
{
|
||||
ngx_int_t rc;
|
||||
|
||||
|
@ -953,6 +953,13 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||
"http2 DATA frame");
|
||||
|
||||
if (h2c->state.sid == 0) {
|
||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||
"client sent DATA frame with incorrect identifier");
|
||||
|
||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
if (size > h2c->recv_window) {
|
||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||
"client violated connection flow control: "
|
||||
@ -1051,6 +1058,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
size_t size;
|
||||
ngx_buf_t *buf;
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *fc;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_v2_stream_t *stream;
|
||||
ngx_http_v2_srv_conf_t *h2scf;
|
||||
@ -1069,6 +1077,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
}
|
||||
|
||||
r = stream->request;
|
||||
fc = r->connection;
|
||||
|
||||
if (r->reading_body && !r->request_body_no_buffering) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||
@ -1077,6 +1086,13 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
return ngx_http_v2_state_skip_padded(h2c, pos, end);
|
||||
}
|
||||
|
||||
if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||
"skipping http2 DATA frame");
|
||||
|
||||
return ngx_http_v2_state_skip_padded(h2c, pos, end);
|
||||
}
|
||||
|
||||
size = end - pos;
|
||||
|
||||
if (size >= h2c->state.length) {
|
||||
@ -1094,6 +1110,8 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
ngx_http_finalize_request(r, rc);
|
||||
}
|
||||
|
||||
ngx_http_run_posted_requests(fc);
|
||||
|
||||
} else if (size) {
|
||||
buf = stream->preread;
|
||||
|
||||
@ -2095,6 +2113,16 @@ static u_char *
|
||||
ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
u_char *end)
|
||||
{
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||
"http2 SETTINGS frame");
|
||||
|
||||
if (h2c->state.sid) {
|
||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||
"client sent SETTINGS frame with incorrect identifier");
|
||||
|
||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
if (h2c->state.flags == NGX_HTTP_V2_ACK_FLAG) {
|
||||
|
||||
if (h2c->state.length != 0) {
|
||||
@ -2118,9 +2146,6 @@ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||
"http2 SETTINGS frame");
|
||||
|
||||
return ngx_http_v2_state_settings_params(h2c, pos, end);
|
||||
}
|
||||
|
||||
@ -2269,6 +2294,13 @@ ngx_http_v2_state_ping(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end)
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
|
||||
"http2 PING frame");
|
||||
|
||||
if (h2c->state.sid) {
|
||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||
"client sent PING frame with incorrect identifier");
|
||||
|
||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
if (h2c->state.flags & NGX_HTTP_V2_ACK_FLAG) {
|
||||
return ngx_http_v2_state_skip(h2c, pos, end);
|
||||
}
|
||||
@ -2310,6 +2342,13 @@ ngx_http_v2_state_goaway(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_goaway);
|
||||
}
|
||||
|
||||
if (h2c->state.sid) {
|
||||
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
|
||||
"client sent GOAWAY frame with incorrect identifier");
|
||||
|
||||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
h2c->state.length -= NGX_HTTP_V2_GOAWAY_SIZE;
|
||||
|
||||
|
226
src/stream/ngx_stream_set_module.c
Normal file
226
src/stream/ngx_stream_set_module.c
Normal file
@ -0,0 +1,226 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Pavel Pautov
|
||||
* Copyright (C) Nginx, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_stream.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_int_t index;
|
||||
ngx_stream_set_variable_pt set_handler;
|
||||
uintptr_t data;
|
||||
ngx_stream_complex_value_t value;
|
||||
} ngx_stream_set_cmd_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_array_t commands;
|
||||
} ngx_stream_set_srv_conf_t;
|
||||
|
||||
|
||||
static ngx_int_t ngx_stream_set_handler(ngx_stream_session_t *s);
|
||||
static ngx_int_t ngx_stream_set_var(ngx_stream_session_t *s,
|
||||
ngx_stream_variable_value_t *v, uintptr_t data);
|
||||
static ngx_int_t ngx_stream_set_init(ngx_conf_t *cf);
|
||||
static void *ngx_stream_set_create_srv_conf(ngx_conf_t *cf);
|
||||
static char *ngx_stream_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
|
||||
|
||||
static ngx_command_t ngx_stream_set_commands[] = {
|
||||
|
||||
{ ngx_string("set"),
|
||||
NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
|
||||
ngx_stream_set,
|
||||
NGX_STREAM_SRV_CONF_OFFSET,
|
||||
0,
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
static ngx_stream_module_t ngx_stream_set_module_ctx = {
|
||||
NULL, /* preconfiguration */
|
||||
ngx_stream_set_init, /* postconfiguration */
|
||||
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
ngx_stream_set_create_srv_conf, /* create server configuration */
|
||||
NULL /* merge server configuration */
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_stream_set_module = {
|
||||
NGX_MODULE_V1,
|
||||
&ngx_stream_set_module_ctx, /* module context */
|
||||
ngx_stream_set_commands, /* module directives */
|
||||
NGX_STREAM_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_stream_set_handler(ngx_stream_session_t *s)
|
||||
{
|
||||
ngx_str_t str;
|
||||
ngx_uint_t i;
|
||||
ngx_stream_set_cmd_t *cmds;
|
||||
ngx_stream_set_srv_conf_t *scf;
|
||||
ngx_stream_variable_value_t vv;
|
||||
|
||||
scf = ngx_stream_get_module_srv_conf(s, ngx_stream_set_module);
|
||||
cmds = scf->commands.elts;
|
||||
vv = ngx_stream_variable_null_value;
|
||||
|
||||
for (i = 0; i < scf->commands.nelts; i++) {
|
||||
if (ngx_stream_complex_value(s, &cmds[i].value, &str) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (cmds[i].set_handler != NULL) {
|
||||
vv.len = str.len;
|
||||
vv.data = str.data;
|
||||
cmds[i].set_handler(s, &vv, cmds[i].data);
|
||||
|
||||
} else {
|
||||
s->variables[cmds[i].index].len = str.len;
|
||||
s->variables[cmds[i].index].valid = 1;
|
||||
s->variables[cmds[i].index].no_cacheable = 0;
|
||||
s->variables[cmds[i].index].not_found = 0;
|
||||
s->variables[cmds[i].index].data = str.data;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_stream_set_var(ngx_stream_session_t *s, ngx_stream_variable_value_t *v,
|
||||
uintptr_t data)
|
||||
{
|
||||
*v = ngx_stream_variable_null_value;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_stream_set_init(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_stream_handler_pt *h;
|
||||
ngx_stream_core_main_conf_t *cmcf;
|
||||
|
||||
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||
|
||||
h = ngx_array_push(&cmcf->phases[NGX_STREAM_PREACCESS_PHASE].handlers);
|
||||
if (h == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*h = ngx_stream_set_handler;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ngx_stream_set_create_srv_conf(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_stream_set_srv_conf_t *conf;
|
||||
|
||||
conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_set_srv_conf_t));
|
||||
if (conf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* set by ngx_pcalloc():
|
||||
*
|
||||
* conf->commands = { NULL };
|
||||
*/
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_stream_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_stream_set_srv_conf_t *scf = conf;
|
||||
|
||||
ngx_str_t *args;
|
||||
ngx_int_t index;
|
||||
ngx_stream_set_cmd_t *set_cmd;
|
||||
ngx_stream_variable_t *v;
|
||||
ngx_stream_compile_complex_value_t ccv;
|
||||
|
||||
args = cf->args->elts;
|
||||
|
||||
if (args[1].data[0] != '$') {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid variable name \"%V\"", &args[1]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
args[1].len--;
|
||||
args[1].data++;
|
||||
|
||||
v = ngx_stream_add_variable(cf, &args[1],
|
||||
NGX_STREAM_VAR_CHANGEABLE|NGX_STREAM_VAR_WEAK);
|
||||
if (v == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
index = ngx_stream_get_variable_index(cf, &args[1]);
|
||||
if (index == NGX_ERROR) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (v->get_handler == NULL) {
|
||||
v->get_handler = ngx_stream_set_var;
|
||||
}
|
||||
|
||||
if (scf->commands.elts == NULL) {
|
||||
if (ngx_array_init(&scf->commands, cf->pool, 1,
|
||||
sizeof(ngx_stream_set_cmd_t))
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
set_cmd = ngx_array_push(&scf->commands);
|
||||
if (set_cmd == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
set_cmd->index = index;
|
||||
set_cmd->set_handler = v->set_handler;
|
||||
set_cmd->data = v->data;
|
||||
|
||||
ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
|
||||
|
||||
ccv.cf = cf;
|
||||
ccv.value = &args[2];
|
||||
ccv.complex_value = &set_cmd->value;
|
||||
|
||||
if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
Loading…
Reference in New Issue
Block a user