diff --git a/examples/shrpx_downstream.cc b/examples/shrpx_downstream.cc index 9411f050..be4d6d94 100644 --- a/examples/shrpx_downstream.cc +++ b/examples/shrpx_downstream.cc @@ -49,6 +49,7 @@ Downstream::Downstream(Upstream *upstream, int stream_id, int priority) request_minor_(1), chunked_request_(false), request_connection_close_(false), + request_expect_100_continue_(false), response_state_(INITIAL), response_http_status_(0), response_major_(1), @@ -111,15 +112,31 @@ void Downstream::force_resume_read() ioctrl_.force_resume_read(); } +namespace { +void check_header_field(bool *result, const Headers::value_type &item, + const char *name, const char *value) +{ + if(util::strieq(item.first.c_str(), name)) { + if(util::strifind(item.second.c_str(), value)) { + *result = true; + } + } +} +} // namespace + namespace { void check_transfer_encoding_chunked(bool *chunked, const Headers::value_type &item) { - if(util::strieq(item.first.c_str(), "transfer-encoding")) { - if(util::strifind(item.second.c_str(), "chunked")) { - *chunked = true; - } - } + return check_header_field(chunked, item, "transfer-encoding", "chunked"); +} +} // namespace + +namespace { +void check_expect_100_continue(bool *res, + const Headers::value_type& item) +{ + return check_header_field(res, item, "expect", "100-continue"); } } // namespace @@ -136,7 +153,7 @@ void check_connection_close(bool *connection_close, } } } // namespace - + void Downstream::add_request_header(const std::string& name, const std::string& value) { @@ -148,6 +165,7 @@ void Downstream::set_last_request_header_value(const std::string& value) Headers::value_type &item = request_headers_.back(); item.second = value; check_transfer_encoding_chunked(&chunked_request_, item); + check_expect_100_continue(&request_expect_100_continue_, item); check_connection_close(&request_connection_close_, item); } @@ -216,6 +234,11 @@ void Downstream::set_request_connection_close(bool f) request_connection_close_ = f; } +bool Downstream::get_expect_100_continue() const +{ + return request_expect_100_continue_; +} + namespace { const size_t DOWNSTREAM_OUTPUT_UPPER_THRES = 64*1024; } // namespace @@ -255,6 +278,10 @@ int Downstream::push_request_headers() if(util::strieq((*i).first.c_str(), "host")) { continue; } + if(util::strieq((*i).first.c_str(), "expect") && + util::strifind((*i).second.c_str(), "100-continue")) { + continue; + } hdrs += (*i).first; hdrs += ": "; hdrs += (*i).second; diff --git a/examples/shrpx_downstream.h b/examples/shrpx_downstream.h index 5fd7b29a..fb1605e1 100644 --- a/examples/shrpx_downstream.h +++ b/examples/shrpx_downstream.h @@ -80,6 +80,7 @@ public: bool get_chunked_request() const; bool get_request_connection_close() const; void set_request_connection_close(bool f); + bool get_expect_100_continue() const; int push_upload_data_chunk(const uint8_t *data, size_t datalen); int end_upload_data(); enum { @@ -122,6 +123,7 @@ private: int request_minor_; bool chunked_request_; bool request_connection_close_; + bool request_expect_100_continue_; Headers request_headers_; int response_state_; diff --git a/examples/shrpx_https_upstream.cc b/examples/shrpx_https_upstream.cc index a0898ab7..cf77408a 100644 --- a/examples/shrpx_https_upstream.cc +++ b/examples/shrpx_https_upstream.cc @@ -161,6 +161,12 @@ int htp_hdrs_completecb(htparser *htp) DownstreamConnection *dconn; dconn = upstream->get_client_handler()->get_downstream_connection(); + if(downstream->get_expect_100_continue()) { + static const char reply_100[] = "HTTP/1.1 100 Continue\r\n\r\n"; + bufferevent_write(upstream->get_client_handler()->get_bev(), + reply_100, sizeof(reply_100)-1); + } + int rv = dconn->attach_downstream(downstream); if(rv != 0) { downstream->set_request_state(Downstream::CONNECT_FAIL);