nghttpx: Support response trailer part handling in h1 backend

This commit is contained in:
Tatsuhiro Tsujikawa 2015-03-08 17:19:52 +09:00
parent 60c2fe5a2e
commit 6ad63a06b0
3 changed files with 64 additions and 15 deletions

View File

@ -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_http2_expect_body_(false), chunked_response_(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.,
get_config()->stream_read_timeout);
@ -679,6 +680,39 @@ unsigned int Downstream::get_response_http_status() const {
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) {
response_http_status_ = status;
}

View File

@ -225,6 +225,11 @@ public:
void add_response_trailer(const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
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;
void set_response_http_status(unsigned int status);
@ -405,6 +410,7 @@ private:
bool chunked_response_;
bool response_connection_close_;
bool response_header_key_prev_;
bool response_trailer_key_prev_;
bool expect_final_response_;
// true if downstream request is pending because backend connection
// has not been established or should be checked before use;

View File

@ -555,14 +555,19 @@ int htp_hdrs_completecb(http_parser *htp) {
namespace {
int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
auto downstream = static_cast<Downstream *>(htp->data);
if (downstream->get_response_state() != Downstream::INITIAL) {
// ignore trailers
return 0;
}
if (downstream->get_response_header_key_prev()) {
downstream->append_last_response_header_key(data, len);
if (downstream->get_response_state() == Downstream::INITIAL) {
if (downstream->get_response_header_key_prev()) {
downstream->append_last_response_header_key(data, len);
} else {
downstream->add_response_header(std::string(data, len), "");
}
} 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 (LOG_ENABLED(INFO)) {
@ -578,14 +583,18 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
namespace {
int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) {
auto downstream = static_cast<Downstream *>(htp->data);
if (downstream->get_response_state() != Downstream::INITIAL) {
// ignore trailers
return 0;
}
if (downstream->get_response_header_key_prev()) {
downstream->set_last_response_header_value(std::string(data, len));
if (downstream->get_response_state() == Downstream::INITIAL) {
if (downstream->get_response_header_key_prev()) {
downstream->set_last_response_header_value(std::string(data, len));
} else {
downstream->append_last_response_header_value(data, len);
}
} 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 (LOG_ENABLED(INFO)) {