Latest update - GitHub 446ce03
This commit is contained in:
@@ -129,26 +129,6 @@ if test -z "$NGX_KQUEUE_CHECKED"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ "$NGX_SYSTEM" = "NetBSD" ]; then
|
|
||||||
|
|
||||||
# NetBSD 2.0 incompatibly defines kevent.udata as "intptr_t"
|
|
||||||
|
|
||||||
cat << END >> $NGX_AUTO_CONFIG_H
|
|
||||||
|
|
||||||
#define NGX_KQUEUE_UDATA_T
|
|
||||||
|
|
||||||
END
|
|
||||||
|
|
||||||
else
|
|
||||||
cat << END >> $NGX_AUTO_CONFIG_H
|
|
||||||
|
|
||||||
#define NGX_KQUEUE_UDATA_T (void *)
|
|
||||||
|
|
||||||
END
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
ngx_feature="crypt()"
|
ngx_feature="crypt()"
|
||||||
ngx_feature_name="NGX_HAVE_CRYPT"
|
ngx_feature_name="NGX_HAVE_CRYPT"
|
||||||
ngx_feature_run=no
|
ngx_feature_run=no
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ http {
|
|||||||
listen 80;
|
listen 80;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
|
||||||
#charset koi8-r;
|
|
||||||
|
|
||||||
#access_log logs/host.access.log main;
|
#access_log logs/host.access.log main;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
|||||||
@@ -5,6 +5,199 @@
|
|||||||
<change_log title="nginx">
|
<change_log title="nginx">
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.29.1" date="2025-08-13">
|
||||||
|
|
||||||
|
<change type="security">
|
||||||
|
<para lang="ru">
|
||||||
|
обработка специально созданного логина/пароля при использовании
|
||||||
|
метода аутентификации "none" в модуле ngx_mail_smtp_module
|
||||||
|
могла приводить к отправке серверу аутентификации
|
||||||
|
части содержимого памяти рабочего процесса (CVE-2025-53859).
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
processing of a specially crafted login/password when using
|
||||||
|
the "none" authentication method in the ngx_mail_smtp_module
|
||||||
|
might cause worker process memory disclosure
|
||||||
|
to the authentication server (CVE-2025-53859).
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
теперь сжатие сертификатов в протоколе TLSv1.3 по умолчанию запрещено.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
now TLSv1.3 certificate compression is disabled by default.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
директива ssl_certificate_compression.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the "ssl_certificate_compression" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
поддержка 0-RTT в QUIC при использовании OpenSSL 3.5.1 и новее.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
support for 0-RTT in QUIC when using OpenSSL 3.5.1 or newer.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
при использовании HTTP/2 и директивы early_hints
|
||||||
|
ответ 103 мог буферизироваться.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the 103 response might be buffered
|
||||||
|
when using HTTP/2 and the "early_hints" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в обработке заголовков запроса "Host" и ":authority"
|
||||||
|
с одинаковыми значениями при использовании HTTP/2;
|
||||||
|
ошибка появилась в 1.17.9.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in handling "Host" and ":authority" header lines
|
||||||
|
with equal values when using HTTP/2;
|
||||||
|
the bug had appeared in 1.17.9.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в обработке заголовка запроса "Host" с портом
|
||||||
|
при использовании HTTP/3.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in handling "Host" header lines with a port
|
||||||
|
when using HTTP/3.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
nginx не собирался под NetBSD 10.0.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx could not be built on NetBSD 10.0.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
в работе параметра none директивы smtp_auth.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
in the "none" parameter of the "smtp_auth" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
|
<changes ver="1.29.0" date="2025-06-24">
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
поддержка ответа с кодом 103 от proxy- и gRPC-бэкендов;
|
||||||
|
директива early_hints.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
support for response code 103 from proxy and gRPC backends;
|
||||||
|
the "early_hints" directive.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
возможность загрузки секретных ключей с аппаратных устройств
|
||||||
|
с помощью OpenSSL provider.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
loading of secret keys from hardware tokens
|
||||||
|
with OpenSSL provider.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="feature">
|
||||||
|
<para lang="ru">
|
||||||
|
поддержка параметра so_keepalive директивы listen на macOS.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
support for the "so_keepalive" parameter of the "listen" directive on macOS.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
уровень логгирования ошибок SSL в QUIC handshake
|
||||||
|
изменён с уровня error на crit для критических ошибок
|
||||||
|
и на info для всех остальных;
|
||||||
|
уровень логгирования неподдерживаемых транспортных параметров QUIC
|
||||||
|
понижен с уровня info до debug.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the logging level of SSL errors in a QUIC handshake
|
||||||
|
has been changed from "error" to "crit" for critical errors,
|
||||||
|
and to "info" for the rest;
|
||||||
|
the logging level of unsupported QUIC transport parameters
|
||||||
|
has been lowered from "info" to "debug".
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="change">
|
||||||
|
<para lang="ru">
|
||||||
|
бинарная версия nginx/Windows теперь использует для сборки Windows SDK 10.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
the native nginx/Windows binary release is now built using Windows SDK 10.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
nginx не собирался gcc 15,
|
||||||
|
если использовались модули ngx_http_v2_module и ngx_http_v3_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx could not be built by gcc 15
|
||||||
|
if ngx_http_v2_module or ngx_http_v3_module modules were used.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para lang="ru">
|
||||||
|
nginx мог не собираться gcc 14 и новее с оптимизацией -O3 -flto,
|
||||||
|
если использовался модуль ngx_http_v3_module.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
nginx might not be built by gcc 14 or newer with -O3 -flto optimization
|
||||||
|
if ngx_http_v3_module was used.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
<change>
|
||||||
|
<para lang="ru">
|
||||||
|
Исправления и улучшения в HTTP/3.
|
||||||
|
</para>
|
||||||
|
<para lang="en">
|
||||||
|
Bugfixes and improvements in HTTP/3.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
|
</changes>
|
||||||
|
|
||||||
|
|
||||||
<changes ver="1.27.5" date="2025-04-16">
|
<changes ver="1.27.5" date="2025-04-16">
|
||||||
|
|
||||||
<change type="feature">
|
<change type="feature">
|
||||||
|
|||||||
+5
-4
@@ -6,9 +6,9 @@ TEMP = tmp
|
|||||||
|
|
||||||
CC = cl
|
CC = cl
|
||||||
OBJS = objs.msvc8
|
OBJS = objs.msvc8
|
||||||
OPENSSL = openssl-3.0.15
|
OPENSSL = openssl-3.5.2
|
||||||
ZLIB = zlib-1.3.1
|
ZLIB = zlib-1.3.1
|
||||||
PCRE = pcre2-10.39
|
PCRE = pcre2-10.45
|
||||||
|
|
||||||
|
|
||||||
release: export
|
release: export
|
||||||
@@ -76,7 +76,8 @@ win32:
|
|||||||
--with-stream_realip_module \
|
--with-stream_realip_module \
|
||||||
--with-stream_ssl_preread_module \
|
--with-stream_ssl_preread_module \
|
||||||
--with-openssl=$(OBJS)/lib/$(OPENSSL) \
|
--with-openssl=$(OBJS)/lib/$(OPENSSL) \
|
||||||
--with-openssl-opt="no-asm no-tests -D_WIN32_WINNT=0x0501" \
|
--with-openssl-opt="no-asm no-tests no-makedepend \
|
||||||
|
-D_WIN32_WINNT=0x0501" \
|
||||||
--with-http_ssl_module \
|
--with-http_ssl_module \
|
||||||
--with-mail_ssl_module \
|
--with-mail_ssl_module \
|
||||||
--with-stream_ssl_module
|
--with-stream_ssl_module
|
||||||
@@ -109,7 +110,7 @@ zip: export
|
|||||||
cp -p $(OBJS)/lib/$(OPENSSL)/LICENSE.txt \
|
cp -p $(OBJS)/lib/$(OPENSSL)/LICENSE.txt \
|
||||||
$(TEMP)/$(NGINX)/docs/OpenSSL.LICENSE
|
$(TEMP)/$(NGINX)/docs/OpenSSL.LICENSE
|
||||||
|
|
||||||
cp -p $(OBJS)/lib/$(PCRE)/LICENCE \
|
cp -p $(OBJS)/lib/$(PCRE)/LICENCE.md \
|
||||||
$(TEMP)/$(NGINX)/docs/PCRE.LICENCE
|
$(TEMP)/$(NGINX)/docs/PCRE.LICENCE
|
||||||
|
|
||||||
sed -ne '/^ (C) 1995-20/,/^ jloup@gzip\.org/p' \
|
sed -ne '/^ (C) 1995-20/,/^ jloup@gzip\.org/p' \
|
||||||
|
|||||||
+2
-2
@@ -9,8 +9,8 @@
|
|||||||
#define _NGINX_H_INCLUDED_
|
#define _NGINX_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
#define nginx_version 1027006
|
#define nginx_version 1029002
|
||||||
#define NGINX_VERSION "1.27.6"
|
#define NGINX_VERSION "1.29.2"
|
||||||
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
|
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
|
||||||
|
|
||||||
#ifndef NGINX_SERVER
|
#ifndef NGINX_SERVER
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ ngx_thread_pool_exit_handler(void *data, ngx_log_t *log)
|
|||||||
|
|
||||||
*lock = 0;
|
*lock = 0;
|
||||||
|
|
||||||
pthread_exit(0);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,15 @@
|
|||||||
#include <ngx_event.h>
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* NetBSD up to 10.0 incompatibly defines kevent.udata as "intptr_t" */
|
||||||
|
|
||||||
|
#if (__NetBSD__ && __NetBSD_Version__ < 1000000000)
|
||||||
|
#define NGX_KQUEUE_UDATA_T
|
||||||
|
#else
|
||||||
|
#define NGX_KQUEUE_UDATA_T (void *)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_uint_t changes;
|
ngx_uint_t changes;
|
||||||
ngx_uint_t events;
|
ngx_uint_t events;
|
||||||
@@ -191,7 +200,7 @@ ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
|
|||||||
kev.flags = EV_ADD|EV_ENABLE;
|
kev.flags = EV_ADD|EV_ENABLE;
|
||||||
kev.fflags = 0;
|
kev.fflags = 0;
|
||||||
kev.data = timer;
|
kev.data = timer;
|
||||||
kev.udata = 0;
|
kev.udata = NGX_KQUEUE_UDATA_T (uintptr_t) 0;
|
||||||
|
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
@@ -237,7 +246,7 @@ ngx_kqueue_notify_init(ngx_log_t *log)
|
|||||||
notify_kev.data = 0;
|
notify_kev.data = 0;
|
||||||
notify_kev.flags = EV_ADD|EV_CLEAR;
|
notify_kev.flags = EV_ADD|EV_CLEAR;
|
||||||
notify_kev.fflags = 0;
|
notify_kev.fflags = 0;
|
||||||
notify_kev.udata = 0;
|
notify_kev.udata = NGX_KQUEUE_UDATA_T (uintptr_t) 0;
|
||||||
|
|
||||||
if (kevent(ngx_kqueue, ¬ify_kev, 1, NULL, 0, NULL) == -1) {
|
if (kevent(ngx_kqueue, ¬ify_kev, 1, NULL, 0, NULL) == -1) {
|
||||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||||
|
|||||||
@@ -387,6 +387,11 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
|
|||||||
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
|
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SSL_OP_NO_TX_CERTIFICATE_COMPRESSION
|
||||||
|
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TX_CERTIFICATE_COMPRESSION);
|
||||||
|
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_RX_CERTIFICATE_COMPRESSION);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SSL_OP_NO_ANTI_REPLAY
|
#ifdef SSL_OP_NO_ANTI_REPLAY
|
||||||
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY);
|
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_ANTI_REPLAY);
|
||||||
#endif
|
#endif
|
||||||
@@ -659,6 +664,36 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_ssl_certificate_compression(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||||
|
ngx_uint_t enable)
|
||||||
|
{
|
||||||
|
if (!enable) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SSL_OP_NO_TX_CERTIFICATE_COMPRESSION
|
||||||
|
|
||||||
|
if (SSL_CTX_compress_certs(ssl->ctx, 0) == 0) {
|
||||||
|
ngx_ssl_error(NGX_LOG_WARN, ssl->log, 0,
|
||||||
|
"SSL_CTX_compress_certs() failed, ignored");
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TX_CERTIFICATE_COMPRESSION);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
|
||||||
|
"\"ssl_certificate_compression\" is not supported "
|
||||||
|
"on this platform, ignored");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
|
ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
|
||||||
ngx_uint_t prefer_server_ciphers)
|
ngx_uint_t prefer_server_ciphers)
|
||||||
@@ -1374,7 +1409,7 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
|
|||||||
if (SSL_CTX_set0_tmp_dh_pkey(ssl->ctx, dh) != 1) {
|
if (SSL_CTX_set0_tmp_dh_pkey(ssl->ctx, dh) != 1) {
|
||||||
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
|
||||||
"SSL_CTX_set0_tmp_dh_pkey(\"%s\") failed", file->data);
|
"SSL_CTX_set0_tmp_dh_pkey(\"%s\") failed", file->data);
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x3000001fL)
|
#if (OPENSSL_VERSION_NUMBER >= 0x30000010L)
|
||||||
EVP_PKEY_free(dh);
|
EVP_PKEY_free(dh);
|
||||||
#endif
|
#endif
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
@@ -5094,11 +5129,7 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
|
|
||||||
name = SSL_group_to_name(c->ssl->connection, nid);
|
name = SSL_group_to_name(c->ssl->connection, nid);
|
||||||
#else
|
|
||||||
name = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s->len = name ? ngx_strlen(name) : sizeof("0x0000") - 1;
|
s->len = name ? ngx_strlen(name) : sizeof("0x0000") - 1;
|
||||||
s->data = ngx_pnalloc(pool, s->len);
|
s->data = ngx_pnalloc(pool, s->len);
|
||||||
@@ -5152,11 +5183,7 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
|||||||
nid = curves[i];
|
nid = curves[i];
|
||||||
|
|
||||||
if (nid & TLSEXT_nid_unknown) {
|
if (nid & TLSEXT_nid_unknown) {
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
|
|
||||||
name = SSL_group_to_name(c->ssl->connection, nid);
|
name = SSL_group_to_name(c->ssl->connection, nid);
|
||||||
#else
|
|
||||||
name = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
len += name ? ngx_strlen(name) : sizeof("0x0000") - 1;
|
len += name ? ngx_strlen(name) : sizeof("0x0000") - 1;
|
||||||
|
|
||||||
@@ -5178,11 +5205,7 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
|
|||||||
nid = curves[i];
|
nid = curves[i];
|
||||||
|
|
||||||
if (nid & TLSEXT_nid_unknown) {
|
if (nid & TLSEXT_nid_unknown) {
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
|
|
||||||
name = SSL_group_to_name(c->ssl->connection, nid);
|
name = SSL_group_to_name(c->ssl->connection, nid);
|
||||||
#else
|
|
||||||
name = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p = name ? ngx_cpymem(p, name, ngx_strlen(name))
|
p = name ? ngx_cpymem(p, name, ngx_strlen(name))
|
||||||
: ngx_sprintf(p, "0x%04xd", nid & 0xffff);
|
: ngx_sprintf(p, "0x%04xd", nid & 0xffff);
|
||||||
|
|||||||
@@ -96,6 +96,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
|
||||||
|
#define SSL_group_to_name(s, nid) NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
|
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -245,6 +250,8 @@ ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
|||||||
ngx_int_t ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
|
ngx_int_t ngx_ssl_connection_certificate(ngx_connection_t *c, ngx_pool_t *pool,
|
||||||
ngx_str_t *cert, ngx_str_t *key, ngx_ssl_cache_t *cache,
|
ngx_str_t *cert, ngx_str_t *key, ngx_ssl_cache_t *cache,
|
||||||
ngx_array_t *passwords);
|
ngx_array_t *passwords);
|
||||||
|
ngx_int_t ngx_ssl_certificate_compression(ngx_conf_t *cf, ngx_ssl_t *ssl,
|
||||||
|
ngx_uint_t enable);
|
||||||
|
|
||||||
ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
|
ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers,
|
||||||
ngx_uint_t prefer_server_ciphers);
|
ngx_uint_t prefer_server_ciphers);
|
||||||
|
|||||||
@@ -707,7 +707,7 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0);
|
pkey = ENGINE_load_private_key(engine, (char *) last, NULL, NULL);
|
||||||
|
|
||||||
if (pkey == NULL) {
|
if (pkey == NULL) {
|
||||||
*err = "ENGINE_load_private_key() failed";
|
*err = "ENGINE_load_private_key() failed";
|
||||||
|
|||||||
@@ -964,7 +964,7 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
|
|||||||
qc = ngx_quic_get_connection(c);
|
qc = ngx_quic_get_connection(c);
|
||||||
|
|
||||||
qc->error = 0;
|
qc->error = 0;
|
||||||
qc->error_reason = 0;
|
qc->error_reason = NULL;
|
||||||
|
|
||||||
c->log->action = "decrypting packet";
|
c->log->action = "decrypting packet";
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <ngx_core.h>
|
#include <ngx_core.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef OSSL_RECORD_PROTECTION_LEVEL_NONE
|
#if (OPENSSL_VERSION_NUMBER >= 0x30500010L)
|
||||||
#define NGX_QUIC_OPENSSL_API 1
|
#define NGX_QUIC_OPENSSL_API 1
|
||||||
|
|
||||||
#elif (defined SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION)
|
#elif (defined SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION)
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
||||||
&prev->types_keys, &prev->types,
|
&prev->types_keys, &prev->types,
|
||||||
ngx_http_html_default_types)
|
ngx_http_html_default_types)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,7 +253,8 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r)
|
|||||||
pwd.len = i - passwd;
|
pwd.len = i - passwd;
|
||||||
pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
|
pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
|
||||||
if (pwd.data == NULL) {
|
if (pwd.data == NULL) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
|
ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
|
||||||
|
|||||||
@@ -1564,7 +1564,7 @@ ngx_http_charset_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
||||||
&prev->types_keys, &prev->types,
|
&prev->types_keys, &prev->types,
|
||||||
ngx_http_charset_default_types)
|
ngx_http_charset_default_types)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3130,7 +3130,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
||||||
prev->upstream.temp_path,
|
prev->upstream.temp_path,
|
||||||
&ngx_http_fastcgi_temp_path)
|
&ngx_http_fastcgi_temp_path)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1869,7 +1869,8 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
|
|||||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status < NGX_HTTP_OK) {
|
if (status < NGX_HTTP_OK && status != NGX_HTTP_EARLY_HINTS)
|
||||||
|
{
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"upstream sent unexpected :status \"%V\"",
|
"upstream sent unexpected :status \"%V\"",
|
||||||
status_line);
|
status_line);
|
||||||
@@ -1902,6 +1903,10 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
|
|||||||
h->lowcase_key = h->key.data;
|
h->lowcase_key = h->key.data;
|
||||||
h->hash = ngx_hash_key(h->key.data, h->key.len);
|
h->hash = ngx_hash_key(h->key.data, h->key.len);
|
||||||
|
|
||||||
|
if (u->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||||
h->lowcase_key, h->key.len);
|
h->lowcase_key, h->key.len);
|
||||||
|
|
||||||
@@ -1923,6 +1928,17 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
|
|||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"grpc header done");
|
"grpc header done");
|
||||||
|
|
||||||
|
if (u->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
|
||||||
|
if (ctx->end_stream) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"upstream prematurely closed stream");
|
||||||
|
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->status = 0;
|
||||||
|
return NGX_HTTP_UPSTREAM_EARLY_HINTS;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->end_stream) {
|
if (ctx->end_stream) {
|
||||||
u->headers_in.content_length_n = 0;
|
u->headers_in.content_length_n = 0;
|
||||||
|
|
||||||
@@ -4413,6 +4429,7 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
|
|||||||
conf->upstream.pass_request_body = 1;
|
conf->upstream.pass_request_body = 1;
|
||||||
conf->upstream.force_ranges = 0;
|
conf->upstream.force_ranges = 0;
|
||||||
conf->upstream.pass_trailers = 1;
|
conf->upstream.pass_trailers = 1;
|
||||||
|
conf->upstream.pass_early_hints = 1;
|
||||||
conf->upstream.preserve_output = 1;
|
conf->upstream.preserve_output = 1;
|
||||||
|
|
||||||
conf->headers_source = NGX_CONF_UNSET_PTR;
|
conf->headers_source = NGX_CONF_UNSET_PTR;
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ctx->zstream.next_in = Z_NULL;
|
ctx->zstream.next_in = NULL;
|
||||||
ctx->zstream.avail_in = 0;
|
ctx->zstream.avail_in = 0;
|
||||||
|
|
||||||
ctx->zstream.zalloc = ngx_http_gunzip_filter_alloc;
|
ctx->zstream.zalloc = ngx_http_gunzip_filter_alloc;
|
||||||
|
|||||||
@@ -1115,7 +1115,7 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
||||||
&prev->types_keys, &prev->types,
|
&prev->types_keys, &prev->types,
|
||||||
ngx_http_html_default_types)
|
ngx_http_html_default_types)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1877,6 +1877,13 @@ ngx_http_proxy_process_status_line(ngx_http_request_t *r)
|
|||||||
u->headers_in.status_n, &u->headers_in.status_line);
|
u->headers_in.status_n, &u->headers_in.status_line);
|
||||||
|
|
||||||
if (ctx->status.http_version < NGX_HTTP_VERSION_11) {
|
if (ctx->status.http_version < NGX_HTTP_VERSION_11) {
|
||||||
|
|
||||||
|
if (ctx->status.code == NGX_HTTP_EARLY_HINTS) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"upstream sent HTTP/1.0 response with early hints");
|
||||||
|
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
u->headers_in.connection_close = 1;
|
u->headers_in.connection_close = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1938,6 +1945,14 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||||||
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
|
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http proxy header: \"%V: %V\"",
|
||||||
|
&h->key, &h->value);
|
||||||
|
|
||||||
|
if (r->upstream->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
|
||||||
h->lowcase_key, h->key.len);
|
h->lowcase_key, h->key.len);
|
||||||
|
|
||||||
@@ -1949,10 +1964,6 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
|
||||||
"http proxy header: \"%V: %V\"",
|
|
||||||
&h->key, &h->value);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1963,6 +1974,20 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"http proxy header done");
|
"http proxy header done");
|
||||||
|
|
||||||
|
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
||||||
|
|
||||||
|
if (r->upstream->headers_in.status_n == NGX_HTTP_EARLY_HINTS) {
|
||||||
|
ctx->status.code = 0;
|
||||||
|
ctx->status.count = 0;
|
||||||
|
ctx->status.start = NULL;
|
||||||
|
ctx->status.end = NULL;
|
||||||
|
|
||||||
|
r->upstream->process_header =
|
||||||
|
ngx_http_proxy_process_status_line;
|
||||||
|
r->state = 0;
|
||||||
|
return NGX_HTTP_UPSTREAM_EARLY_HINTS;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if no "Server" and "Date" in header line,
|
* if no "Server" and "Date" in header line,
|
||||||
* then add the special empty headers
|
* then add the special empty headers
|
||||||
@@ -2010,8 +2035,6 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
|
|||||||
* connections alive in case of r->header_only or X-Accel-Redirect
|
* connections alive in case of r->header_only or X-Accel-Redirect
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
|
||||||
|
|
||||||
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||||
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
|
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
|
||||||
|| ctx->head
|
|| ctx->head
|
||||||
@@ -3422,10 +3445,10 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
|||||||
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
|
conf->ssl_conf_commands = NGX_CONF_UNSET_PTR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* "proxy_cyclic_temp_file" is disabled */
|
/* the hardcoded values */
|
||||||
conf->upstream.cyclic_temp_file = 0;
|
conf->upstream.cyclic_temp_file = 0;
|
||||||
|
|
||||||
conf->upstream.change_buffering = 1;
|
conf->upstream.change_buffering = 1;
|
||||||
|
conf->upstream.pass_early_hints = 1;
|
||||||
|
|
||||||
conf->headers_source = NGX_CONF_UNSET_PTR;
|
conf->headers_source = NGX_CONF_UNSET_PTR;
|
||||||
|
|
||||||
@@ -3638,7 +3661,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
||||||
prev->upstream.temp_path,
|
prev->upstream.temp_path,
|
||||||
&ngx_http_proxy_temp_path)
|
&ngx_http_proxy_temp_path)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1543,7 +1543,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
||||||
prev->upstream.temp_path,
|
prev->upstream.temp_path,
|
||||||
&ngx_http_scgi_temp_path)
|
&ngx_http_scgi_temp_path)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -820,7 +820,7 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (prm = cmd->params; prm->name.len; prm++) {
|
for (prm = cmd->params; prm->name.len; prm++) {
|
||||||
if (prm->mandatory && params[prm->index] == 0) {
|
if (prm->mandatory && params[prm->index] == NULL) {
|
||||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
"mandatory \"%V\" parameter is absent "
|
"mandatory \"%V\" parameter is absent "
|
||||||
"in \"%V\" SSI command",
|
"in \"%V\" SSI command",
|
||||||
@@ -2942,7 +2942,7 @@ ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
||||||
&prev->types_keys, &prev->types,
|
&prev->types_keys, &prev->types,
|
||||||
ngx_http_html_default_types)
|
ngx_http_html_default_types)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,13 @@ static ngx_command_t ngx_http_ssl_commands[] = {
|
|||||||
0,
|
0,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_certificate_compression"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
|
||||||
|
ngx_conf_set_flag_slot,
|
||||||
|
NGX_HTTP_SRV_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_ssl_srv_conf_t, certificate_compression),
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_dhparam"),
|
{ ngx_string("ssl_dhparam"),
|
||||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
@@ -656,6 +663,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
sscf->prefer_server_ciphers = NGX_CONF_UNSET;
|
sscf->prefer_server_ciphers = NGX_CONF_UNSET;
|
||||||
|
sscf->certificate_compression = NGX_CONF_UNSET;
|
||||||
sscf->early_data = NGX_CONF_UNSET;
|
sscf->early_data = NGX_CONF_UNSET;
|
||||||
sscf->reject_handshake = NGX_CONF_UNSET;
|
sscf->reject_handshake = NGX_CONF_UNSET;
|
||||||
sscf->buffer_size = NGX_CONF_UNSET_SIZE;
|
sscf->buffer_size = NGX_CONF_UNSET_SIZE;
|
||||||
@@ -698,6 +706,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
||||||
prev->prefer_server_ciphers, 1);
|
prev->prefer_server_ciphers, 1);
|
||||||
|
|
||||||
|
ngx_conf_merge_value(conf->certificate_compression,
|
||||||
|
prev->certificate_compression, 0);
|
||||||
|
|
||||||
ngx_conf_merge_value(conf->early_data, prev->early_data, 1);
|
ngx_conf_merge_value(conf->early_data, prev->early_data, 1);
|
||||||
ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
|
ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
|
||||||
|
|
||||||
@@ -846,6 +857,13 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_ssl_certificate_compression(cf, &conf->ssl,
|
||||||
|
conf->certificate_compression)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conf->ssl.buffer_size = conf->buffer_size;
|
conf->ssl.buffer_size = conf->buffer_size;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ typedef struct {
|
|||||||
ngx_ssl_t ssl;
|
ngx_ssl_t ssl;
|
||||||
|
|
||||||
ngx_flag_t prefer_server_ciphers;
|
ngx_flag_t prefer_server_ciphers;
|
||||||
|
ngx_flag_t certificate_compression;
|
||||||
ngx_flag_t early_data;
|
ngx_flag_t early_data;
|
||||||
ngx_flag_t reject_handshake;
|
ngx_flag_t reject_handshake;
|
||||||
|
|
||||||
|
|||||||
@@ -901,7 +901,7 @@ ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
||||||
&prev->types_keys, &prev->types,
|
&prev->types_keys, &prev->types,
|
||||||
ngx_http_html_default_types)
|
ngx_http_html_default_types)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1803,7 +1803,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
||||||
prev->upstream.temp_path,
|
prev->upstream.temp_path,
|
||||||
&ngx_http_uwsgi_temp_path)
|
&ngx_http_uwsgi_temp_path)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1112,7 +1112,7 @@ ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
||||||
&prev->types_keys, &prev->types,
|
&prev->types_keys, &prev->types,
|
||||||
ngx_http_xslt_default_types)
|
ngx_http_xslt_default_types)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ ngx_uint_t ngx_http_max_module;
|
|||||||
|
|
||||||
|
|
||||||
ngx_http_output_header_filter_pt ngx_http_top_header_filter;
|
ngx_http_output_header_filter_pt ngx_http_top_header_filter;
|
||||||
|
ngx_http_output_header_filter_pt ngx_http_top_early_hints_filter;
|
||||||
ngx_http_output_body_filter_pt ngx_http_top_body_filter;
|
ngx_http_output_body_filter_pt ngx_http_top_body_filter;
|
||||||
ngx_http_request_body_filter_pt ngx_http_top_request_body_filter;
|
ngx_http_request_body_filter_pt ngx_http_top_request_body_filter;
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -122,7 +122,6 @@ ngx_int_t ngx_http_parse_chunked(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
|
|
||||||
ngx_http_request_t *ngx_http_create_request(ngx_connection_t *c);
|
ngx_http_request_t *ngx_http_create_request(ngx_connection_t *c);
|
||||||
ngx_int_t ngx_http_process_request_uri(ngx_http_request_t *r);
|
ngx_int_t ngx_http_process_request_uri(ngx_http_request_t *r);
|
||||||
ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
|
|
||||||
void ngx_http_process_request(ngx_http_request_t *r);
|
void ngx_http_process_request(ngx_http_request_t *r);
|
||||||
void ngx_http_update_location_config(ngx_http_request_t *r);
|
void ngx_http_update_location_config(ngx_http_request_t *r);
|
||||||
void ngx_http_handler(ngx_http_request_t *r);
|
void ngx_http_handler(ngx_http_request_t *r);
|
||||||
@@ -152,6 +151,7 @@ ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
|
|||||||
ngx_int_t ngx_http_read_unbuffered_request_body(ngx_http_request_t *r);
|
ngx_int_t ngx_http_read_unbuffered_request_body(ngx_http_request_t *r);
|
||||||
|
|
||||||
ngx_int_t ngx_http_send_header(ngx_http_request_t *r);
|
ngx_int_t ngx_http_send_header(ngx_http_request_t *r);
|
||||||
|
ngx_int_t ngx_http_send_early_hints(ngx_http_request_t *r);
|
||||||
ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r,
|
ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r,
|
||||||
ngx_int_t error);
|
ngx_int_t error);
|
||||||
ngx_int_t ngx_http_filter_finalize_request(ngx_http_request_t *r,
|
ngx_int_t ngx_http_filter_finalize_request(ngx_http_request_t *r,
|
||||||
@@ -191,6 +191,7 @@ extern ngx_str_t ngx_http_html_default_types[];
|
|||||||
|
|
||||||
|
|
||||||
extern ngx_http_output_header_filter_pt ngx_http_top_header_filter;
|
extern ngx_http_output_header_filter_pt ngx_http_top_header_filter;
|
||||||
|
extern ngx_http_output_header_filter_pt ngx_http_top_early_hints_filter;
|
||||||
extern ngx_http_output_body_filter_pt ngx_http_top_body_filter;
|
extern ngx_http_output_body_filter_pt ngx_http_top_body_filter;
|
||||||
extern ngx_http_request_body_filter_pt ngx_http_top_request_body_filter;
|
extern ngx_http_request_body_filter_pt ngx_http_top_request_body_filter;
|
||||||
|
|
||||||
|
|||||||
@@ -670,6 +670,13 @@ static ngx_command_t ngx_http_core_commands[] = {
|
|||||||
offsetof(ngx_http_core_loc_conf_t, etag),
|
offsetof(ngx_http_core_loc_conf_t, etag),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("early_hints"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
|
||||||
|
ngx_http_set_predicate_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_core_loc_conf_t, early_hints),
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("error_page"),
|
{ ngx_string("error_page"),
|
||||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|
||||||
|NGX_CONF_2MORE,
|
|NGX_CONF_2MORE,
|
||||||
@@ -1857,6 +1864,37 @@ ngx_http_send_header(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_send_early_hints(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
|
||||||
|
if (r->post_action) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->header_sent) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||||
|
"header already sent");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
rc = ngx_http_test_predicates(r, clcf->early_hints);
|
||||||
|
|
||||||
|
if (rc != NGX_DECLINED) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http send early hints \"%V?%V\"", &r->uri, &r->args);
|
||||||
|
|
||||||
|
return ngx_http_top_early_hints_filter(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||||
{
|
{
|
||||||
@@ -3637,6 +3675,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
|
|||||||
clcf->chunked_transfer_encoding = NGX_CONF_UNSET;
|
clcf->chunked_transfer_encoding = NGX_CONF_UNSET;
|
||||||
clcf->etag = NGX_CONF_UNSET;
|
clcf->etag = NGX_CONF_UNSET;
|
||||||
clcf->server_tokens = NGX_CONF_UNSET_UINT;
|
clcf->server_tokens = NGX_CONF_UNSET_UINT;
|
||||||
|
clcf->early_hints = NGX_CONF_UNSET_PTR;
|
||||||
clcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
|
clcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
|
||||||
clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
|
clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
|
||||||
|
|
||||||
@@ -3892,7 +3931,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
if (ngx_conf_merge_path_value(cf, &conf->client_body_temp_path,
|
if (ngx_conf_merge_path_value(cf, &conf->client_body_temp_path,
|
||||||
prev->client_body_temp_path,
|
prev->client_body_temp_path,
|
||||||
&ngx_http_client_temp_path)
|
&ngx_http_client_temp_path)
|
||||||
!= NGX_OK)
|
!= NGX_CONF_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
@@ -3917,6 +3956,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_conf_merge_uint_value(conf->server_tokens, prev->server_tokens,
|
ngx_conf_merge_uint_value(conf->server_tokens, prev->server_tokens,
|
||||||
NGX_HTTP_SERVER_TOKENS_ON);
|
NGX_HTTP_SERVER_TOKENS_ON);
|
||||||
|
|
||||||
|
ngx_conf_merge_ptr_value(conf->early_hints, prev->early_hints, NULL);
|
||||||
|
|
||||||
ngx_conf_merge_ptr_value(conf->open_file_cache,
|
ngx_conf_merge_ptr_value(conf->open_file_cache,
|
||||||
prev->open_file_cache, NULL);
|
prev->open_file_cache, NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -430,6 +430,8 @@ struct ngx_http_core_loc_conf_s {
|
|||||||
ngx_http_complex_value_t *disable_symlinks_from;
|
ngx_http_complex_value_t *disable_symlinks_from;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ngx_array_t *early_hints; /* early_hints */
|
||||||
|
|
||||||
ngx_array_t *error_pages; /* error_page */
|
ngx_array_t *error_pages; /* error_page */
|
||||||
|
|
||||||
ngx_path_t *client_body_temp_path; /* client_body_temp_path */
|
ngx_path_t *client_body_temp_path; /* client_body_temp_path */
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
static ngx_int_t ngx_http_header_filter_init(ngx_conf_t *cf);
|
static ngx_int_t ngx_http_header_filter_init(ngx_conf_t *cf);
|
||||||
static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_early_hints_filter(ngx_http_request_t *r);
|
||||||
|
|
||||||
|
|
||||||
static ngx_http_module_t ngx_http_header_filter_module_ctx = {
|
static ngx_http_module_t ngx_http_header_filter_module_ctx = {
|
||||||
@@ -50,6 +51,9 @@ static u_char ngx_http_server_string[] = "Server: " NGINX_SERVER CRLF;
|
|||||||
static u_char ngx_http_server_full_string[] = "Server: " NGINX_SERVER_FULL CRLF;
|
static u_char ngx_http_server_full_string[] = "Server: " NGINX_SERVER_FULL CRLF;
|
||||||
static u_char ngx_http_server_build_string[] = "Server: " NGINX_SERVER_FULL_BUILD CRLF;
|
static u_char ngx_http_server_build_string[] = "Server: " NGINX_SERVER_FULL_BUILD CRLF;
|
||||||
|
|
||||||
|
static ngx_str_t ngx_http_early_hints_status_line =
|
||||||
|
ngx_string("HTTP/1.1 103 Early Hints" CRLF);
|
||||||
|
|
||||||
|
|
||||||
static ngx_str_t ngx_http_status_lines[] = {
|
static ngx_str_t ngx_http_status_lines[] = {
|
||||||
|
|
||||||
@@ -625,10 +629,113 @@ ngx_http_header_filter(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_early_hints_filter(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
ngx_buf_t *b;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_chain_t out;
|
||||||
|
ngx_list_part_t *part;
|
||||||
|
ngx_table_elt_t *header;
|
||||||
|
|
||||||
|
if (r != r->main) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->http_version < NGX_HTTP_VERSION_11) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
part = &r->headers_out.headers.part;
|
||||||
|
header = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
header = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].hash == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len
|
||||||
|
+ sizeof(CRLF) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += ngx_http_early_hints_status_line.len
|
||||||
|
/* the end of the early hints */
|
||||||
|
+ sizeof(CRLF) - 1;
|
||||||
|
|
||||||
|
b = ngx_create_temp_buf(r->pool, len);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->last = ngx_copy(b->last, ngx_http_early_hints_status_line.data,
|
||||||
|
ngx_http_early_hints_status_line.len);
|
||||||
|
|
||||||
|
part = &r->headers_out.headers.part;
|
||||||
|
header = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
header = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].hash == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
|
||||||
|
*b->last++ = ':'; *b->last++ = ' ';
|
||||||
|
|
||||||
|
b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len);
|
||||||
|
*b->last++ = CR; *b->last++ = LF;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"%*s", (size_t) (b->last - b->pos), b->pos);
|
||||||
|
|
||||||
|
/* the end of HTTP early hints */
|
||||||
|
*b->last++ = CR; *b->last++ = LF;
|
||||||
|
|
||||||
|
r->header_size = b->last - b->pos;
|
||||||
|
|
||||||
|
b->flush = 1;
|
||||||
|
|
||||||
|
out.buf = b;
|
||||||
|
out.next = NULL;
|
||||||
|
|
||||||
|
return ngx_http_write_filter(r, &out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_header_filter_init(ngx_conf_t *cf)
|
ngx_http_header_filter_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
ngx_http_top_header_filter = ngx_http_header_filter;
|
ngx_http_top_header_filter = ngx_http_header_filter;
|
||||||
|
ngx_http_top_early_hints_filter = ngx_http_early_hints_filter;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,7 @@ static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
|
|||||||
static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
|
||||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
|
static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
|
||||||
ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
|
ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
|
||||||
ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
|
ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
|
||||||
@@ -1984,7 +1985,7 @@ ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_process_request_header(ngx_http_request_t *r)
|
ngx_http_process_request_header(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
if (r->headers_in.server.len == 0
|
if (r->headers_in.server.len == 0
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
#define NGX_HTTP_CONTINUE 100
|
#define NGX_HTTP_CONTINUE 100
|
||||||
#define NGX_HTTP_SWITCHING_PROTOCOLS 101
|
#define NGX_HTTP_SWITCHING_PROTOCOLS 101
|
||||||
#define NGX_HTTP_PROCESSING 102
|
#define NGX_HTTP_PROCESSING 102
|
||||||
|
#define NGX_HTTP_EARLY_HINTS 103
|
||||||
|
|
||||||
#define NGX_HTTP_OK 200
|
#define NGX_HTTP_OK 200
|
||||||
#define NGX_HTTP_CREATED 201
|
#define NGX_HTTP_CREATED 201
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
|
|||||||
static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r);
|
static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r);
|
||||||
static void ngx_http_upstream_process_header(ngx_http_request_t *r,
|
static void ngx_http_upstream_process_header(ngx_http_request_t *r,
|
||||||
ngx_http_upstream_t *u);
|
ngx_http_upstream_t *u);
|
||||||
|
static ngx_int_t ngx_http_upstream_process_early_hints(ngx_http_request_t *r,
|
||||||
|
ngx_http_upstream_t *u);
|
||||||
|
static void ngx_http_upstream_early_hints_writer(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
|
||||||
ngx_http_upstream_t *u);
|
ngx_http_upstream_t *u);
|
||||||
static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
|
||||||
@@ -1120,7 +1123,7 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN || rc == NGX_HTTP_UPSTREAM_EARLY_HINTS) {
|
||||||
rc = NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
rc = NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2530,6 +2533,18 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_HTTP_UPSTREAM_EARLY_HINTS) {
|
||||||
|
rc = ngx_http_upstream_process_early_hints(r, u);
|
||||||
|
|
||||||
|
if (rc == NGX_OK) {
|
||||||
|
rc = u->process_header(r);
|
||||||
|
|
||||||
|
if (rc == NGX_AGAIN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2567,6 +2582,148 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_upstream_process_early_hints(ngx_http_request_t *r,
|
||||||
|
ngx_http_upstream_t *u)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_list_part_t *part;
|
||||||
|
ngx_table_elt_t *h, *ho;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
|
||||||
|
c = r->connection;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream early hints");
|
||||||
|
|
||||||
|
if (u->conf->pass_early_hints) {
|
||||||
|
|
||||||
|
u->early_hints_length += u->buffer.pos - u->buffer.start;
|
||||||
|
|
||||||
|
if (u->early_hints_length <= (off_t) u->conf->buffer_size) {
|
||||||
|
|
||||||
|
part = &u->headers_in.headers.part;
|
||||||
|
h = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
h = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
|
||||||
|
h[i].lowcase_key, h[i].key.len))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ho = ngx_list_push(&r->headers_out.headers);
|
||||||
|
if (ho == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ho = h[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_send_early_hints(r) == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->buffered) {
|
||||||
|
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->write_event_handler = ngx_http_upstream_early_hints_writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
|
"upstream sent too big early hints");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_http_clean_header(r);
|
||||||
|
|
||||||
|
ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
|
||||||
|
u->headers_in.content_length_n = -1;
|
||||||
|
u->headers_in.last_modified_time = -1;
|
||||||
|
|
||||||
|
if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
|
||||||
|
sizeof(ngx_table_elt_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_list_init(&u->headers_in.trailers, r->pool, 2,
|
||||||
|
sizeof(ngx_table_elt_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = u->buffer.pos;
|
||||||
|
|
||||||
|
u->buffer.pos = u->buffer.start;
|
||||||
|
|
||||||
|
#if (NGX_HTTP_CACHE)
|
||||||
|
|
||||||
|
if (r->cache) {
|
||||||
|
u->buffer.pos += r->cache->header_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u->buffer.last = ngx_movemem(u->buffer.pos, p, u->buffer.last - p);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_http_upstream_early_hints_writer(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_http_upstream_t *u;
|
||||||
|
|
||||||
|
c = r->connection;
|
||||||
|
u = r->upstream;
|
||||||
|
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
|
"http upstream early hints writer");
|
||||||
|
|
||||||
|
c->log->action = "sending early hints to client";
|
||||||
|
|
||||||
|
if (ngx_http_write_filter(r, NULL) == NGX_ERROR) {
|
||||||
|
ngx_http_upstream_finalize_request(r, u,
|
||||||
|
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c->buffered) {
|
||||||
|
if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
|
||||||
|
r->write_event_handler =
|
||||||
|
ngx_http_upstream_wr_check_broken_connection;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
r->write_event_handler = ngx_http_request_empty_handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
|
||||||
|
ngx_http_upstream_finalize_request(r, u,
|
||||||
|
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
|NGX_HTTP_UPSTREAM_FT_HTTP_429)
|
|NGX_HTTP_UPSTREAM_FT_HTTP_429)
|
||||||
|
|
||||||
#define NGX_HTTP_UPSTREAM_INVALID_HEADER 40
|
#define NGX_HTTP_UPSTREAM_INVALID_HEADER 40
|
||||||
|
#define NGX_HTTP_UPSTREAM_EARLY_HINTS 41
|
||||||
|
|
||||||
|
|
||||||
#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT 0x00000002
|
#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT 0x00000002
|
||||||
@@ -184,6 +185,8 @@ typedef struct {
|
|||||||
ngx_flag_t request_buffering;
|
ngx_flag_t request_buffering;
|
||||||
ngx_flag_t pass_request_headers;
|
ngx_flag_t pass_request_headers;
|
||||||
ngx_flag_t pass_request_body;
|
ngx_flag_t pass_request_body;
|
||||||
|
ngx_flag_t pass_trailers;
|
||||||
|
ngx_flag_t pass_early_hints;
|
||||||
|
|
||||||
ngx_flag_t ignore_client_abort;
|
ngx_flag_t ignore_client_abort;
|
||||||
ngx_flag_t intercept_errors;
|
ngx_flag_t intercept_errors;
|
||||||
@@ -232,7 +235,6 @@ typedef struct {
|
|||||||
signed store:2;
|
signed store:2;
|
||||||
unsigned intercept_404:1;
|
unsigned intercept_404:1;
|
||||||
unsigned change_buffering:1;
|
unsigned change_buffering:1;
|
||||||
unsigned pass_trailers:1;
|
|
||||||
unsigned preserve_output:1;
|
unsigned preserve_output:1;
|
||||||
|
|
||||||
#if (NGX_HTTP_SSL || NGX_COMPAT)
|
#if (NGX_HTTP_SSL || NGX_COMPAT)
|
||||||
@@ -354,6 +356,7 @@ struct ngx_http_upstream_s {
|
|||||||
|
|
||||||
ngx_buf_t buffer;
|
ngx_buf_t buffer;
|
||||||
off_t length;
|
off_t length;
|
||||||
|
off_t early_hints_length;
|
||||||
|
|
||||||
ngx_chain_t *out_bufs;
|
ngx_chain_t *out_bufs;
|
||||||
ngx_chain_t *busy_bufs;
|
ngx_chain_t *busy_bufs;
|
||||||
|
|||||||
+136
-37
@@ -158,6 +158,7 @@ static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r);
|
|||||||
static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r,
|
||||||
ngx_http_v2_header_t *header);
|
ngx_http_v2_header_t *header);
|
||||||
static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_v2_construct_host_header(ngx_http_request_t *r);
|
||||||
static void ngx_http_v2_run_request(ngx_http_request_t *r);
|
static void ngx_http_v2_run_request(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r,
|
||||||
u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush);
|
u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush);
|
||||||
@@ -3526,44 +3527,40 @@ ngx_http_v2_parse_scheme(ngx_http_request_t *r, ngx_str_t *value)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
|
ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value)
|
||||||
{
|
{
|
||||||
ngx_table_elt_t *h;
|
ngx_int_t rc;
|
||||||
ngx_http_header_t *hh;
|
|
||||||
ngx_http_core_main_conf_t *cmcf;
|
|
||||||
|
|
||||||
static ngx_str_t host = ngx_string("host");
|
if (r->host_start) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
h = ngx_list_push(&r->headers_in.headers);
|
"client sent duplicate \":authority\" header");
|
||||||
if (h == NULL) {
|
return NGX_DECLINED;
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't');
|
r->host_start = value->data;
|
||||||
|
r->host_end = value->data + value->len;
|
||||||
|
|
||||||
h->key.len = host.len;
|
rc = ngx_http_validate_host(value, r->pool, 0);
|
||||||
h->key.data = host.data;
|
|
||||||
|
|
||||||
h->value.len = value->len;
|
if (rc == NGX_DECLINED) {
|
||||||
h->value.data = value->data;
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"client sent invalid \":authority\" header");
|
||||||
h->lowcase_key = host.data;
|
return NGX_DECLINED;
|
||||||
|
|
||||||
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
|
|
||||||
|
|
||||||
hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
|
|
||||||
h->lowcase_key, h->key.len);
|
|
||||||
|
|
||||||
if (hh == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hh->handler(r, h, hh->offset) != NGX_OK) {
|
if (rc == NGX_ERROR) {
|
||||||
|
ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
return NGX_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_set_virtual_server(r, value) == NGX_ERROR) {
|
||||||
/*
|
/*
|
||||||
* request has been finalized already
|
* request has been finalized already
|
||||||
* in ngx_http_process_host()
|
* in ngx_http_set_virtual_server()
|
||||||
*/
|
*/
|
||||||
return NGX_ABORT;
|
return NGX_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->headers_in.server = *value;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3734,7 +3731,54 @@ ngx_http_v2_construct_cookie_header(ngx_http_request_t *r)
|
|||||||
if (hh->handler(r, h, hh->offset) != NGX_OK) {
|
if (hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||||
/*
|
/*
|
||||||
* request has been finalized already
|
* request has been finalized already
|
||||||
* in ngx_http_process_multi_header_lines()
|
* in ngx_http_process_header_line()
|
||||||
|
*/
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_v2_construct_host_header(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_table_elt_t *h;
|
||||||
|
ngx_http_header_t *hh;
|
||||||
|
ngx_http_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
|
static ngx_str_t host = ngx_string("host");
|
||||||
|
|
||||||
|
h = ngx_list_push(&r->headers_in.headers);
|
||||||
|
if (h == NULL) {
|
||||||
|
ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't');
|
||||||
|
|
||||||
|
h->key.len = host.len;
|
||||||
|
h->key.data = host.data;
|
||||||
|
|
||||||
|
h->value.len = r->host_end - r->host_start;
|
||||||
|
h->value.data = r->host_start;
|
||||||
|
|
||||||
|
h->lowcase_key = host.data;
|
||||||
|
|
||||||
|
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
|
||||||
|
h->lowcase_key, h->key.len);
|
||||||
|
|
||||||
|
if (hh == NULL) {
|
||||||
|
ngx_http_v2_close_stream(r->stream, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||||
|
/*
|
||||||
|
* request has been finalized already
|
||||||
|
* in ngx_http_process_host()
|
||||||
*/
|
*/
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
@@ -3746,6 +3790,7 @@ ngx_http_v2_construct_cookie_header(ngx_http_request_t *r)
|
|||||||
static void
|
static void
|
||||||
ngx_http_v2_run_request(ngx_http_request_t *r)
|
ngx_http_v2_run_request(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
|
ngx_str_t host;
|
||||||
ngx_connection_t *fc;
|
ngx_connection_t *fc;
|
||||||
ngx_http_v2_srv_conf_t *h2scf;
|
ngx_http_v2_srv_conf_t *h2scf;
|
||||||
ngx_http_v2_connection_t *h2c;
|
ngx_http_v2_connection_t *h2c;
|
||||||
@@ -3773,24 +3818,78 @@ ngx_http_v2_run_request(ngx_http_request_t *r)
|
|||||||
|
|
||||||
r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
|
r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
|
||||||
|
|
||||||
if (ngx_http_process_request_header(r) != NGX_OK) {
|
if (r->headers_in.server.len == 0) {
|
||||||
goto failed;
|
ngx_log_error(NGX_LOG_INFO, fc->log, 0,
|
||||||
}
|
"client sent neither \":authority\" nor \"Host\" header");
|
||||||
|
|
||||||
if (r->headers_in.content_length_n > 0 && r->stream->in_closed) {
|
|
||||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
|
||||||
"client prematurely closed stream");
|
|
||||||
|
|
||||||
r->stream->skip_data = 1;
|
|
||||||
|
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->headers_in.content_length_n == -1 && !r->stream->in_closed) {
|
if (r->host_end) {
|
||||||
|
|
||||||
|
host.len = r->host_end - r->host_start;
|
||||||
|
host.data = r->host_start;
|
||||||
|
|
||||||
|
if (r->headers_in.host) {
|
||||||
|
if (r->headers_in.host->value.len != host.len
|
||||||
|
|| ngx_memcmp(r->headers_in.host->value.data, host.data,
|
||||||
|
host.len)
|
||||||
|
!= 0)
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_INFO, fc->log, 0,
|
||||||
|
"client sent \":authority\" and \"Host\" headers "
|
||||||
|
"with different values");
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* compatibility for $http_host */
|
||||||
|
|
||||||
|
if (ngx_http_v2_construct_host_header(r) != NGX_OK) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->headers_in.content_length) {
|
||||||
|
r->headers_in.content_length_n =
|
||||||
|
ngx_atoof(r->headers_in.content_length->value.data,
|
||||||
|
r->headers_in.content_length->value.len);
|
||||||
|
|
||||||
|
if (r->headers_in.content_length_n == NGX_ERROR) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, fc->log, 0,
|
||||||
|
"client sent invalid \"Content-Length\" header");
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->headers_in.content_length_n > 0 && r->stream->in_closed) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, fc->log, 0,
|
||||||
|
"client prematurely closed stream");
|
||||||
|
|
||||||
|
r->stream->skip_data = 1;
|
||||||
|
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (!r->stream->in_closed) {
|
||||||
r->headers_in.chunked = 1;
|
r->headers_in.chunked = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r->method == NGX_HTTP_CONNECT) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client sent CONNECT method");
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->method == NGX_HTTP_TRACE) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client sent TRACE method");
|
||||||
|
ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
h2c = r->stream->connection;
|
h2c = r->stream->connection;
|
||||||
|
|
||||||
h2c->payload_bytes += r->request_length;
|
h2c->payload_bytes += r->request_length;
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ struct ngx_http_v2_stream_s {
|
|||||||
|
|
||||||
ngx_pool_t *pool;
|
ngx_pool_t *pool;
|
||||||
|
|
||||||
|
unsigned initialized:1;
|
||||||
unsigned waiting:1;
|
unsigned waiting:1;
|
||||||
unsigned blocked:1;
|
unsigned blocked:1;
|
||||||
unsigned exhausted:1;
|
unsigned exhausted:1;
|
||||||
|
|||||||
@@ -59,8 +59,13 @@
|
|||||||
#define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1
|
#define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_v2_header_filter(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_v2_early_hints_filter(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_v2_init_stream(ngx_http_request_t *r);
|
||||||
|
|
||||||
static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame(
|
static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame(
|
||||||
ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin);
|
ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin,
|
||||||
|
ngx_uint_t flush);
|
||||||
static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame(
|
static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame(
|
||||||
ngx_http_request_t *r);
|
ngx_http_request_t *r);
|
||||||
|
|
||||||
@@ -127,6 +132,7 @@ ngx_module_t ngx_http_v2_filter_module = {
|
|||||||
|
|
||||||
|
|
||||||
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
|
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
|
||||||
|
static ngx_http_output_header_filter_pt ngx_http_next_early_hints_filter;
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
@@ -139,7 +145,6 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
|
|||||||
ngx_list_part_t *part;
|
ngx_list_part_t *part;
|
||||||
ngx_table_elt_t *header;
|
ngx_table_elt_t *header;
|
||||||
ngx_connection_t *fc;
|
ngx_connection_t *fc;
|
||||||
ngx_http_cleanup_t *cln;
|
|
||||||
ngx_http_v2_stream_t *stream;
|
ngx_http_v2_stream_t *stream;
|
||||||
ngx_http_v2_out_frame_t *frame;
|
ngx_http_v2_out_frame_t *frame;
|
||||||
ngx_http_v2_connection_t *h2c;
|
ngx_http_v2_connection_t *h2c;
|
||||||
@@ -582,14 +587,203 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
|
|||||||
fin = r->header_only
|
fin = r->header_only
|
||||||
|| (r->headers_out.content_length_n == 0 && !r->expect_trailers);
|
|| (r->headers_out.content_length_n == 0 && !r->expect_trailers);
|
||||||
|
|
||||||
frame = ngx_http_v2_create_headers_frame(r, start, pos, fin);
|
frame = ngx_http_v2_create_headers_frame(r, start, pos, fin, 0);
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_http_v2_queue_blocked_frame(h2c, frame);
|
ngx_http_v2_queue_blocked_frame(h2c, frame);
|
||||||
|
|
||||||
stream->queued = 1;
|
stream->queued++;
|
||||||
|
|
||||||
|
if (ngx_http_v2_init_stream(r) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_v2_filter_send(fc, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_v2_early_hints_filter(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
u_char *pos, *start, *tmp;
|
||||||
|
size_t len, tmp_len;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_list_part_t *part;
|
||||||
|
ngx_table_elt_t *header;
|
||||||
|
ngx_connection_t *fc;
|
||||||
|
ngx_http_v2_stream_t *stream;
|
||||||
|
ngx_http_v2_out_frame_t *frame;
|
||||||
|
ngx_http_v2_connection_t *h2c;
|
||||||
|
|
||||||
|
stream = r->stream;
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
return ngx_http_next_early_hints_filter(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != r->main) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
fc = r->connection;
|
||||||
|
|
||||||
|
if (fc->error) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
tmp_len = 0;
|
||||||
|
|
||||||
|
part = &r->headers_out.headers.part;
|
||||||
|
header = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
header = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].hash == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
|
||||||
|
ngx_log_error(NGX_LOG_CRIT, fc->log, 0,
|
||||||
|
"too long response header name: \"%V\"",
|
||||||
|
&header[i].key);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
|
||||||
|
ngx_log_error(NGX_LOG_CRIT, fc->log, 0,
|
||||||
|
"too long response header value: \"%V: %V\"",
|
||||||
|
&header[i].key, &header[i].value);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
|
||||||
|
+ NGX_HTTP_V2_INT_OCTETS + header[i].value.len;
|
||||||
|
|
||||||
|
if (header[i].key.len > tmp_len) {
|
||||||
|
tmp_len = header[i].key.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].value.len > tmp_len) {
|
||||||
|
tmp_len = header[i].value.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2c = stream->connection;
|
||||||
|
|
||||||
|
len += h2c->table_update ? 1 : 0;
|
||||||
|
len += 1 + ngx_http_v2_literal_size("418");
|
||||||
|
|
||||||
|
tmp = ngx_palloc(r->pool, tmp_len);
|
||||||
|
pos = ngx_pnalloc(r->pool, len);
|
||||||
|
|
||||||
|
if (pos == NULL || tmp == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = pos;
|
||||||
|
|
||||||
|
if (h2c->table_update) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||||
|
"http2 table size update: 0");
|
||||||
|
*pos++ = (1 << 5) | 0;
|
||||||
|
h2c->table_update = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||||
|
"http2 output header: \":status: %03ui\"",
|
||||||
|
(ngx_uint_t) NGX_HTTP_EARLY_HINTS);
|
||||||
|
|
||||||
|
*pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_STATUS_INDEX);
|
||||||
|
*pos++ = NGX_HTTP_V2_ENCODE_RAW | 3;
|
||||||
|
pos = ngx_sprintf(pos, "%03ui", (ngx_uint_t) NGX_HTTP_EARLY_HINTS);
|
||||||
|
|
||||||
|
part = &r->headers_out.headers.part;
|
||||||
|
header = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
header = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].hash == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (NGX_DEBUG)
|
||||||
|
if (fc->log->log_level & NGX_LOG_DEBUG_HTTP) {
|
||||||
|
ngx_strlow(tmp, header[i].key.data, header[i].key.len);
|
||||||
|
|
||||||
|
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, fc->log, 0,
|
||||||
|
"http2 output header: \"%*s: %V\"",
|
||||||
|
header[i].key.len, tmp, &header[i].value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*pos++ = 0;
|
||||||
|
|
||||||
|
pos = ngx_http_v2_write_name(pos, header[i].key.data,
|
||||||
|
header[i].key.len, tmp);
|
||||||
|
|
||||||
|
pos = ngx_http_v2_write_value(pos, header[i].value.data,
|
||||||
|
header[i].value.len, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame = ngx_http_v2_create_headers_frame(r, start, pos, 0, 1);
|
||||||
|
if (frame == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_http_v2_queue_blocked_frame(h2c, frame);
|
||||||
|
|
||||||
|
stream->queued++;
|
||||||
|
|
||||||
|
if (ngx_http_v2_init_stream(r) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_v2_filter_send(fc, stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_v2_init_stream(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_connection_t *fc;
|
||||||
|
ngx_http_cleanup_t *cln;
|
||||||
|
ngx_http_v2_stream_t *stream;
|
||||||
|
|
||||||
|
stream = r->stream;
|
||||||
|
fc = r->connection;
|
||||||
|
|
||||||
|
if (stream->initialized) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->initialized = 1;
|
||||||
|
|
||||||
cln = ngx_http_cleanup_add(r, 0);
|
cln = ngx_http_cleanup_add(r, 0);
|
||||||
if (cln == NULL) {
|
if (cln == NULL) {
|
||||||
@@ -603,13 +797,13 @@ ngx_http_v2_header_filter(ngx_http_request_t *r)
|
|||||||
fc->need_last_buf = 1;
|
fc->need_last_buf = 1;
|
||||||
fc->need_flush_buf = 1;
|
fc->need_flush_buf = 1;
|
||||||
|
|
||||||
return ngx_http_v2_filter_send(fc, stream);
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_http_v2_out_frame_t *
|
static ngx_http_v2_out_frame_t *
|
||||||
ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos,
|
ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos,
|
||||||
u_char *end, ngx_uint_t fin)
|
u_char *end, ngx_uint_t fin, ngx_uint_t flush)
|
||||||
{
|
{
|
||||||
u_char type, flags;
|
u_char type, flags;
|
||||||
size_t rest, frame_size;
|
size_t rest, frame_size;
|
||||||
@@ -700,6 +894,7 @@ ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
b->last_buf = fin;
|
b->last_buf = fin;
|
||||||
|
b->flush = flush;
|
||||||
cl->next = NULL;
|
cl->next = NULL;
|
||||||
frame->last = cl;
|
frame->last = cl;
|
||||||
|
|
||||||
@@ -822,7 +1017,7 @@ ngx_http_v2_create_trailers_frame(ngx_http_request_t *r)
|
|||||||
header[i].value.len, tmp);
|
header[i].value.len, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ngx_http_v2_create_headers_frame(r, start, pos, 1);
|
return ngx_http_v2_create_headers_frame(r, start, pos, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1544,5 +1739,8 @@ ngx_http_v2_filter_init(ngx_conf_t *cf)
|
|||||||
ngx_http_next_header_filter = ngx_http_top_header_filter;
|
ngx_http_next_header_filter = ngx_http_top_header_filter;
|
||||||
ngx_http_top_header_filter = ngx_http_v2_header_filter;
|
ngx_http_top_header_filter = ngx_http_v2_header_filter;
|
||||||
|
|
||||||
|
ngx_http_next_early_hints_filter = ngx_http_top_early_hints_filter;
|
||||||
|
ngx_http_top_early_hints_filter = ngx_http_v2_early_hints_filter;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#define NGX_HTTP_V3_HEADER_METHOD_GET 17
|
#define NGX_HTTP_V3_HEADER_METHOD_GET 17
|
||||||
#define NGX_HTTP_V3_HEADER_SCHEME_HTTP 22
|
#define NGX_HTTP_V3_HEADER_SCHEME_HTTP 22
|
||||||
#define NGX_HTTP_V3_HEADER_SCHEME_HTTPS 23
|
#define NGX_HTTP_V3_HEADER_SCHEME_HTTPS 23
|
||||||
|
#define NGX_HTTP_V3_HEADER_STATUS_103 24
|
||||||
#define NGX_HTTP_V3_HEADER_STATUS_200 25
|
#define NGX_HTTP_V3_HEADER_STATUS_200 25
|
||||||
#define NGX_HTTP_V3_HEADER_ACCEPT_ENCODING 31
|
#define NGX_HTTP_V3_HEADER_ACCEPT_ENCODING 31
|
||||||
#define NGX_HTTP_V3_HEADER_CONTENT_TYPE_TEXT_PLAIN 53
|
#define NGX_HTTP_V3_HEADER_CONTENT_TYPE_TEXT_PLAIN 53
|
||||||
@@ -36,6 +37,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t ngx_http_v3_header_filter(ngx_http_request_t *r);
|
static ngx_int_t ngx_http_v3_header_filter(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_v3_early_hints_filter(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_v3_body_filter(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_v3_body_filter(ngx_http_request_t *r,
|
||||||
ngx_chain_t *in);
|
ngx_chain_t *in);
|
||||||
static ngx_chain_t *ngx_http_v3_create_trailers(ngx_http_request_t *r,
|
static ngx_chain_t *ngx_http_v3_create_trailers(ngx_http_request_t *r,
|
||||||
@@ -75,6 +77,7 @@ ngx_module_t ngx_http_v3_filter_module = {
|
|||||||
|
|
||||||
|
|
||||||
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
|
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
|
||||||
|
static ngx_http_output_header_filter_pt ngx_http_next_early_hints_filter;
|
||||||
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
|
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
|
||||||
|
|
||||||
|
|
||||||
@@ -588,6 +591,150 @@ ngx_http_v3_header_filter(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_v3_early_hints_filter(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
size_t len, n;
|
||||||
|
ngx_buf_t *b;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_chain_t *out, *hl, *cl;
|
||||||
|
ngx_list_part_t *part;
|
||||||
|
ngx_table_elt_t *header;
|
||||||
|
ngx_http_v3_session_t *h3c;
|
||||||
|
|
||||||
|
if (r->http_version != NGX_HTTP_VERSION_30) {
|
||||||
|
return ngx_http_next_early_hints_filter(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != r->main) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
part = &r->headers_out.headers.part;
|
||||||
|
header = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
header = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].hash == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += ngx_http_v3_encode_field_l(NULL, &header[i].key,
|
||||||
|
&header[i].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += ngx_http_v3_encode_field_section_prefix(NULL, 0, 0, 0);
|
||||||
|
|
||||||
|
len += ngx_http_v3_encode_field_ri(NULL, 0, NGX_HTTP_V3_HEADER_STATUS_103);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http3 header len:%uz", len);
|
||||||
|
|
||||||
|
b = ngx_create_temp_buf(r->pool, len);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->last = (u_char *) ngx_http_v3_encode_field_section_prefix(b->last,
|
||||||
|
0, 0, 0);
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http3 output header: \":status: %03ui\"",
|
||||||
|
(ngx_uint_t) NGX_HTTP_EARLY_HINTS);
|
||||||
|
|
||||||
|
b->last = (u_char *) ngx_http_v3_encode_field_ri(b->last, 0,
|
||||||
|
NGX_HTTP_V3_HEADER_STATUS_103);
|
||||||
|
|
||||||
|
part = &r->headers_out.headers.part;
|
||||||
|
header = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
header = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header[i].hash == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"http3 output header: \"%V: %V\"",
|
||||||
|
&header[i].key, &header[i].value);
|
||||||
|
|
||||||
|
b->last = (u_char *) ngx_http_v3_encode_field_l(b->last,
|
||||||
|
&header[i].key,
|
||||||
|
&header[i].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
b->flush = 1;
|
||||||
|
|
||||||
|
cl = ngx_alloc_chain_link(r->pool);
|
||||||
|
if (cl == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl->buf = b;
|
||||||
|
cl->next = NULL;
|
||||||
|
|
||||||
|
n = b->last - b->pos;
|
||||||
|
|
||||||
|
h3c = ngx_http_v3_get_session(r->connection);
|
||||||
|
h3c->payload_bytes += n;
|
||||||
|
|
||||||
|
len = ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_FRAME_HEADERS)
|
||||||
|
+ ngx_http_v3_encode_varlen_int(NULL, n);
|
||||||
|
|
||||||
|
b = ngx_create_temp_buf(r->pool, len);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last,
|
||||||
|
NGX_HTTP_V3_FRAME_HEADERS);
|
||||||
|
b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, n);
|
||||||
|
|
||||||
|
hl = ngx_alloc_chain_link(r->pool);
|
||||||
|
if (hl == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
hl->buf = b;
|
||||||
|
hl->next = cl;
|
||||||
|
|
||||||
|
out = hl;
|
||||||
|
|
||||||
|
for (cl = out; cl; cl = cl->next) {
|
||||||
|
h3c->total_bytes += cl->buf->last - cl->buf->pos;
|
||||||
|
r->header_size += cl->buf->last - cl->buf->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_write_filter(r, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_v3_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
ngx_http_v3_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||||
{
|
{
|
||||||
@@ -845,6 +992,9 @@ ngx_http_v3_filter_init(ngx_conf_t *cf)
|
|||||||
ngx_http_next_header_filter = ngx_http_top_header_filter;
|
ngx_http_next_header_filter = ngx_http_top_header_filter;
|
||||||
ngx_http_top_header_filter = ngx_http_v3_header_filter;
|
ngx_http_top_header_filter = ngx_http_v3_header_filter;
|
||||||
|
|
||||||
|
ngx_http_next_early_hints_filter = ngx_http_top_early_hints_filter;
|
||||||
|
ngx_http_top_early_hints_filter = ngx_http_v3_early_hints_filter;
|
||||||
|
|
||||||
ngx_http_next_body_filter = ngx_http_top_body_filter;
|
ngx_http_next_body_filter = ngx_http_top_body_filter;
|
||||||
ngx_http_top_body_filter = ngx_http_v3_body_filter;
|
ngx_http_top_body_filter = ngx_http_v3_body_filter;
|
||||||
|
|
||||||
|
|||||||
@@ -623,6 +623,12 @@ ngx_http_v3_parse_literal(ngx_connection_t *c, ngx_http_v3_parse_literal_t *st,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (st->huffman) {
|
if (st->huffman) {
|
||||||
|
if (n > NGX_MAX_INT_T_VALUE / 8) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
|
"client sent too large field line");
|
||||||
|
return NGX_HTTP_V3_ERR_EXCESSIVE_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
n = n * 8 / 5;
|
n = n * 8 / 5;
|
||||||
st->huffstate = 0;
|
st->huffstate = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -965,7 +965,7 @@ ngx_http_v3_init_pseudo_headers(ngx_http_request_t *r)
|
|||||||
|
|
||||||
if (rc == NGX_DECLINED) {
|
if (rc == NGX_DECLINED) {
|
||||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
"client sent invalid host in request line");
|
"client sent invalid \":authority\" header");
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1003,6 +1003,7 @@ ngx_http_v3_process_request_header(ngx_http_request_t *r)
|
|||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
|
ngx_str_t host;
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
ngx_http_v3_session_t *h3c;
|
ngx_http_v3_session_t *h3c;
|
||||||
ngx_http_v3_srv_conf_t *h3scf;
|
ngx_http_v3_srv_conf_t *h3scf;
|
||||||
@@ -1034,11 +1035,13 @@ ngx_http_v3_process_request_header(ngx_http_request_t *r)
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->headers_in.host) {
|
if (r->headers_in.host && r->host_end) {
|
||||||
if (r->headers_in.host->value.len != r->headers_in.server.len
|
|
||||||
|| ngx_memcmp(r->headers_in.host->value.data,
|
host.len = r->host_end - r->host_start;
|
||||||
r->headers_in.server.data,
|
host.data = r->host_start;
|
||||||
r->headers_in.server.len)
|
|
||||||
|
if (r->headers_in.host->value.len != host.len
|
||||||
|
|| ngx_memcmp(r->headers_in.host->value.data, host.data, host.len)
|
||||||
!= 0)
|
!= 0)
|
||||||
{
|
{
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
@@ -1213,7 +1216,7 @@ ngx_http_v3_construct_cookie_header(ngx_http_request_t *r)
|
|||||||
if (hh->handler(r, h, hh->offset) != NGX_OK) {
|
if (hh->handler(r, h, hh->offset) != NGX_OK) {
|
||||||
/*
|
/*
|
||||||
* request has been finalized already
|
* request has been finalized already
|
||||||
* in ngx_http_process_multi_header_lines()
|
* in ngx_http_process_header_line()
|
||||||
*/
|
*/
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1321,7 +1321,10 @@ ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool,
|
|||||||
b->last = ngx_copy(b->last, passwd.data, passwd.len);
|
b->last = ngx_copy(b->last, passwd.data, passwd.len);
|
||||||
*b->last++ = CR; *b->last++ = LF;
|
*b->last++ = CR; *b->last++ = LF;
|
||||||
|
|
||||||
if (s->auth_method != NGX_MAIL_AUTH_PLAIN && s->salt.len) {
|
if ((s->auth_method == NGX_MAIL_AUTH_APOP
|
||||||
|
|| s->auth_method == NGX_MAIL_AUTH_CRAM_MD5)
|
||||||
|
&& s->salt.len)
|
||||||
|
{
|
||||||
b->last = ngx_cpymem(b->last, "Auth-Salt: ", sizeof("Auth-Salt: ") - 1);
|
b->last = ngx_cpymem(b->last, "Auth-Salt: ", sizeof("Auth-Salt: ") - 1);
|
||||||
b->last = ngx_copy(b->last, s->salt.data, s->salt.len);
|
b->last = ngx_copy(b->last, s->salt.data, s->salt.len);
|
||||||
|
|
||||||
|
|||||||
+26
-22
@@ -523,7 +523,7 @@ ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n)
|
ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n)
|
||||||
{
|
{
|
||||||
u_char *p, *last;
|
u_char *p, *pos, *last;
|
||||||
ngx_str_t *arg, plain;
|
ngx_str_t *arg, plain;
|
||||||
|
|
||||||
arg = s->args.elts;
|
arg = s->args.elts;
|
||||||
@@ -555,7 +555,7 @@ ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n)
|
|||||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->login.data = p;
|
pos = p;
|
||||||
|
|
||||||
while (p < last && *p) { p++; }
|
while (p < last && *p) { p++; }
|
||||||
|
|
||||||
@@ -565,7 +565,8 @@ ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n)
|
|||||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->login.len = p++ - s->login.data;
|
s->login.len = p++ - pos;
|
||||||
|
s->login.data = pos;
|
||||||
|
|
||||||
s->passwd.len = last - p;
|
s->passwd.len = last - p;
|
||||||
s->passwd.data = p;
|
s->passwd.data = p;
|
||||||
@@ -583,24 +584,26 @@ ngx_int_t
|
|||||||
ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c,
|
ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c,
|
||||||
ngx_uint_t n)
|
ngx_uint_t n)
|
||||||
{
|
{
|
||||||
ngx_str_t *arg;
|
ngx_str_t *arg, login;
|
||||||
|
|
||||||
arg = s->args.elts;
|
arg = s->args.elts;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||||
"mail auth login username: \"%V\"", &arg[n]);
|
"mail auth login username: \"%V\"", &arg[n]);
|
||||||
|
|
||||||
s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len));
|
login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len));
|
||||||
if (s->login.data == NULL) {
|
if (login.data == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_decode_base64(&s->login, &arg[n]) != NGX_OK) {
|
if (ngx_decode_base64(&login, &arg[n]) != NGX_OK) {
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
"client sent invalid base64 encoding in AUTH LOGIN command");
|
"client sent invalid base64 encoding in AUTH LOGIN command");
|
||||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->login = login;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||||
"mail auth login username: \"%V\"", &s->login);
|
"mail auth login username: \"%V\"", &s->login);
|
||||||
|
|
||||||
@@ -611,7 +614,7 @@ ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c,
|
|||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c)
|
ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
ngx_str_t *arg;
|
ngx_str_t *arg, passwd;
|
||||||
|
|
||||||
arg = s->args.elts;
|
arg = s->args.elts;
|
||||||
|
|
||||||
@@ -620,18 +623,19 @@ ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||||||
"mail auth login password: \"%V\"", &arg[0]);
|
"mail auth login password: \"%V\"", &arg[0]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s->passwd.data = ngx_pnalloc(c->pool,
|
passwd.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[0].len));
|
||||||
ngx_base64_decoded_length(arg[0].len));
|
if (passwd.data == NULL) {
|
||||||
if (s->passwd.data == NULL) {
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) {
|
if (ngx_decode_base64(&passwd, &arg[0]) != NGX_OK) {
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
"client sent invalid base64 encoding in AUTH LOGIN command");
|
"client sent invalid base64 encoding in AUTH LOGIN command");
|
||||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->passwd = passwd;
|
||||||
|
|
||||||
#if (NGX_DEBUG_MAIL_PASSWD)
|
#if (NGX_DEBUG_MAIL_PASSWD)
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||||
"mail auth login password: \"%V\"", &s->passwd);
|
"mail auth login password: \"%V\"", &s->passwd);
|
||||||
@@ -674,24 +678,26 @@ ngx_int_t
|
|||||||
ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c)
|
ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c)
|
||||||
{
|
{
|
||||||
u_char *p, *last;
|
u_char *p, *last;
|
||||||
ngx_str_t *arg;
|
ngx_str_t *arg, login;
|
||||||
|
|
||||||
arg = s->args.elts;
|
arg = s->args.elts;
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
|
||||||
"mail auth cram-md5: \"%V\"", &arg[0]);
|
"mail auth cram-md5: \"%V\"", &arg[0]);
|
||||||
|
|
||||||
s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[0].len));
|
login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[0].len));
|
||||||
if (s->login.data == NULL) {
|
if (login.data == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) {
|
if (ngx_decode_base64(&login, &arg[0]) != NGX_OK) {
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
"client sent invalid base64 encoding in AUTH CRAM-MD5 command");
|
"client sent invalid base64 encoding in AUTH CRAM-MD5 command");
|
||||||
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
return NGX_MAIL_PARSE_INVALID_COMMAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->login = login;
|
||||||
|
|
||||||
p = s->login.data;
|
p = s->login.data;
|
||||||
last = p + s->login.len;
|
last = p + s->login.len;
|
||||||
|
|
||||||
@@ -1000,14 +1006,12 @@ ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len)
|
|||||||
len -= p - buf;
|
len -= p - buf;
|
||||||
buf = p;
|
buf = p;
|
||||||
|
|
||||||
if (s->login.len == 0) {
|
if (s->login.len) {
|
||||||
return p;
|
p = ngx_snprintf(buf, len, ", login: \"%V\"", &s->login);
|
||||||
|
len -= p - buf;
|
||||||
|
buf = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = ngx_snprintf(buf, len, ", login: \"%V\"", &s->login);
|
|
||||||
len -= p - buf;
|
|
||||||
buf = p;
|
|
||||||
|
|
||||||
if (s->proxy == NULL) {
|
if (s->proxy == NULL) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -782,6 +782,9 @@ ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
|
|||||||
|
|
||||||
ngx_str_set(&s->out, smtp_ok);
|
ngx_str_set(&s->out, smtp_ok);
|
||||||
|
|
||||||
|
ngx_str_null(&s->login);
|
||||||
|
ngx_str_null(&s->passwd);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,13 @@ static ngx_command_t ngx_mail_ssl_commands[] = {
|
|||||||
0,
|
0,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_certificate_compression"),
|
||||||
|
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
|
||||||
|
ngx_conf_set_flag_slot,
|
||||||
|
NGX_MAIL_SRV_CONF_OFFSET,
|
||||||
|
offsetof(ngx_mail_ssl_conf_t, certificate_compression),
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_dhparam"),
|
{ ngx_string("ssl_dhparam"),
|
||||||
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
@@ -315,6 +322,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)
|
|||||||
scf->passwords = NGX_CONF_UNSET_PTR;
|
scf->passwords = NGX_CONF_UNSET_PTR;
|
||||||
scf->conf_commands = NGX_CONF_UNSET_PTR;
|
scf->conf_commands = NGX_CONF_UNSET_PTR;
|
||||||
scf->prefer_server_ciphers = NGX_CONF_UNSET;
|
scf->prefer_server_ciphers = NGX_CONF_UNSET;
|
||||||
|
scf->certificate_compression = NGX_CONF_UNSET;
|
||||||
scf->verify = NGX_CONF_UNSET_UINT;
|
scf->verify = NGX_CONF_UNSET_UINT;
|
||||||
scf->verify_depth = NGX_CONF_UNSET_UINT;
|
scf->verify_depth = NGX_CONF_UNSET_UINT;
|
||||||
scf->builtin_session_cache = NGX_CONF_UNSET;
|
scf->builtin_session_cache = NGX_CONF_UNSET;
|
||||||
@@ -344,6 +352,9 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
||||||
prev->prefer_server_ciphers, 1);
|
prev->prefer_server_ciphers, 1);
|
||||||
|
|
||||||
|
ngx_conf_merge_value(conf->certificate_compression,
|
||||||
|
prev->certificate_compression, 0);
|
||||||
|
|
||||||
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
||||||
(NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));
|
(NGX_CONF_BITMASK_SET|NGX_SSL_DEFAULT_PROTOCOLS));
|
||||||
|
|
||||||
@@ -447,6 +458,13 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_ssl_certificate_compression(cf, &conf->ssl,
|
||||||
|
conf->certificate_compression)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (conf->verify) {
|
if (conf->verify) {
|
||||||
|
|
||||||
if (conf->client_certificate.len == 0 && conf->verify != 3) {
|
if (conf->client_certificate.len == 0 && conf->verify != 3) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_flag_t prefer_server_ciphers;
|
ngx_flag_t prefer_server_ciphers;
|
||||||
|
ngx_flag_t certificate_compression;
|
||||||
|
|
||||||
ngx_ssl_t ssl;
|
ngx_ssl_t ssl;
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ ngx_timezone_update(void)
|
|||||||
struct tm *t;
|
struct tm *t;
|
||||||
char buf[4];
|
char buf[4];
|
||||||
|
|
||||||
s = time(0);
|
s = time(NULL);
|
||||||
|
|
||||||
t = localtime(&s);
|
t = localtime(&s);
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
|
|||||||
0,
|
0,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_certificate_compression"),
|
||||||
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
||||||
|
ngx_conf_set_flag_slot,
|
||||||
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
|
offsetof(ngx_stream_ssl_srv_conf_t, certificate_compression),
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_dhparam"),
|
{ ngx_string("ssl_dhparam"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
@@ -881,6 +888,7 @@ ngx_stream_ssl_create_srv_conf(ngx_conf_t *cf)
|
|||||||
sscf->passwords = NGX_CONF_UNSET_PTR;
|
sscf->passwords = NGX_CONF_UNSET_PTR;
|
||||||
sscf->conf_commands = NGX_CONF_UNSET_PTR;
|
sscf->conf_commands = NGX_CONF_UNSET_PTR;
|
||||||
sscf->prefer_server_ciphers = NGX_CONF_UNSET;
|
sscf->prefer_server_ciphers = NGX_CONF_UNSET;
|
||||||
|
sscf->certificate_compression = NGX_CONF_UNSET;
|
||||||
sscf->reject_handshake = NGX_CONF_UNSET;
|
sscf->reject_handshake = NGX_CONF_UNSET;
|
||||||
sscf->verify = NGX_CONF_UNSET_UINT;
|
sscf->verify = NGX_CONF_UNSET_UINT;
|
||||||
sscf->verify_depth = NGX_CONF_UNSET_UINT;
|
sscf->verify_depth = NGX_CONF_UNSET_UINT;
|
||||||
@@ -914,6 +922,9 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
||||||
prev->prefer_server_ciphers, 1);
|
prev->prefer_server_ciphers, 1);
|
||||||
|
|
||||||
|
ngx_conf_merge_value(conf->certificate_compression,
|
||||||
|
prev->certificate_compression, 0);
|
||||||
|
|
||||||
ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
|
ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
|
||||||
|
|
||||||
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
||||||
@@ -1039,6 +1050,13 @@ ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_ssl_certificate_compression(cf, &conf->ssl,
|
||||||
|
conf->certificate_compression)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->verify) {
|
if (conf->verify) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ typedef struct {
|
|||||||
ngx_msec_t handshake_timeout;
|
ngx_msec_t handshake_timeout;
|
||||||
|
|
||||||
ngx_flag_t prefer_server_ciphers;
|
ngx_flag_t prefer_server_ciphers;
|
||||||
|
ngx_flag_t certificate_compression;
|
||||||
ngx_flag_t reject_handshake;
|
ngx_flag_t reject_handshake;
|
||||||
|
|
||||||
ngx_ssl_t ssl;
|
ngx_ssl_t ssl;
|
||||||
|
|||||||
Reference in New Issue
Block a user