diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index e71893a8..34669cf2 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -120,10 +120,10 @@ Downstream::Downstream(Upstream *upstream, int32_t stream_id, int32_t priority) response_minor_(1), upgrade_request_(false), upgraded_(false), http2_upgrade_seen_(false), chunked_request_(false), request_connection_close_(false), request_header_key_prev_(false), - request_http2_expect_body_(false), chunked_response_(false), - response_connection_close_(false), response_header_key_prev_(false), - response_trailer_key_prev_(false), expect_final_response_(false), - request_pending_(false) { + request_trailer_key_prev_(false), request_http2_expect_body_(false), + chunked_response_(false), response_connection_close_(false), + response_header_key_prev_(false), response_trailer_key_prev_(false), + expect_final_response_(false), request_pending_(false) { ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0., get_config()->stream_read_timeout); @@ -288,6 +288,45 @@ const std::string &Downstream::get_assembled_request_cookie() const { return assembled_request_cookie_; } +namespace { +void add_header(bool &key_prev, size_t &sum, Headers &headers, std::string name, + std::string value) { + key_prev = true; + sum += name.size() + value.size(); + headers.emplace_back(std::move(name), std::move(value)); +} +} // namespace + +namespace { +void append_last_header_key(bool key_prev, size_t &sum, Headers &headers, + const char *data, size_t len) { + assert(key_prev); + sum += len; + auto &item = headers.back(); + item.name.append(data, len); +} +} // namespace + +namespace { +void append_last_header_value(bool key_prev, size_t &sum, Headers &headers, + const char *data, size_t len) { + assert(!key_prev); + sum += len; + auto &item = headers.back(); + item.value.append(data, len); +} +} // namespace + +namespace { +void set_last_header_value(bool &key_prev, size_t &sum, Headers &headers, + const char *data, size_t len) { + key_prev = false; + sum += len; + auto &item = headers.back(); + item.value.assign(data, len); +} +} // namespace + namespace { int index_headers(http2::HeaderIndex &hdidx, Headers &headers, int64_t &content_length) { @@ -334,16 +373,13 @@ Downstream::get_request_header(const std::string &name) const { } void Downstream::add_request_header(std::string name, std::string value) { - request_header_key_prev_ = true; - request_headers_sum_ += name.size() + value.size(); - request_headers_.emplace_back(std::move(name), std::move(value)); + add_header(request_header_key_prev_, request_headers_sum_, request_headers_, + std::move(name), std::move(value)); } -void Downstream::set_last_request_header_value(std::string value) { - request_header_key_prev_ = false; - request_headers_sum_ += value.size(); - Headers::value_type &item = request_headers_.back(); - item.value = std::move(value); +void Downstream::set_last_request_header_value(const char *data, size_t len) { + set_last_header_value(request_header_key_prev_, request_headers_sum_, + request_headers_, data, len); } void Downstream::add_request_header(const uint8_t *name, size_t namelen, @@ -360,18 +396,14 @@ bool Downstream::get_request_header_key_prev() const { } void Downstream::append_last_request_header_key(const char *data, size_t len) { - assert(request_header_key_prev_); - request_headers_sum_ += len; - auto &item = request_headers_.back(); - item.name.append(data, len); + append_last_header_key(request_header_key_prev_, request_headers_sum_, + request_headers_, data, len); } void Downstream::append_last_request_header_value(const char *data, size_t len) { - assert(!request_header_key_prev_); - request_headers_sum_ += len; - auto &item = request_headers_.back(); - item.value.append(data, len); + append_last_header_value(request_header_key_prev_, request_headers_sum_, + request_headers_, data, len); } void Downstream::clear_request_headers() { @@ -397,6 +429,31 @@ const Headers &Downstream::get_request_trailers() const { return request_trailers_; } +void Downstream::add_request_trailer(std::string name, std::string value) { + add_header(request_trailer_key_prev_, request_headers_sum_, request_trailers_, + std::move(name), std::move(value)); +} + +void Downstream::set_last_request_trailer_value(const char *data, size_t len) { + set_last_header_value(request_trailer_key_prev_, request_headers_sum_, + request_trailers_, data, len); +} + +bool Downstream::get_request_trailer_key_prev() const { + return request_trailer_key_prev_; +} + +void Downstream::append_last_request_trailer_key(const char *data, size_t len) { + append_last_header_key(request_trailer_key_prev_, request_headers_sum_, + request_trailers_, data, len); +} + +void Downstream::append_last_request_trailer_value(const char *data, + size_t len) { + append_last_header_value(request_trailer_key_prev_, request_headers_sum_, + request_trailers_, data, len); +} + void Downstream::set_request_method(std::string method) { request_method_ = std::move(method); } @@ -607,16 +664,13 @@ void Downstream::rewrite_location_response_header( } void Downstream::add_response_header(std::string name, std::string value) { - response_header_key_prev_ = true; - response_headers_sum_ += name.size() + value.size(); - response_headers_.emplace_back(std::move(name), std::move(value)); + add_header(response_header_key_prev_, response_headers_sum_, + response_headers_, std::move(name), std::move(value)); } -void Downstream::set_last_response_header_value(std::string value) { - response_header_key_prev_ = false; - response_headers_sum_ += value.size(); - auto &item = response_headers_.back(); - item.value = std::move(value); +void Downstream::set_last_response_header_value(const char *data, size_t len) { + set_last_header_value(response_header_key_prev_, response_headers_sum_, + response_headers_, data, len); } void Downstream::add_response_header(std::string name, std::string value, @@ -641,18 +695,14 @@ bool Downstream::get_response_header_key_prev() const { } void Downstream::append_last_response_header_key(const char *data, size_t len) { - assert(response_header_key_prev_); - response_headers_sum_ += len; - auto &item = response_headers_.back(); - item.name.append(data, len); + append_last_header_key(response_header_key_prev_, response_headers_sum_, + response_headers_, data, len); } void Downstream::append_last_response_header_value(const char *data, size_t len) { - assert(!response_header_key_prev_); - response_headers_sum_ += len; - auto &item = response_headers_.back(); - item.value.append(data, len); + append_last_header_value(response_header_key_prev_, response_headers_sum_, + response_headers_, data, len); } void Downstream::clear_response_headers() { @@ -681,9 +731,13 @@ unsigned int Downstream::get_response_http_status() const { } void Downstream::add_response_trailer(std::string name, std::string value) { - response_trailer_key_prev_ = true; - response_headers_sum_ += name.size() + value.size(); - response_trailers_.emplace_back(std::move(name), std::move(value)); + add_header(response_trailer_key_prev_, response_headers_sum_, + response_trailers_, std::move(name), std::move(value)); +} + +void Downstream::set_last_response_trailer_value(const char *data, size_t len) { + set_last_header_value(response_trailer_key_prev_, response_headers_sum_, + response_trailers_, data, len); } bool Downstream::get_response_trailer_key_prev() const { @@ -692,25 +746,14 @@ bool Downstream::get_response_trailer_key_prev() const { void Downstream::append_last_response_trailer_key(const char *data, size_t len) { - assert(response_trailer_key_prev_); - response_headers_sum_ += len; - auto &item = response_trailers_.back(); - item.name.append(data, len); + append_last_header_key(response_trailer_key_prev_, response_headers_sum_, + response_trailers_, data, len); } void Downstream::append_last_response_trailer_value(const char *data, size_t len) { - assert(!response_trailer_key_prev_); - response_headers_sum_ += len; - auto &item = response_trailers_.back(); - item.value.append(data, len); -} - -void Downstream::set_last_response_trailer_value(std::string value) { - response_trailer_key_prev_ = false; - response_headers_sum_ += value.size(); - auto &item = response_trailers_.back(); - item.value = std::move(value); + append_last_header_value(response_trailer_key_prev_, response_headers_sum_, + response_trailers_, data, len); } void Downstream::set_response_http_status(unsigned int status) { diff --git a/src/shrpx_downstream.h b/src/shrpx_downstream.h index 8ffff731..e1a51f4c 100644 --- a/src/shrpx_downstream.h +++ b/src/shrpx_downstream.h @@ -113,7 +113,7 @@ public: // no such header is found, returns nullptr. const Headers::value_type *get_request_header(const std::string &name) const; void add_request_header(std::string name, std::string value); - void set_last_request_header_value(std::string value); + void set_last_request_header_value(const char *data, size_t len); void add_request_header(const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, bool no_index, @@ -131,6 +131,11 @@ public: void add_request_trailer(const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, bool no_index, int16_t token); + void add_request_trailer(std::string name, std::string value); + void set_last_request_trailer_value(const char *data, size_t len); + bool get_request_trailer_key_prev() const; + void append_last_request_trailer_key(const char *data, size_t len); + void append_last_request_trailer_value(const char *data, size_t len); void set_request_method(std::string method); const std::string &get_request_method() const; @@ -206,7 +211,7 @@ public: // Rewrites the location response header field. void rewrite_location_response_header(const std::string &upstream_scheme); void add_response_header(std::string name, std::string value); - void set_last_response_header_value(std::string value); + void set_last_response_header_value(const char *data, size_t len); void add_response_header(std::string name, std::string value, int16_t token); void add_response_header(const uint8_t *name, size_t namelen, @@ -226,10 +231,10 @@ public: const uint8_t *value, size_t valuelen, bool no_index, int16_t token); void add_response_trailer(std::string name, std::string value); + void set_last_response_trailer_value(const char *data, size_t len); bool get_response_trailer_key_prev() const; void append_last_response_trailer_key(const char *data, size_t len); void append_last_response_trailer_value(const char *data, size_t len); - void set_last_response_trailer_value(std::string value); unsigned int get_response_http_status() const; void set_response_http_status(unsigned int status); @@ -405,6 +410,7 @@ private: bool chunked_request_; bool request_connection_close_; bool request_header_key_prev_; + bool request_trailer_key_prev_; bool request_http2_expect_body_; bool chunked_response_; diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index 8630815d..be8981cd 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -594,13 +594,13 @@ int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) { auto downstream = static_cast(htp->data); if (downstream->get_response_state() == Downstream::INITIAL) { if (downstream->get_response_header_key_prev()) { - downstream->set_last_response_header_value(std::string(data, len)); + downstream->set_last_response_header_value(data, len); } else { downstream->append_last_response_header_value(data, len); } } else { if (downstream->get_response_trailer_key_prev()) { - downstream->set_last_response_trailer_value(std::string(data, len)); + downstream->set_last_response_trailer_value(data, len); } else { downstream->append_last_response_trailer_value(data, len); } diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index 1020adb1..b14a8664 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -83,14 +83,19 @@ namespace { int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) { auto upstream = static_cast(htp->data); auto downstream = upstream->get_downstream(); - if (downstream->get_request_state() != Downstream::INITIAL) { - // ignore trailers - return 0; - } - if (downstream->get_request_header_key_prev()) { - downstream->append_last_request_header_key(data, len); + if (downstream->get_request_state() == Downstream::INITIAL) { + if (downstream->get_request_header_key_prev()) { + downstream->append_last_request_header_key(data, len); + } else { + downstream->add_request_header(std::string(data, len), ""); + } } else { - downstream->add_request_header(std::string(data, len), ""); + // trailer part + if (downstream->get_request_trailer_key_prev()) { + downstream->append_last_request_trailer_key(data, len); + } else { + downstream->add_request_trailer(std::string(data, len), ""); + } } if (downstream->get_request_headers_sum() > Downstream::MAX_HEADERS_SUM) { if (LOG_ENABLED(INFO)) { @@ -107,14 +112,18 @@ namespace { int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) { auto upstream = static_cast(htp->data); auto downstream = upstream->get_downstream(); - if (downstream->get_request_state() != Downstream::INITIAL) { - // ignore trailers - return 0; - } - if (downstream->get_request_header_key_prev()) { - downstream->set_last_request_header_value(std::string(data, len)); + if (downstream->get_request_state() == Downstream::INITIAL) { + if (downstream->get_request_header_key_prev()) { + downstream->set_last_request_header_value(data, len); + } else { + downstream->append_last_request_header_value(data, len); + } } else { - downstream->append_last_request_header_value(data, len); + if (downstream->get_request_trailer_key_prev()) { + downstream->set_last_request_trailer_value(data, len); + } else { + downstream->append_last_request_trailer_value(data, len); + } } if (downstream->get_request_headers_sum() > Downstream::MAX_HEADERS_SUM) { if (LOG_ENABLED(INFO)) {