From ee076947833f3d5664cc2196c493f451559bc7e1 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 6 Feb 2016 17:22:23 +0900 Subject: [PATCH] nghttpx: Add request-header-field-buffer and max-request-header-fields options This commit adds request-header-field-buffer and max-request-header-fields, and deprecates header-field-buffer and max-header-fields options. --- gennghttpxfun.py | 6 ++++-- src/shrpx.cc | 22 ++++++++++++++++------ src/shrpx_config.cc | 24 +++++++++++++++++++++--- src/shrpx_config.h | 8 ++++++-- src/shrpx_http2_session.cc | 4 ++-- src/shrpx_http2_upstream.cc | 4 ++-- src/shrpx_https_upstream.cc | 12 +++++++----- src/shrpx_spdy_upstream.cc | 4 ++-- 8 files changed, 60 insertions(+), 24 deletions(-) diff --git a/gennghttpxfun.py b/gennghttpxfun.py index d92026ed..627549aa 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -88,8 +88,6 @@ OPTIONS = [ "fetch-ocsp-response-file", "ocsp-update-interval", "no-ocsp", - "header-field-buffer", - "max-header-fields", "include", "tls-ticket-key-cipher", "host-rewrite", @@ -110,6 +108,10 @@ OPTIONS = [ "forwarded-for", "response-header-field-buffer", "max-response-header-fields", + "request-header-field-buffer", + "max-request-header-fields", + "header-field-buffer", + "max-header-fields", "no-http2-cipher-black-list" ] diff --git a/src/shrpx.cc b/src/shrpx.cc index 48f6f687..001ab1e3 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -1071,8 +1071,8 @@ void fill_default_config() { auto &httpconf = mod_config()->http; httpconf.server_name = "nghttpx nghttp2/" NGHTTP2_VERSION; httpconf.no_host_rewrite = true; - httpconf.header_field_buffer = 64_k; - httpconf.max_header_fields = 100; + httpconf.request_header_field_buffer = 64_k; + httpconf.max_request_header_fields = 100; httpconf.response_header_field_buffer = 64_k; httpconf.max_response_header_fields = 500; @@ -1775,18 +1775,18 @@ HTTP: won't replace anything already set. This option can be used several times to specify multiple header fields. Example: --add-response-header="foo: bar" - --header-field-buffer= + --request-header-field-buffer= Set maximum buffer size for incoming HTTP request header field list. This is the sum of header name and value in bytes. If trailer fields exist, they are counted towards this number. Default: )" - << util::utos_unit(get_config()->http.header_field_buffer) << R"( - --max-header-fields= + << util::utos_unit(get_config()->http.request_header_field_buffer) << R"( + --max-request-header-fields= Set maximum number of incoming HTTP request header fields. If trailer fields exist, they are counted towards this number. - Default: )" << get_config()->http.max_header_fields << R"( + Default: )" << get_config()->http.max_request_header_fields << R"( --response-header-field-buffer= Set maximum buffer size for incoming HTTP response header field list. This is the sum of header name and @@ -2372,6 +2372,8 @@ int main(int argc, char **argv) { {SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER, required_argument, &flag, 101}, {SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS, required_argument, &flag, 102}, {SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST, no_argument, &flag, 103}, + {SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER, required_argument, &flag, 104}, + {SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS, required_argument, &flag, 105}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -2813,6 +2815,14 @@ int main(int argc, char **argv) { // --no-http2-cipher-black-list cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST, "yes"); break; + case 104: + // --request-header-field-buffer + cmdcfgs.emplace_back(SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER, optarg); + break; + case 105: + // --max-request-header-fields + cmdcfgs.emplace_back(SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS, optarg); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 0f3e8824..d90c12d3 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -726,6 +726,7 @@ enum { SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT, SHRPX_OPTID_LOG_LEVEL, SHRPX_OPTID_MAX_HEADER_FIELDS, + SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS, SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS, SHRPX_OPTID_MRUBY_FILE, SHRPX_OPTID_NO_HOST_REWRITE, @@ -742,6 +743,7 @@ enum { SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE, SHRPX_OPTID_READ_BURST, SHRPX_OPTID_READ_RATE, + SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER, SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER, SHRPX_OPTID_RLIMIT_NOFILE, SHRPX_OPTID_STREAM_READ_TIMEOUT, @@ -1252,6 +1254,9 @@ int option_lookup_token(const char *name, size_t namelen) { if (util::strieq_l("backend-http2-window-bit", name, 24)) { return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS; } + if (util::strieq_l("max-request-header-field", name, 24)) { + return SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS; + } break; } break; @@ -1282,6 +1287,11 @@ int option_lookup_token(const char *name, size_t namelen) { return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED; } break; + case 'r': + if (util::strieq_l("request-header-field-buffe", name, 26)) { + return SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER; + } + break; case 's': if (util::strieq_l("worker-frontend-connection", name, 26)) { return SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS; @@ -2017,10 +2027,18 @@ int parse_config(const char *opt, const char *optarg, return 0; case SHRPX_OPTID_HEADER_FIELD_BUFFER: - return parse_uint_with_unit(&mod_config()->http.header_field_buffer, opt, - optarg); + LOG(WARN) << opt + << ": deprecated. Use request-header-field-buffer instead."; + // fall through + case SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER: + return parse_uint_with_unit(&mod_config()->http.request_header_field_buffer, + opt, optarg); case SHRPX_OPTID_MAX_HEADER_FIELDS: - return parse_uint(&mod_config()->http.max_header_fields, opt, optarg); + LOG(WARN) << opt << ": deprecated. Use max-request-header-fields instead."; + // fall through + case SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS: + return parse_uint(&mod_config()->http.max_request_header_fields, opt, + optarg); case SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER: return parse_uint_with_unit( &mod_config()->http.response_header_field_buffer, opt, optarg); diff --git a/src/shrpx_config.h b/src/shrpx_config.h index f485ae6f..02f027d1 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -196,6 +196,10 @@ constexpr char SHRPX_OPT_STRIP_INCOMING_FORWARDED[] = "strip-incoming-forwarded"; constexpr static char SHRPX_OPT_FORWARDED_BY[] = "forwarded-by"; constexpr char SHRPX_OPT_FORWARDED_FOR[] = "forwarded-for"; +constexpr char SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER[] = + "request-header-field-buffer"; +constexpr char SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS[] = + "max-request-header-fields"; constexpr char SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER[] = "response-header-field-buffer"; constexpr char SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS[] = @@ -425,8 +429,8 @@ struct HttpConfig { std::vector> add_request_headers; std::vector> add_response_headers; StringRef server_name; - size_t header_field_buffer; - size_t max_header_fields; + size_t request_header_field_buffer; + size_t max_request_header_fields; size_t response_header_field_buffer; size_t max_response_header_fields; bool no_via; diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index 6b5625e3..77502f7d 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -784,8 +784,8 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, // We use request header limit for PUSH_PROMISE if (promised_req.fs.buffer_size() + namelen + valuelen > - httpconf.header_field_buffer || - promised_req.fs.num_fields() >= httpconf.max_header_fields) { + httpconf.request_header_field_buffer || + promised_req.fs.num_fields() >= httpconf.max_request_header_fields) { if (LOG_ENABLED(INFO)) { DLOG(INFO, downstream) << "Too large or many header field size=" diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 363769cf..a08fc588 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -177,8 +177,8 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, auto &httpconf = get_config()->http; if (req.fs.buffer_size() + namelen + valuelen > - httpconf.header_field_buffer || - req.fs.num_fields() >= httpconf.max_header_fields) { + httpconf.request_header_field_buffer || + req.fs.num_fields() >= httpconf.max_request_header_fields) { if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { return 0; } diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index 0c288cab..1794b94c 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -89,7 +89,8 @@ int htp_uricb(http_parser *htp, const char *data, size_t len) { // We happen to have the same value for method token. req.method = htp->method; - if (req.fs.buffer_size() + len > get_config()->http.header_field_buffer) { + if (req.fs.buffer_size() + len > + get_config()->http.request_header_field_buffer) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Too large URI size=" << req.fs.buffer_size() + len; @@ -118,7 +119,7 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { auto &req = downstream->request(); auto &httpconf = get_config()->http; - if (req.fs.buffer_size() + len > httpconf.header_field_buffer) { + if (req.fs.buffer_size() + len > httpconf.request_header_field_buffer) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Too large header block size=" << req.fs.buffer_size() + len; @@ -132,7 +133,7 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { if (req.fs.header_key_prev()) { req.fs.append_last_header_key(data, len); } else { - if (req.fs.num_fields() >= httpconf.max_header_fields) { + if (req.fs.num_fields() >= httpconf.max_request_header_fields) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Too many header field num=" << req.fs.num_fields() + 1; @@ -148,7 +149,7 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { if (req.fs.trailer_key_prev()) { req.fs.append_last_trailer_key(data, len); } else { - if (req.fs.num_fields() >= httpconf.max_header_fields) { + if (req.fs.num_fields() >= httpconf.max_request_header_fields) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Too many header field num=" << req.fs.num_fields() + 1; @@ -168,7 +169,8 @@ int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) { auto downstream = upstream->get_downstream(); auto &req = downstream->request(); - if (req.fs.buffer_size() + len > get_config()->http.header_field_buffer) { + if (req.fs.buffer_size() + len > + get_config()->http.request_header_field_buffer) { if (LOG_ENABLED(INFO)) { ULOG(INFO, upstream) << "Too large header block size=" << req.fs.buffer_size() + len; diff --git a/src/shrpx_spdy_upstream.cc b/src/shrpx_spdy_upstream.cc index 0b3388a0..2a9ed64d 100644 --- a/src/shrpx_spdy_upstream.cc +++ b/src/shrpx_spdy_upstream.cc @@ -181,8 +181,8 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, // spdy does not define usage of trailer fields, and we ignores // them. - if (header_buffer > httpconf.header_field_buffer || - num_headers > httpconf.max_header_fields) { + if (header_buffer > httpconf.request_header_field_buffer || + num_headers > httpconf.max_request_header_fields) { upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); return; }