nghttpx: Create authority from host or authority-form for CONNECT request
This commit is contained in:
parent
64c754e2c5
commit
02bb2c3e83
|
@ -515,6 +515,10 @@ void Downstream::set_request_http2_authority(std::string authority) {
|
|||
request_http2_authority_ = std::move(authority);
|
||||
}
|
||||
|
||||
void Downstream::append_request_http2_authority(const char *data, size_t len) {
|
||||
request_http2_authority_.append(data, len);
|
||||
}
|
||||
|
||||
void Downstream::set_request_major(int major) { request_major_ = major; }
|
||||
|
||||
void Downstream::set_request_minor(int minor) { request_minor_ = minor; }
|
||||
|
|
|
@ -150,15 +150,19 @@ public:
|
|||
get_request_start_time() const;
|
||||
void append_request_path(const char *data, size_t len);
|
||||
// Returns request path. For HTTP/1.1, this is request-target. For
|
||||
// HTTP/2, this is :path header field value.
|
||||
// HTTP/2, this is :path header field value. For CONNECT request,
|
||||
// this is empty.
|
||||
const std::string &get_request_path() const;
|
||||
// Returns HTTP/2 :scheme header field value.
|
||||
const std::string &get_request_http2_scheme() const;
|
||||
void set_request_http2_scheme(std::string scheme);
|
||||
// Returns HTTP/2 :authority header field value. We also set the
|
||||
// value retrieved from absolute-form HTTP/1 request.
|
||||
// Returns :authority or host header field value. We may deduce it
|
||||
// from absolute-form HTTP/1 request. We also store authority-form
|
||||
// HTTP/1 request. This could be empty if request comes from
|
||||
// HTTP/1.0 without Host header field and origin-form.
|
||||
const std::string &get_request_http2_authority() const;
|
||||
void set_request_http2_authority(std::string authority);
|
||||
void append_request_http2_authority(const char *data, size_t len);
|
||||
void set_request_major(int major);
|
||||
void set_request_minor(int minor);
|
||||
int get_request_major() const;
|
||||
|
|
|
@ -265,37 +265,21 @@ int Http2DownstreamConnection::push_request_headers() {
|
|||
.addrs[addr_idx]
|
||||
.hostport.get();
|
||||
|
||||
const char *authority = nullptr, *host = nullptr;
|
||||
if (!no_host_rewrite) {
|
||||
if (!downstream_->get_request_http2_authority().empty()) {
|
||||
authority = downstream_hostport;
|
||||
}
|
||||
if (downstream_->get_request_header(http2::HD_HOST)) {
|
||||
host = downstream_hostport;
|
||||
}
|
||||
} else {
|
||||
if (!downstream_->get_request_http2_authority().empty()) {
|
||||
authority = downstream_->get_request_http2_authority().c_str();
|
||||
}
|
||||
auto h = downstream_->get_request_header(http2::HD_HOST);
|
||||
if (h) {
|
||||
host = h->value.c_str();
|
||||
}
|
||||
// For HTTP/1.0 request, there is no authority in request. In that
|
||||
// case, we use backend server's host nonetheless.
|
||||
const char *authority = downstream_hostport;
|
||||
auto &req_authority = downstream_->get_request_http2_authority();
|
||||
if (no_host_rewrite && !req_authority.empty()) {
|
||||
authority = req_authority.c_str();
|
||||
}
|
||||
|
||||
if (!authority && !host) {
|
||||
// upstream is HTTP/1.0. We use backend server's host
|
||||
// nonetheless.
|
||||
host = downstream_hostport;
|
||||
if (!authority) {
|
||||
authority = downstream_hostport;
|
||||
}
|
||||
|
||||
if (authority) {
|
||||
downstream_->set_request_downstream_host(authority);
|
||||
} else {
|
||||
downstream_->set_request_downstream_host(host);
|
||||
}
|
||||
downstream_->set_request_downstream_host(authority);
|
||||
|
||||
size_t nheader = downstream_->get_request_headers().size();
|
||||
auto nheader = downstream_->get_request_headers().size();
|
||||
|
||||
Headers cookies;
|
||||
if (!get_config()->http2_no_cookie_crumbling) {
|
||||
|
@ -306,7 +290,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
|||
// 1. :method
|
||||
// 2. :scheme
|
||||
// 3. :path
|
||||
// 4. :authority or host (at least either of them exists)
|
||||
// 4. :authority
|
||||
// 5. via (optional)
|
||||
// 6. x-forwarded-for (optional)
|
||||
// 7. x-forwarded-proto (optional)
|
||||
|
@ -320,30 +304,14 @@ int Http2DownstreamConnection::push_request_headers() {
|
|||
|
||||
auto &scheme = downstream_->get_request_http2_scheme();
|
||||
|
||||
if (downstream_->get_request_method() == HTTP_CONNECT) {
|
||||
if (authority) {
|
||||
nva.push_back(http2::make_nv_lc(":authority", authority));
|
||||
} else {
|
||||
nva.push_back(
|
||||
http2::make_nv_ls(":authority", downstream_->get_request_path()));
|
||||
}
|
||||
} else {
|
||||
nva.push_back(http2::make_nv_lc(":authority", authority));
|
||||
|
||||
if (downstream_->get_request_method() != HTTP_CONNECT) {
|
||||
assert(!scheme.empty());
|
||||
nva.push_back(http2::make_nv_ls(":scheme", scheme));
|
||||
|
||||
if (authority) {
|
||||
nva.push_back(http2::make_nv_lc(":authority", authority));
|
||||
}
|
||||
|
||||
nva.push_back(http2::make_nv_ls(":path", downstream_->get_request_path()));
|
||||
}
|
||||
|
||||
// only emit host header field if :authority is not emitted. They
|
||||
// both must be the same value.
|
||||
if (!authority && host) {
|
||||
nva.push_back(http2::make_nv_lc("host", host));
|
||||
}
|
||||
|
||||
http2::copy_headers_to_nva(nva, downstream_->get_request_headers());
|
||||
|
||||
bool chunked_encoding = false;
|
||||
|
|
|
@ -292,7 +292,12 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
|
|||
|
||||
downstream->set_request_method(method_token);
|
||||
downstream->set_request_http2_scheme(http2::value_to_str(scheme));
|
||||
// nghttp2 library guarantees either :authority or host exist
|
||||
if (!authority) {
|
||||
authority = downstream->get_request_header(http2::HD_HOST);
|
||||
}
|
||||
downstream->set_request_http2_authority(http2::value_to_str(authority));
|
||||
|
||||
if (path) {
|
||||
if (get_config()->http2_proxy || get_config()->client_proxy) {
|
||||
downstream->set_request_path(http2::value_to_str(path));
|
||||
|
|
|
@ -209,42 +209,25 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
|
|||
}
|
||||
|
||||
int HttpDownstreamConnection::push_request_headers() {
|
||||
const char *authority = nullptr, *host = nullptr;
|
||||
auto downstream_hostport = get_config()
|
||||
->downstream_addr_groups[group_]
|
||||
.addrs[addr_idx_]
|
||||
.hostport.get();
|
||||
auto connect_method = downstream_->get_request_method() == HTTP_CONNECT;
|
||||
|
||||
if (!get_config()->no_host_rewrite && !get_config()->http2_proxy &&
|
||||
!get_config()->client_proxy && !connect_method) {
|
||||
if (!downstream_->get_request_http2_authority().empty()) {
|
||||
authority = downstream_hostport;
|
||||
}
|
||||
if (downstream_->get_request_header(http2::HD_HOST)) {
|
||||
host = downstream_hostport;
|
||||
}
|
||||
} else {
|
||||
if (!downstream_->get_request_http2_authority().empty()) {
|
||||
authority = downstream_->get_request_http2_authority().c_str();
|
||||
}
|
||||
auto h = downstream_->get_request_header(http2::HD_HOST);
|
||||
if (h) {
|
||||
host = h->value.c_str();
|
||||
}
|
||||
// For HTTP/1.0 request, there is no authority in request. In that
|
||||
// case, we use backend server's host nonetheless.
|
||||
const char *authority = downstream_hostport;
|
||||
auto &req_authority = downstream_->get_request_http2_authority();
|
||||
auto no_host_rewrite = get_config()->no_host_rewrite ||
|
||||
get_config()->http2_proxy ||
|
||||
get_config()->client_proxy || connect_method;
|
||||
|
||||
if (no_host_rewrite && !req_authority.empty()) {
|
||||
authority = req_authority.c_str();
|
||||
}
|
||||
|
||||
if (!authority && !host) {
|
||||
// upstream is HTTP/1.0. We use backend server's host
|
||||
// nonetheless.
|
||||
host = downstream_hostport;
|
||||
}
|
||||
|
||||
if (authority) {
|
||||
downstream_->set_request_downstream_host(authority);
|
||||
} else {
|
||||
downstream_->set_request_downstream_host(host);
|
||||
}
|
||||
downstream_->set_request_downstream_host(authority);
|
||||
|
||||
downstream_->assemble_request_cookie();
|
||||
|
||||
|
@ -255,23 +238,14 @@ int HttpDownstreamConnection::push_request_headers() {
|
|||
auto &scheme = downstream_->get_request_http2_scheme();
|
||||
|
||||
if (connect_method) {
|
||||
if (authority) {
|
||||
hdrs += authority;
|
||||
} else {
|
||||
hdrs += downstream_->get_request_path();
|
||||
}
|
||||
hdrs += authority;
|
||||
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
||||
// Construct absolute-form request target because we are going to
|
||||
// send a request to a HTTP/1 proxy.
|
||||
assert(!scheme.empty());
|
||||
hdrs += scheme;
|
||||
hdrs += "://";
|
||||
|
||||
if (authority) {
|
||||
hdrs += authority;
|
||||
} else {
|
||||
hdrs += host;
|
||||
}
|
||||
hdrs += authority;
|
||||
|
||||
// Server-wide OPTIONS takes following form in proxy request:
|
||||
//
|
||||
|
@ -287,11 +261,7 @@ int HttpDownstreamConnection::push_request_headers() {
|
|||
hdrs += downstream_->get_request_path();
|
||||
}
|
||||
hdrs += " HTTP/1.1\r\nHost: ";
|
||||
if (authority) {
|
||||
hdrs += authority;
|
||||
} else {
|
||||
hdrs += host;
|
||||
}
|
||||
hdrs += authority;
|
||||
hdrs += "\r\n";
|
||||
|
||||
http2::build_http1_headers_from_headers(hdrs,
|
||||
|
|
|
@ -70,8 +70,14 @@ int htp_msg_begin(http_parser *htp) {
|
|||
auto handler = upstream->get_client_handler();
|
||||
|
||||
// TODO specify 0 as priority for now
|
||||
upstream->attach_downstream(
|
||||
make_unique<Downstream>(upstream, handler->get_mcpool(), 0, 0));
|
||||
auto downstream =
|
||||
make_unique<Downstream>(upstream, handler->get_mcpool(), 0, 0);
|
||||
|
||||
// We happen to have the same value for method token.
|
||||
downstream->set_request_method(htp->method);
|
||||
|
||||
upstream->attach_downstream(std::move(downstream));
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -91,7 +97,12 @@ int htp_uricb(http_parser *htp, const char *data, size_t len) {
|
|||
return -1;
|
||||
}
|
||||
downstream->add_request_headers_sum(len);
|
||||
downstream->append_request_path(data, len);
|
||||
if (downstream->get_request_method() == HTTP_CONNECT) {
|
||||
downstream->append_request_http2_authority(data, len);
|
||||
} else {
|
||||
downstream->append_request_path(data, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -242,8 +253,6 @@ int htp_hdrs_completecb(http_parser *htp) {
|
|||
}
|
||||
auto downstream = upstream->get_downstream();
|
||||
|
||||
// We happen to have the same value for method token.
|
||||
downstream->set_request_method(htp->method);
|
||||
downstream->set_request_major(htp->http_major);
|
||||
downstream->set_request_minor(htp->http_minor);
|
||||
|
||||
|
@ -296,6 +305,11 @@ int htp_hdrs_completecb(http_parser *htp) {
|
|||
downstream->set_request_path(
|
||||
http2::rewrite_clean_path(std::begin(uri), std::end(uri)));
|
||||
|
||||
auto host = downstream->get_request_header(http2::HD_HOST);
|
||||
if (host) {
|
||||
downstream->set_request_http2_authority(host->value);
|
||||
}
|
||||
|
||||
if (upstream->get_client_handler()->get_ssl()) {
|
||||
downstream->set_request_http2_scheme("https");
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue