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