nghttpx: Support response trailer part handling in h1 backend
This commit is contained in:
parent
60c2fe5a2e
commit
6ad63a06b0
|
@ -122,7 +122,8 @@ Downstream::Downstream(Upstream *upstream, int32_t stream_id, int32_t priority)
|
||||||
request_connection_close_(false), request_header_key_prev_(false),
|
request_connection_close_(false), request_header_key_prev_(false),
|
||||||
request_http2_expect_body_(false), chunked_response_(false),
|
request_http2_expect_body_(false), chunked_response_(false),
|
||||||
response_connection_close_(false), response_header_key_prev_(false),
|
response_connection_close_(false), response_header_key_prev_(false),
|
||||||
expect_final_response_(false), request_pending_(false) {
|
response_trailer_key_prev_(false), expect_final_response_(false),
|
||||||
|
request_pending_(false) {
|
||||||
|
|
||||||
ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
|
ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
|
||||||
get_config()->stream_read_timeout);
|
get_config()->stream_read_timeout);
|
||||||
|
@ -679,6 +680,39 @@ unsigned int Downstream::get_response_http_status() const {
|
||||||
return response_http_status_;
|
return response_http_status_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Downstream::get_response_trailer_key_prev() const {
|
||||||
|
return response_trailer_key_prev_;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
void Downstream::set_response_http_status(unsigned int status) {
|
void Downstream::set_response_http_status(unsigned int status) {
|
||||||
response_http_status_ = status;
|
response_http_status_ = status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,6 +225,11 @@ public:
|
||||||
void add_response_trailer(const uint8_t *name, size_t namelen,
|
void add_response_trailer(const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen,
|
const uint8_t *value, size_t valuelen,
|
||||||
bool no_index, int16_t token);
|
bool no_index, int16_t token);
|
||||||
|
void add_response_trailer(std::string name, std::string value);
|
||||||
|
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;
|
unsigned int get_response_http_status() const;
|
||||||
void set_response_http_status(unsigned int status);
|
void set_response_http_status(unsigned int status);
|
||||||
|
@ -405,6 +410,7 @@ private:
|
||||||
bool chunked_response_;
|
bool chunked_response_;
|
||||||
bool response_connection_close_;
|
bool response_connection_close_;
|
||||||
bool response_header_key_prev_;
|
bool response_header_key_prev_;
|
||||||
|
bool response_trailer_key_prev_;
|
||||||
bool expect_final_response_;
|
bool expect_final_response_;
|
||||||
// true if downstream request is pending because backend connection
|
// true if downstream request is pending because backend connection
|
||||||
// has not been established or should be checked before use;
|
// has not been established or should be checked before use;
|
||||||
|
|
|
@ -555,14 +555,19 @@ int htp_hdrs_completecb(http_parser *htp) {
|
||||||
namespace {
|
namespace {
|
||||||
int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
|
int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
|
||||||
auto downstream = static_cast<Downstream *>(htp->data);
|
auto downstream = static_cast<Downstream *>(htp->data);
|
||||||
if (downstream->get_response_state() != Downstream::INITIAL) {
|
if (downstream->get_response_state() == Downstream::INITIAL) {
|
||||||
// ignore trailers
|
if (downstream->get_response_header_key_prev()) {
|
||||||
return 0;
|
downstream->append_last_response_header_key(data, len);
|
||||||
}
|
} else {
|
||||||
if (downstream->get_response_header_key_prev()) {
|
downstream->add_response_header(std::string(data, len), "");
|
||||||
downstream->append_last_response_header_key(data, len);
|
}
|
||||||
} else {
|
} else {
|
||||||
downstream->add_response_header(std::string(data, len), "");
|
// trailer part
|
||||||
|
if (downstream->get_response_trailer_key_prev()) {
|
||||||
|
downstream->append_last_response_trailer_key(data, len);
|
||||||
|
} else {
|
||||||
|
downstream->add_response_trailer(std::string(data, len), "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) {
|
if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
@ -578,14 +583,18 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
|
||||||
namespace {
|
namespace {
|
||||||
int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) {
|
int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) {
|
||||||
auto downstream = static_cast<Downstream *>(htp->data);
|
auto downstream = static_cast<Downstream *>(htp->data);
|
||||||
if (downstream->get_response_state() != Downstream::INITIAL) {
|
if (downstream->get_response_state() == Downstream::INITIAL) {
|
||||||
// ignore trailers
|
if (downstream->get_response_header_key_prev()) {
|
||||||
return 0;
|
downstream->set_last_response_header_value(std::string(data, len));
|
||||||
}
|
} else {
|
||||||
if (downstream->get_response_header_key_prev()) {
|
downstream->append_last_response_header_value(data, len);
|
||||||
downstream->set_last_response_header_value(std::string(data, len));
|
}
|
||||||
} else {
|
} else {
|
||||||
downstream->append_last_response_header_value(data, len);
|
if (downstream->get_response_trailer_key_prev()) {
|
||||||
|
downstream->set_last_response_trailer_value(std::string(data, len));
|
||||||
|
} else {
|
||||||
|
downstream->append_last_response_trailer_value(data, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) {
|
if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
|
Loading…
Reference in New Issue