From 2576855dedfed40f35353e136de87f242c28dba5 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 21 Sep 2017 21:42:56 +0900 Subject: [PATCH] nghttpx: Send non-final response to HTTP/1.1 or HTTP/2 client only --- src/shrpx-unittest.cc | 2 ++ src/shrpx_downstream.cc | 4 ++++ src/shrpx_downstream.h | 3 +++ src/shrpx_downstream_test.cc | 25 +++++++++++++++++++++++++ src/shrpx_downstream_test.h | 1 + src/shrpx_https_upstream.cc | 5 +++++ 6 files changed, 40 insertions(+) diff --git a/src/shrpx-unittest.cc b/src/shrpx-unittest.cc index da427740..88c1dc40 100644 --- a/src/shrpx-unittest.cc +++ b/src/shrpx-unittest.cc @@ -115,6 +115,8 @@ int main(int argc, char *argv[]) { shrpx::test_downstream_assemble_request_cookie) || !CU_add_test(pSuite, "downstream_rewrite_location_response_header", shrpx::test_downstream_rewrite_location_response_header) || + !CU_add_test(pSuite, "downstream_supports_non_final_response", + shrpx::test_downstream_supports_non_final_response) || !CU_add_test(pSuite, "config_parse_header", shrpx::test_shrpx_config_parse_header) || !CU_add_test(pSuite, "config_parse_log_format", diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index e4236e54..5683dac8 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -743,6 +743,10 @@ bool Downstream::get_non_final_response() const { return !upgraded_ && resp_.http_status / 100 == 1; } +bool Downstream::supports_non_final_response() const { + return req_.http_major == 2 || (req_.http_major == 1 && req_.http_minor == 1); +} + bool Downstream::get_upgraded() const { return upgraded_; } bool Downstream::get_http2_upgrade_request() const { diff --git a/src/shrpx_downstream.h b/src/shrpx_downstream.h index 28c177d4..42ff4013 100644 --- a/src/shrpx_downstream.h +++ b/src/shrpx_downstream.h @@ -348,6 +348,9 @@ public: // True if the response is non-final (1xx status code). Note that // if connection was upgraded, 101 status code is treated as final. bool get_non_final_response() const; + // True if protocol version used by client supports non final + // response. Only HTTP/1.1 and HTTP/2 clients support it. + bool supports_non_final_response() const; void set_expect_final_response(bool f); bool get_expect_final_response() const; diff --git a/src/shrpx_downstream_test.cc b/src/shrpx_downstream_test.cc index 77895305..fc8c54a8 100644 --- a/src/shrpx_downstream_test.cc +++ b/src/shrpx_downstream_test.cc @@ -164,4 +164,29 @@ void test_downstream_rewrite_location_response_header(void) { CU_ASSERT("https://localhost:8443/" == (*location).value); } +void test_downstream_supports_non_final_response(void) { + Downstream d(nullptr, nullptr, 0); + auto &req = d.request(); + + req.http_major = 2; + req.http_minor = 0; + + CU_ASSERT(d.supports_non_final_response()); + + req.http_major = 1; + req.http_minor = 1; + + CU_ASSERT(d.supports_non_final_response()); + + req.http_major = 1; + req.http_minor = 0; + + CU_ASSERT(!d.supports_non_final_response()); + + req.http_major = 0; + req.http_minor = 9; + + CU_ASSERT(!d.supports_non_final_response()); +} + } // namespace shrpx diff --git a/src/shrpx_downstream_test.h b/src/shrpx_downstream_test.h index f7b1e603..c042de17 100644 --- a/src/shrpx_downstream_test.h +++ b/src/shrpx_downstream_test.h @@ -36,6 +36,7 @@ void test_downstream_field_store_header(void); void test_downstream_crumble_request_cookie(void); void test_downstream_assemble_request_cookie(void); void test_downstream_rewrite_location_response_header(void); +void test_downstream_supports_non_final_response(void); } // namespace shrpx diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index 976904ed..ef8c4e56 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -1022,6 +1022,11 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) { auto &resp = downstream->response(); auto &balloc = downstream->get_block_allocator(); + if (!downstream->supports_non_final_response()) { + resp.fs.clear_headers(); + return 0; + } + #ifdef HAVE_MRUBY if (!downstream->get_non_final_response()) { auto worker = handler_->get_worker();