From 46576178a3e3566f2a43b337eb279266bf98f9aa Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 14 Oct 2018 22:57:54 +0900 Subject: [PATCH] Don't send Transfer-Encoding to pre-HTTP/1.1 clients --- src/http2.cc | 9 +++++++++ src/http2.h | 7 +++++++ src/shrpx_http_downstream_connection.cc | 5 +++++ src/shrpx_https_upstream.cc | 8 ++++++-- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/http2.cc b/src/http2.cc index 566cfb00..74360a50 100644 --- a/src/http2.cc +++ b/src/http2.cc @@ -503,6 +503,11 @@ void build_http1_headers_from_headers(DefaultMemchunks *buf, continue; } break; + case HD_TRANSFER_ENCODING: + if (flags & HDOP_STRIP_TRANSFER_ENCODING) { + continue; + } + break; case HD_FORWARDED: if (flags & HDOP_STRIP_FORWARDED) { continue; @@ -1874,6 +1879,10 @@ StringRef make_websocket_accept_token(uint8_t *dest, const StringRef &key) { return StringRef{dest, end}; } +bool legacy_http1(int major, int minor) { + return major <= 0 || (major == 1 && minor == 0); +} + } // namespace http2 } // namespace nghttp2 diff --git a/src/http2.h b/src/http2.h index 9e7d7491..5b8ef284 100644 --- a/src/http2.h +++ b/src/http2.h @@ -217,6 +217,9 @@ enum HeaderBuildOp { // Sec-WebSocket-Key header field must be stripped. If this flag is // not set, all Sec-WebSocket-Key header fields are added. HDOP_STRIP_SEC_WEBSOCKET_KEY = 1 << 6, + // Transfer-Encoding header field must be stripped. If this flag is + // not set, all Transfer-Encoding header fields are added. + HDOP_STRIP_TRANSFER_ENCODING = 1 << 7, }; // Appends headers in |headers| to |nv|. |headers| must be indexed @@ -437,6 +440,10 @@ bool contains_trailers(const StringRef &s); // of error. StringRef make_websocket_accept_token(uint8_t *dest, const StringRef &key); +// Returns true if HTTP version represents pre-HTTP/1.1 (e.g., +// HTTP/0.9 or HTTP/1.0). +bool legacy_http1(int major, int minor); + } // namespace http2 } // namespace nghttp2 diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index 31f48a24..50d8634c 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -1000,6 +1000,11 @@ int htp_hdrs_completecb(http_parser *htp) { resp.connection_close = true; // transfer-encoding not applied to upgraded connection downstream->set_chunked_response(false); + } else if (http2::legacy_http1(req.http_major, req.http_minor)) { + if (resp.fs.content_length == -1) { + resp.connection_close = true; + } + downstream->set_chunked_response(false); } else if (!downstream->expect_response_body()) { downstream->set_chunked_response(false); } diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index b6953a76..d4e8538c 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -1122,8 +1122,12 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) { return 0; } - http2::build_http1_headers_from_headers( - buf, resp.fs.headers(), http2::HDOP_STRIP_ALL & ~http2::HDOP_STRIP_VIA); + auto build_flags = (http2::HDOP_STRIP_ALL & ~http2::HDOP_STRIP_VIA) | + (!http2::legacy_http1(req.http_major, req.http_minor) + ? 0 + : http2::HDOP_STRIP_TRANSFER_ENCODING); + + http2::build_http1_headers_from_headers(buf, resp.fs.headers(), build_flags); auto worker = handler_->get_worker();