From 4fca2502d8a7dc8f5e53768a1b9433c03a5d3e12 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 17 May 2019 22:04:46 +0900 Subject: [PATCH] nghttpx: Ignore Content-Length and Transfer-Encoding in 1xx or 200 to CONNECT A well known server sends content-length: 0 in 101 response. RFC 7230 says Content-Length or Transfer-Encoding in 200 response to CONNECT request: https://tools.ietf.org/html/rfc7230#section-3.3.3 --- src/shrpx_downstream.cc | 12 ++++++++++++ src/shrpx_downstream.h | 4 ++++ src/shrpx_http_downstream_connection.cc | 11 ++++------- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index 72a5b8ee..66daff66 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -573,6 +573,18 @@ void FieldStore::append_last_trailer_value(const char *data, size_t len) { trailers_, data, len); } +void FieldStore::erase_content_length_and_transfer_encoding() { + for (auto &kv : headers_) { + switch (kv.token) { + case http2::HD_CONTENT_LENGTH: + case http2::HD_TRANSFER_ENCODING: + kv.name = StringRef{}; + kv.token = -1; + break; + } + } +} + void Downstream::set_request_start_time( std::chrono::high_resolution_clock::time_point time) { request_start_time_ = std::move(time); diff --git a/src/shrpx_downstream.h b/src/shrpx_downstream.h index d507d101..d82d7c9b 100644 --- a/src/shrpx_downstream.h +++ b/src/shrpx_downstream.h @@ -119,6 +119,10 @@ public: bool trailer_key_prev() const { return trailer_key_prev_; } + // erase_content_length_and_transfer_encoding erases content-length + // and transfer-encoding header fields. + void erase_content_length_and_transfer_encoding(); + // content-length, -1 if it is unknown. int64_t content_length; diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index 3f7fb82e..c03e2723 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -935,18 +935,15 @@ int htp_hdrs_completecb(llhttp_t *htp) { return -1; } if (resp.fs.content_length == 0) { - auto cl = resp.fs.header(http2::HD_CONTENT_LENGTH); - assert(cl); - http2::erase_header(cl); + resp.fs.erase_content_length_and_transfer_encoding(); } else if (resp.fs.content_length != -1) { return -1; } } else if (resp.http_status / 100 == 1 || (resp.http_status / 100 == 2 && req.method == HTTP_CONNECT)) { - if (resp.fs.header(http2::HD_CONTENT_LENGTH) || - resp.fs.header(http2::HD_TRANSFER_ENCODING)) { - return -1; - } + // Server MUST NOT send Content-Length and Transfer-Encoding in + // these responses. + resp.fs.erase_content_length_and_transfer_encoding(); } else if (resp.fs.parse_content_length() != 0) { downstream->set_response_state(DownstreamState::MSG_BAD_HEADER); return -1;