nghttpx: Support trailer part in h2 -> h2 path
This commit is contained in:
parent
d10dc4bb9b
commit
41b5077330
|
@ -382,6 +382,20 @@ size_t Downstream::get_request_headers_sum() const {
|
||||||
return request_headers_sum_;
|
return request_headers_sum_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Downstream::add_request_trailer(const uint8_t *name, size_t namelen,
|
||||||
|
const uint8_t *value, size_t valuelen,
|
||||||
|
bool no_index, int16_t token) {
|
||||||
|
// we never index trailer part. Header size limit should be applied
|
||||||
|
// to all request header fields combined.
|
||||||
|
request_headers_sum_ += namelen + valuelen;
|
||||||
|
http2::add_header(request_trailers_, name, namelen, value, valuelen, no_index,
|
||||||
|
-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Headers &Downstream::get_request_trailers() const {
|
||||||
|
return request_trailers_;
|
||||||
|
}
|
||||||
|
|
||||||
void Downstream::set_request_method(std::string method) {
|
void Downstream::set_request_method(std::string method) {
|
||||||
request_method_ = std::move(method);
|
request_method_ = std::move(method);
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,11 @@ public:
|
||||||
|
|
||||||
size_t get_request_headers_sum() const;
|
size_t get_request_headers_sum() const;
|
||||||
|
|
||||||
|
const Headers &get_request_trailers() const;
|
||||||
|
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 set_request_method(std::string method);
|
void set_request_method(std::string method);
|
||||||
const std::string &get_request_method() const;
|
const std::string &get_request_method() const;
|
||||||
void set_request_path(std::string path);
|
void set_request_path(std::string path);
|
||||||
|
@ -308,6 +313,10 @@ private:
|
||||||
Headers request_headers_;
|
Headers request_headers_;
|
||||||
Headers response_headers_;
|
Headers response_headers_;
|
||||||
|
|
||||||
|
// trailer part. For HTTP/1.1, trailer part is only included with
|
||||||
|
// chunked encoding. For HTTP/2, there is no such limit.
|
||||||
|
Headers request_trailers_;
|
||||||
|
|
||||||
std::chrono::high_resolution_clock::time_point request_start_time_;
|
std::chrono::high_resolution_clock::time_point request_start_time_;
|
||||||
|
|
||||||
std::string request_method_;
|
std::string request_method_;
|
||||||
|
|
|
@ -159,6 +159,7 @@ ssize_t http2_data_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||||
uint8_t *buf, size_t length,
|
uint8_t *buf, size_t length,
|
||||||
uint32_t *data_flags,
|
uint32_t *data_flags,
|
||||||
nghttp2_data_source *source, void *user_data) {
|
nghttp2_data_source *source, void *user_data) {
|
||||||
|
int rv;
|
||||||
auto sd = static_cast<StreamData *>(
|
auto sd = static_cast<StreamData *>(
|
||||||
nghttp2_session_get_stream_user_data(session, stream_id));
|
nghttp2_session_get_stream_user_data(session, stream_id));
|
||||||
if (!sd || !sd->dconn) {
|
if (!sd || !sd->dconn) {
|
||||||
|
@ -201,6 +202,22 @@ ssize_t http2_data_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||||
!downstream->get_upgraded()))) {
|
!downstream->get_upgraded()))) {
|
||||||
|
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||||
|
|
||||||
|
if (!downstream->get_request_trailers().empty()) {
|
||||||
|
std::vector<nghttp2_nv> nva;
|
||||||
|
nva.reserve(downstream->get_request_trailers().size());
|
||||||
|
for (auto &kv : downstream->get_request_trailers()) {
|
||||||
|
nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index));
|
||||||
|
}
|
||||||
|
rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size());
|
||||||
|
if (rv != 0) {
|
||||||
|
if (nghttp2_is_fatal(rv)) {
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input_empty) {
|
if (!input_empty) {
|
||||||
|
@ -275,7 +292,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
cookies = downstream_->crumble_request_cookie();
|
cookies = downstream_->crumble_request_cookie();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8 means:
|
// 9 means:
|
||||||
// 1. :method
|
// 1. :method
|
||||||
// 2. :scheme
|
// 2. :scheme
|
||||||
// 3. :path
|
// 3. :path
|
||||||
|
@ -284,8 +301,9 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
// 6. via (optional)
|
// 6. via (optional)
|
||||||
// 7. x-forwarded-for (optional)
|
// 7. x-forwarded-for (optional)
|
||||||
// 8. x-forwarded-proto (optional)
|
// 8. x-forwarded-proto (optional)
|
||||||
|
// 9. te (optional)
|
||||||
auto nva = std::vector<nghttp2_nv>();
|
auto nva = std::vector<nghttp2_nv>();
|
||||||
nva.reserve(nheader + 8 + cookies.size());
|
nva.reserve(nheader + 9 + cookies.size());
|
||||||
|
|
||||||
std::string via_value;
|
std::string via_value;
|
||||||
std::string xff_value;
|
std::string xff_value;
|
||||||
|
@ -432,6 +450,11 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
nva.push_back(http2::make_nv_ls("via", via_value));
|
nva.push_back(http2::make_nv_ls("via", via_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto te = downstream_->get_request_header(http2::HD_TE);
|
||||||
|
if (te) {
|
||||||
|
nva.push_back(http2::make_nv_ls("te", te->value));
|
||||||
|
}
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
for (auto &nv : nva) {
|
for (auto &nv : nva) {
|
||||||
|
|
|
@ -187,8 +187,7 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
verbose_on_header_callback(session, frame, name, namelen, value, valuelen,
|
verbose_on_header_callback(session, frame, name, namelen, value, valuelen,
|
||||||
flags, user_data);
|
flags, user_data);
|
||||||
}
|
}
|
||||||
if (frame->hd.type != NGHTTP2_HEADERS ||
|
if (frame->hd.type != NGHTTP2_HEADERS) {
|
||||||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
auto upstream = static_cast<Http2Upstream *>(user_data);
|
auto upstream = static_cast<Http2Upstream *>(user_data);
|
||||||
|
@ -207,12 +206,25 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
<< downstream->get_request_headers_sum();
|
<< downstream->get_request_headers_sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// just ignore header fields if this is trailer part.
|
||||||
|
if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (upstream->error_reply(downstream, 431) != 0) {
|
if (upstream->error_reply(downstream, 431) != 0) {
|
||||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) {
|
||||||
|
// just store header fields for trailer part
|
||||||
|
downstream->add_request_trailer(name, namelen, value, valuelen,
|
||||||
|
flags & NGHTTP2_NV_FLAG_NO_INDEX, -1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
auto token = http2::lookup_token(name, namelen);
|
auto token = http2::lookup_token(name, namelen);
|
||||||
|
|
||||||
if (token == http2::HD_CONTENT_LENGTH) {
|
if (token == http2::HD_CONTENT_LENGTH) {
|
||||||
|
|
Loading…
Reference in New Issue