nghttpx: Don't emit :authority if request dones not contain authority info

RFC 7540 says that proxy should not emit :authority when translating
HTTP/1 request in origin or asterisk form to HTTP/2.  To keep this
semantics in tact, we should also refrain from emitting :authority if
it is missing (host header field is required in this case).
This commit is contained in:
Tatsuhiro Tsujikawa 2016-01-16 21:12:51 +09:00
parent 7be0217bc0
commit f25fd09bbb
4 changed files with 17 additions and 4 deletions

View File

@ -127,7 +127,7 @@ struct Request {
: fs(16), recv_body_length(0), unconsumed_body_length(0), method(-1),
http_major(1), http_minor(1), upgrade_request(false),
http2_upgrade_seen(false), connection_close(false),
http2_expect_body(false) {}
http2_expect_body(false), no_authority(false) {}
void consume(size_t len) {
assert(unconsumed_body_length >= len);
@ -165,6 +165,10 @@ struct Request {
// true if this is HTTP/2, and request body is expected. Note that
// we don't take into account HTTP method here.
bool http2_expect_body;
// true if request does not have any information about authority.
// This happens when: For HTTP/2 request, :authority is missing.
// For HTTP/1 request, origin or asterisk form is used.
bool no_authority;
};
struct Response {

View File

@ -287,7 +287,7 @@ int Http2DownstreamConnection::push_request_headers() {
// 1. :method
// 2. :scheme
// 3. :path
// 4. :authority
// 4. :authority (or host)
// 5. via (optional)
// 6. x-forwarded-for (optional)
// 7. x-forwarded-proto (optional)
@ -300,8 +300,6 @@ int Http2DownstreamConnection::push_request_headers() {
nva.push_back(
http2::make_nv_lc_nocopy(":method", http2::to_method_string(req.method)));
nva.push_back(http2::make_nv_lc_nocopy(":authority", authority));
if (req.method != HTTP_CONNECT) {
assert(!req.scheme.empty());
@ -312,6 +310,14 @@ int Http2DownstreamConnection::push_request_headers() {
} else {
nva.push_back(http2::make_nv_ls_nocopy(":path", req.path));
}
if (!req.no_authority) {
nva.push_back(http2::make_nv_lc_nocopy(":authority", authority));
} else {
nva.push_back(http2::make_nv_lc_nocopy("host", authority));
}
} else {
nva.push_back(http2::make_nv_lc_nocopy(":authority", authority));
}
http2::copy_headers_to_nva_nocopy(nva, req.fs.headers());

View File

@ -298,6 +298,7 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
// nghttp2 library guarantees either :authority or host exist
if (!authority) {
req.no_authority = true;
authority = req.fs.header(http2::HD_HOST);
}

View File

@ -308,6 +308,8 @@ int htp_hdrs_completecb(http_parser *htp) {
return -1;
}
req.no_authority = true;
if (method == HTTP_OPTIONS && path == "*") {
req.path = "";
} else {