...
 
Commits (16)
......@@ -50,6 +50,7 @@ Jan Kundrát
Jan-E
Janusz Dziemidowicz
Jay Satiro
Jeff 'Raid' Baitis
Jianqing Wang
Jim Morrison
Josh Braegger
......
......@@ -24,12 +24,12 @@
cmake_minimum_required(VERSION 3.0)
# XXX using 1.8.90 instead of 1.9.0-DEV
project(nghttp2 VERSION 1.37.0)
project(nghttp2 VERSION 1.38.0)
# See versioning rule:
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
set(LT_CURRENT 31)
set(LT_REVISION 2)
set(LT_REVISION 3)
set(LT_AGE 17)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
......
commit cfb47d30a5bb5dfcc6b0dc30698957d8605348c5 (HEAD, tag: v1.37.0, origin/master, origin/HEAD, master)
commit 4a9d2005547dc02661ee74fc839df73052443242 (HEAD, tag: v1.38.0, origin/master, origin/HEAD, master)
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-08
AuthorDate: 2019-04-18
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-08
CommitDate: 2019-04-18
Take into account larger frame size for prioritization
Larger frame size just destroys multiplexing and prioritization does
not work.
Update manual pages
commit dbbe4e017a353ced5264baa33db95f336a76c54f
commit acf6a9229d80cc1442c16e7982d2b07d03e4aba8
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-08
AuthorDate: 2019-04-18
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-08
CommitDate: 2019-04-18
Remove unused field
Bump up version number to 1.38.0, LT revision to 31:3:17
commit 371bc3a8f74a4148c9ee5133db644177182f46fe
commit 4ff4582132dbe1ce6f04db275c1828e63da29e73
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-08
AuthorDate: 2019-04-18
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-08
CommitDate: 2019-04-18
clang-format
Update AUTHORS
commit 5e7889c5ef28ef5ba57ac29626e4d8ae770bf2b9
commit 42dce01ec10847a98f49c0e25f39b54bbe56f43b
Merge: 5a30fafd a35059e3
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-07
AuthorDate: 2019-04-16
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-07
CommitDate: 2019-04-16
Update manual pages
Merge branch 'nghttpx-fix-backend-selection-on-retry'
commit b1b2ad5017f3923a84248058853d788336c30445
commit a35059e3f128ed7e0de9c7c808d816693f3455f8
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-07
AuthorDate: 2019-04-16
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-07
CommitDate: 2019-04-16
Bump up version number to 1.37.0, LT revision to 31:2:17
nghttpx: Fix bug that altered authority and path affect backend selection
Fix bug that altered authority and path by per-pattern mruby script
affect backend selection on retry.
commit e043ca83c5d9381febd0ab2041b617d3f90ad781
commit 5a30fafddac5970eacf300f4cbc77ecb4fc86f6f
Merge: dce91ad3 2cff8b43
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-07
AuthorDate: 2019-04-16
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-07
CommitDate: 2019-04-16
Update AUTHORS
Merge branch 'nghttpx-fix-chunked-request-stall'
commit c2434dfbbc65b543eb2c27f7924242e90e7ae5f7
commit dce91ad37c59c56634db57e3aa484ab606622634
Merge: ce962c3f be96654d
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-04
AuthorDate: 2019-04-16
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-04
CommitDate: 2019-04-16
Simplify stream_less
Merge branch 'nghttpx-dont-log-authorization'
commit 816ad2102fe1e0c4e47a2160e1958dfdc2cbabc9
commit 2cff8b43cff24ffaa79e92f2b6fdc55715155ee7
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-03-04
AuthorDate: 2019-04-15
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-03-04
Reuse name when indexing header by referencing dynamic table
CommitDate: 2019-04-15
commit f5feb16ef400fa72319eda0d34d863c6ff58fabc
Merge: adf09f21 34482ed4
Author: Tatsuhiro Tsujikawa <404610+tatsuhiro-t@users.noreply.github.com>
AuthorDate: 2019-02-20
Commit: GitHub <noreply@github.com>
CommitDate: 2019-02-20
nghttpx: Fix bug that chunked request stalls
Merge pull request #1295 from bratkartoffel/fix-compile-boringssl
Fix compilation with boringssl
commit adf09f2124d16765f40fde3806ba9ee2aaf5b42e
Merge: d93842db 2591960e
Author: Tatsuhiro Tsujikawa <404610+tatsuhiro-t@users.noreply.github.com>
AuthorDate: 2019-02-20
Commit: GitHub <noreply@github.com>
CommitDate: 2019-02-20
Merge pull request #1303 from donny-dont/fix-shared-install
Explicitly set install location when building shared libs
commit 2591960e2fc9aef919b010224a221f92a20da3d1
Author: Don <don.j.olmstead@gmail.com>
AuthorDate: 2019-02-06
Commit: Don <don.j.olmstead@gmail.com>
CommitDate: 2019-02-06
Explicitly set install location when building shared libs
commit d93842db3eb481fc6953ec70a81ed2f7863ffb45
commit be96654d569d6e8e88c1b4c38830c2b6dec9d32f
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-01-23
AuthorDate: 2019-04-15
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-01-23
CommitDate: 2019-04-15
nghttpx: Fix backend stall if header and request body are sent in 2 packets
nghttpx: Don't log authorization request header field value with -LINFO
commit 8dc2b263ba62c4b8c3e682757baa59a9708b3b7d
commit ce962c3fdf29206e35f71a217ae2c31814903a53
Merge: d978f351 f931504e
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-01-22
AuthorDate: 2019-04-15
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-01-22
CommitDate: 2019-04-15
nghttpx: Use std::priority_queue
Merge branch 'update-http-parser'
commit 8d842701b512791b3f7613703070fb3079de33de
commit f931504e1cdff30d54a62b6a718d9fdc0ccd4447
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-01-21
AuthorDate: 2019-04-15
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-01-21
CommitDate: 2019-04-15
Update manual pages
Update http-parser to v2.9.1
http-parser c5c45636b85e7598223adede6ba2d8cb8fe03ebe
commit de85b0fda592934a64886ba6a584424b777e97ac
commit d978f351dad7c930e2c601f902b8430ea9a7b584
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-01-21
AuthorDate: 2019-04-11
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-01-21
CommitDate: 2019-04-11
Update README
Fix bug that on_header callback is still called after stream is closed
commit 5d6beed59099487cf77fb0641aae575f3ce6d967
Merge: 9b6ced66 1ff9de4c
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-01-21
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-01-21
commit ec519f22dcad42a06b968e24a8ee8f651464016a
Merge: e8b213e3 2c157059
Author: Tatsuhiro Tsujikawa <404610+tatsuhiro-t@users.noreply.github.com>
AuthorDate: 2019-03-13
Commit: GitHub <noreply@github.com>
CommitDate: 2019-03-13
Merge branch 'nghttpx-backend-weight'
Merge pull request #1270 from baitisj/master
Fix for compilation against modern LibreSSL
commit 1ff9de4c873908ca0612df10daef9ecd7b580051
commit e8b213e3672c4119705f664bb0ecf0b0b9ed873c
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-01-19
AuthorDate: 2019-03-08
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-01-21
nghttpx: Backend address selection with weight
commit 34482ed4df79c7c143226f759af0a8834298acd1
Author: Simon Frankenberger <simon@fraho.eu>
AuthorDate: 2019-01-18
Commit: Simon Frankenberger <simon@fraho.eu>
CommitDate: 2019-01-18
CommitDate: 2019-03-08
Fix compilation with boringssl
Bump up version number to 1.38.0-DEV
commit 9b6ced66f3b89a3a005002ff2df68dae9d7295cd
Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
AuthorDate: 2019-01-18
Commit: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
CommitDate: 2019-01-18
commit 2c1570595e365a18c85fd1b12c8f56516742b664
Author: Jeff 'Raid' Baitis <jeff@baitis.net>
AuthorDate: 2018-12-02
Commit: Jeff 'Raid' Baitis <jeff@baitis.net>
CommitDate: 2018-12-02
Bump up version number to 1.37.0-DEV
Fix for compilation against modern LibreSSL
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for nghttp2 1.37.0.
# Generated by GNU Autoconf 2.69 for nghttp2 1.38.0.
#
# Report bugs to <t-tujikawa@users.sourceforge.net>.
#
......@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='nghttp2'
PACKAGE_TARNAME='nghttp2'
PACKAGE_VERSION='1.37.0'
PACKAGE_STRING='nghttp2 1.37.0'
PACKAGE_VERSION='1.38.0'
PACKAGE_STRING='nghttp2 1.38.0'
PACKAGE_BUGREPORT='t-tujikawa@users.sourceforge.net'
PACKAGE_URL=''
......@@ -1464,7 +1464,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures nghttp2 1.37.0 to adapt to many kinds of systems.
\`configure' configures nghttp2 1.38.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
......@@ -1536,7 +1536,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of nghttp2 1.37.0:";;
short | recursive ) echo "Configuration of nghttp2 1.38.0:";;
esac
cat <<\_ACEOF
......@@ -1732,7 +1732,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
nghttp2 configure 1.37.0
nghttp2 configure 1.38.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
......@@ -2692,7 +2692,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by nghttp2 $as_me 1.37.0, which was
It was created by nghttp2 $as_me 1.38.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
......@@ -12657,7 +12657,7 @@ fi
# Define the identity of the package.
PACKAGE='nghttp2'
VERSION='1.37.0'
VERSION='1.38.0'
cat >>confdefs.h <<_ACEOF
......@@ -12921,7 +12921,7 @@ AM_BACKSLASH='\'
LT_CURRENT=31
LT_REVISION=2
LT_REVISION=3
LT_AGE=17
......@@ -24916,7 +24916,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by nghttp2 $as_me 1.37.0, which was
This file was extended by nghttp2 $as_me 1.38.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
......@@ -24982,7 +24982,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
nghttp2 config.status 1.37.0
nghttp2 config.status 1.38.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
......
......@@ -25,7 +25,7 @@ dnl Do not change user variables!
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61)
AC_INIT([nghttp2], [1.37.0], [t-tujikawa@users.sourceforge.net])
AC_INIT([nghttp2], [1.38.0], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
......@@ -45,7 +45,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 31)
AC_SUBST(LT_REVISION, 2)
AC_SUBST(LT_REVISION, 3)
AC_SUBST(LT_AGE, 17)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
......
.\" Man page generated from reStructuredText.
.
.TH "H2LOAD" "1" "Mar 07, 2019" "1.37.0" "nghttp2"
.TH "H2LOAD" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
.SH NAME
h2load \- HTTP/2 benchmarking tool
.
......
.\" Man page generated from reStructuredText.
.
.TH "NGHTTP" "1" "Mar 07, 2019" "1.37.0" "nghttp2"
.TH "NGHTTP" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
.SH NAME
nghttp \- HTTP/2 client
.
......
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPD" "1" "Mar 07, 2019" "1.37.0" "nghttp2"
.TH "NGHTTPD" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
.SH NAME
nghttpd \- HTTP/2 server
.
......
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPX" "1" "Mar 07, 2019" "1.37.0" "nghttp2"
.TH "NGHTTPX" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
.SH NAME
nghttpx \- HTTP/2 proxy
.
......
......@@ -29,7 +29,7 @@
* @macro
* Version number of the nghttp2 library release
*/
#define NGHTTP2_VERSION "1.37.0"
#define NGHTTP2_VERSION "1.38.0"
/**
* @macro
......@@ -37,6 +37,6 @@
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
#define NGHTTP2_VERSION_NUM 0x012500
#define NGHTTP2_VERSION_NUM 0x012600
#endif /* NGHTTP2VER_H */
......@@ -3619,71 +3619,73 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
rv = 0;
if (subject_stream && session_enforce_http_messaging(session)) {
rv = nghttp2_http_on_header(session, subject_stream, frame, &nv,
trailer);
if (subject_stream) {
if (session_enforce_http_messaging(session)) {
rv = nghttp2_http_on_header(session, subject_stream, frame, &nv,
trailer);
if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
/* Don't overwrite rv here */
int rv2;
if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
/* Don't overwrite rv here */
int rv2;
rv2 = session_call_on_invalid_header(session, frame, &nv);
if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
rv = NGHTTP2_ERR_HTTP_HEADER;
} else {
if (rv2 != 0) {
return rv2;
rv2 = session_call_on_invalid_header(session, frame, &nv);
if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
rv = NGHTTP2_ERR_HTTP_HEADER;
} else {
if (rv2 != 0) {
return rv2;
}
/* header is ignored */
DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
rv2 = session_call_error_callback(
session, NGHTTP2_ERR_HTTP_HEADER,
"Ignoring received invalid HTTP header field: frame type: "
"%u, stream: %d, name: [%.*s], value: [%.*s]",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
if (nghttp2_is_fatal(rv2)) {
return rv2;
}
}
}
/* header is ignored */
DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
if (rv == NGHTTP2_ERR_HTTP_HEADER) {
DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
rv2 = session_call_error_callback(
rv = session_call_error_callback(
session, NGHTTP2_ERR_HTTP_HEADER,
"Ignoring received invalid HTTP header field: frame type: "
"Invalid HTTP header field was received: frame type: "
"%u, stream: %d, name: [%.*s], value: [%.*s]",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
if (nghttp2_is_fatal(rv2)) {
return rv2;
if (nghttp2_is_fatal(rv)) {
return rv;
}
}
}
if (rv == NGHTTP2_ERR_HTTP_HEADER) {
DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
rv = session_call_error_callback(
session, NGHTTP2_ERR_HTTP_HEADER,
"Invalid HTTP header field was received: frame type: "
"%u, stream: %d, name: [%.*s], value: [%.*s]",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
if (nghttp2_is_fatal(rv)) {
return rv;
rv = session_handle_invalid_stream2(session,
subject_stream->stream_id,
frame, NGHTTP2_ERR_HTTP_HEADER);
if (nghttp2_is_fatal(rv)) {
return rv;
}
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
rv =
session_handle_invalid_stream2(session, subject_stream->stream_id,
frame, NGHTTP2_ERR_HTTP_HEADER);
if (nghttp2_is_fatal(rv)) {
}
if (rv == 0) {
rv = session_call_on_header(session, frame, &nv);
/* This handles NGHTTP2_ERR_PAUSE and
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
if (rv != 0) {
return rv;
}
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
}
if (rv == 0) {
rv = session_call_on_header(session, frame, &nv);
/* This handles NGHTTP2_ERR_PAUSE and
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
if (rv != 0) {
return rv;
}
}
}
......
......@@ -893,7 +893,7 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
auto catch_all = downstreamconf.addr_group_catch_all;
auto &groups = worker_->get_downstream_addr_groups();
const auto &req = downstream->request();
auto &req = downstream->request();
err = 0;
......@@ -908,11 +908,14 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
auto &balloc = downstream->get_block_allocator();
// Fast path. If we have one group, it must be catch-all group.
if (groups.size() == 1) {
group_idx = 0;
StringRef authority, path;
if (req.forwarded_once) {
if (groups.size() != 1) {
authority = req.orig_authority;
path = req.orig_path;
}
} else {
StringRef authority;
if (faddr_->sni_fwd) {
authority = sni_;
} else if (!req.authority.empty()) {
......@@ -924,13 +927,24 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
}
}
StringRef path;
// CONNECT method does not have path. But we requires path in
// host-path mapping. As workaround, we assume that path is "/".
// host-path mapping. As workaround, we assume that path is
// "/".
if (!req.regular_connect_method()) {
path = req.path;
}
// Cache the authority and path used for the first-time backend
// selection because per-pattern mruby script can change them.
req.orig_authority = authority;
req.orig_path = path;
req.forwarded_once = true;
}
// Fast path. If we have one group, it must be catch-all group.
if (groups.size() == 1) {
group_idx = 0;
} else {
group_idx = match_downstream_addr_group(routerconf, authority, path, groups,
catch_all, balloc);
}
......
......@@ -153,7 +153,8 @@ struct Request {
http2_upgrade_seen(false),
connection_close(false),
http2_expect_body(false),
no_authority(false) {}
no_authority(false),
forwarded_once(false) {}
void consume(size_t len) {
assert(unconsumed_body_length >= len);
......@@ -184,6 +185,12 @@ struct Request {
// request-target. For HTTP/2, this is :path header field value.
// For CONNECT request, this is empty.
StringRef path;
// This is original authority which cannot be changed by per-pattern
// mruby script.
StringRef orig_authority;
// This is original path which cannot be changed by per-pattern
// mruby script.
StringRef orig_path;
// the length of request body received so far
int64_t recv_body_length;
// The number of bytes not consumed by the application yet.
......@@ -209,6 +216,10 @@ struct Request {
// This happens when: For HTTP/2 request, :authority is missing.
// For HTTP/1 request, origin or asterisk form is used.
bool no_authority;
// true if backend selection is done for request once.
// orig_authority and orig_path have the authority and path which
// are used for the first backend selection.
bool forwarded_once;
};
struct Response {
......
......@@ -146,13 +146,22 @@ std::string colorizeHeaders(const char *hdrs) {
nhdrs += TTY_HTTP_HD;
nhdrs.append(p, np);
nhdrs += TTY_RST;
auto redact = util::strieq_l("authorization", StringRef{p, np});
p = np;
np = strchr(p, '\n');
if (!np) {
nhdrs.append(p);
if (redact) {
nhdrs.append(": <redacted>");
} else {
nhdrs.append(p);
}
break;
}
nhdrs.append(p, np + 1);
if (redact) {
nhdrs.append(": <redacted>\n");
} else {
nhdrs.append(p, np + 1);
}
p = np + 1;
}
return nhdrs;
......
......@@ -463,6 +463,11 @@ int Http2DownstreamConnection::push_request_headers() {
if (LOG_ENABLED(INFO)) {
std::stringstream ss;
for (auto &nv : nva) {
if (util::streq_l("authorization", nv.name, nv.namelen)) {
ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST
<< ": <redacted>\n";
continue;
}
ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": "
<< StringRef{nv.value, nv.valuelen} << "\n";
}
......
......@@ -321,6 +321,10 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
if (LOG_ENABLED(INFO)) {
std::stringstream ss;
for (auto &nv : nva) {
if (nv.name == "authorization") {
ss << TTY_HTTP_HD << nv.name << TTY_RST << ": <redacted>\n";
continue;
}
ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n";
}
ULOG(INFO, this) << "HTTP request headers. stream_id="
......
......@@ -696,8 +696,9 @@ int HttpDownstreamConnection::process_blocked_request_buf() {
}
}
if (downstream_->get_blocked_request_data_eof()) {
return end_upload_data();
if (downstream_->get_blocked_request_data_eof() &&
downstream_->get_chunked_request()) {
end_upload_data_chunk();
}
return 0;
......@@ -751,6 +752,12 @@ int HttpDownstreamConnection::end_upload_data() {
return 0;
}
end_upload_data_chunk();
return 0;
}
void HttpDownstreamConnection::end_upload_data_chunk() {
const auto &req = downstream_->request();
auto output = downstream_->get_request_buf();
......@@ -763,8 +770,6 @@ int HttpDownstreamConnection::end_upload_data() {
http2::HDOP_STRIP_ALL);
output->append("\r\n");
}
return 0;
}
namespace {
......
......@@ -53,6 +53,7 @@ public:
virtual int push_request_headers();
virtual int push_upload_data_chunk(const uint8_t *data, size_t datalen);
virtual int end_upload_data();
void end_upload_data_chunk();
virtual void pause_read(IOCtrlReason reason);
virtual int resume_read(IOCtrlReason reason, size_t consumed);
......
......@@ -318,6 +318,10 @@ int htp_hdrs_completecb(http_parser *htp) {
<< "HTTP/" << req.http_major << "." << req.http_minor << "\n";
for (const auto &kv : req.fs.headers()) {
if (kv.name == "authorization") {
ss << TTY_HTTP_HD << kv.name << TTY_RST << ": <redacted>\n";
continue;
}
ss << TTY_HTTP_HD << kv.name << TTY_RST << ": " << kv.value << "\n";
}
......
......@@ -364,11 +364,11 @@ int tls_session_new_cb(SSL *ssl, SSL_SESSION *session) {
namespace {
SSL_SESSION *tls_session_get_cb(SSL *ssl,
#if OPENSSL_1_1_API
#if OPENSSL_1_1_API || LIBRESSL_2_7_API
const unsigned char *id,
#else // !OPENSSL_1_1_API
#else // !(OPENSSL_1_1_API || LIBRESSL_2_7_API)
unsigned char *id,
#endif // !OPENSSL_1_1_API
#endif // !(OPENSSL_1_1_API || LIBRESSL_2_7_API)
int idlen, int *copy) {
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
auto handler = static_cast<ClientHandler *>(conn->data);
......
......@@ -91,6 +91,8 @@ int main() {
test_nghttp2_session_recv_headers_with_padding) ||
!CU_add_test(pSuite, "session_recv_headers_early_response",
test_nghttp2_session_recv_headers_early_response) ||
!CU_add_test(pSuite, "session_recv_headers_for_closed_stream",
test_nghttp2_session_recv_headers_for_closed_stream) ||
!CU_add_test(pSuite, "session_server_recv_push_response",
test_nghttp2_session_server_recv_push_response) ||
!CU_add_test(pSuite, "session_recv_premature_headers",
......
......@@ -1743,6 +1743,91 @@ void test_nghttp2_session_recv_headers_early_response(void) {
nghttp2_bufs_free(&bufs);
}
void test_nghttp2_session_recv_headers_for_closed_stream(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_nv *nva;
size_t nvlen;
nghttp2_frame frame;
nghttp2_bufs bufs;
nghttp2_buf *buf;
ssize_t rv;
my_user_data ud;
nghttp2_hd_deflater deflater;
nghttp2_stream *stream;
nghttp2_mem *mem;
const uint8_t *data;
mem = nghttp2_mem_default();
frame_pack_bufs_init(&bufs);
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_header_callback = on_header_callback;
nghttp2_session_server_new(&session, &callbacks, &ud);
nghttp2_hd_deflate_init(&deflater, mem);
/* Make sure that on_header callback never be invoked for closed
stream */
nvlen = ARRLEN(reqnv);
nghttp2_nv_array_copy(&nva, reqnv, nvlen, mem);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv);
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
nghttp2_frame_headers_free(&frame.headers, mem);
buf = &bufs.head->buf;
assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
ud.header_cb_called = 0;
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf->pos, NGHTTP2_FRAME_HDLEN);
CU_ASSERT(NGHTTP2_FRAME_HDLEN == rv);
CU_ASSERT(0 == ud.header_cb_called);
CU_ASSERT(0 == ud.frame_recv_cb_called);
stream = nghttp2_session_get_stream(session, 1);
CU_ASSERT(NULL != stream);
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 1,
NGHTTP2_NO_ERROR);
CU_ASSERT(0 == rv);
rv = nghttp2_session_mem_send(session, &data);
CU_ASSERT(rv > 0);
stream = nghttp2_session_get_stream(session, 1);
CU_ASSERT(NULL == stream);
ud.header_cb_called = 0;
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf->pos + NGHTTP2_FRAME_HDLEN,
nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN);
CU_ASSERT((ssize_t)nghttp2_buf_len(buf) - NGHTTP2_FRAME_HDLEN == rv);
CU_ASSERT(0 == ud.header_cb_called);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_bufs_free(&bufs);
nghttp2_hd_deflate_free(&deflater);
nghttp2_session_del(session);
}
void test_nghttp2_session_server_recv_push_response(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
......
......@@ -39,6 +39,7 @@ void test_nghttp2_session_recv_continuation(void);
void test_nghttp2_session_recv_headers_with_priority(void);
void test_nghttp2_session_recv_headers_with_padding(void);
void test_nghttp2_session_recv_headers_early_response(void);
void test_nghttp2_session_recv_headers_for_closed_stream(void);
void test_nghttp2_session_server_recv_push_response(void);
void test_nghttp2_session_recv_premature_headers(void);
void test_nghttp2_session_recv_unknown_frame(void);
......
......@@ -1496,28 +1496,24 @@ reexecute:
switch (h_state) {
case h_general:
{
const char* p_cr;
const char* p_lf;
size_t limit = data + len - p;
limit = MIN(limit, max_header_size);
p_cr = (const char*) memchr(p, CR, limit);
p_lf = (const char*) memchr(p, LF, limit);
if (p_cr != NULL) {
if (p_lf != NULL && p_cr >= p_lf)
p = p_lf;
else
p = p_cr;
} else if (UNLIKELY(p_lf != NULL)) {
p = p_lf;
} else {
p = data + len;
{
const char* limit = p + MIN(data + len - p, max_header_size);
for (; p != limit; p++) {
ch = *p;
if (ch == CR || ch == LF) {
--p;
break;
}
if (!lenient && !IS_HEADER_CHAR(ch)) {
SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
goto error;
}
}
if (p == data + len)
--p;
break;
}
--p;
break;
}
case h_connection:
case h_transfer_encoding:
......
......@@ -27,7 +27,7 @@ extern "C" {
/* Also update SONAME in the Makefile whenever you change these. */
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 9
#define HTTP_PARSER_VERSION_PATCH 0
#define HTTP_PARSER_VERSION_PATCH 1
#include <stddef.h>
#if defined(_WIN32) && !defined(__MINGW32__) && \
......