nghttpx: Store empty string to path for server-wide OPTIONS request
This change is required to show path attribute to mruby script. It is desirable to construct URI from parts. Just checking method and path is "*" is awkward.
This commit is contained in:
parent
02bb2c3e83
commit
200217d8ea
|
@ -739,41 +739,23 @@ namespace {
|
||||||
// HttpDownstreamConnection::push_request_headers(), but vastly
|
// HttpDownstreamConnection::push_request_headers(), but vastly
|
||||||
// simplified since we only care about absolute URI.
|
// simplified since we only care about absolute URI.
|
||||||
std::string construct_absolute_request_uri(Downstream *downstream) {
|
std::string construct_absolute_request_uri(Downstream *downstream) {
|
||||||
const char *authority = nullptr, *host = nullptr;
|
auto &authority = downstream->get_request_http2_authority();
|
||||||
if (!downstream->get_request_http2_authority().empty()) {
|
if (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) {
|
|
||||||
return downstream->get_request_path();
|
return downstream->get_request_path();
|
||||||
}
|
}
|
||||||
std::string uri;
|
std::string uri;
|
||||||
if (downstream->get_request_http2_scheme().empty()) {
|
auto &scheme = downstream->get_request_http2_scheme();
|
||||||
|
if (scheme.empty()) {
|
||||||
// We may have to log the request which lacks scheme (e.g.,
|
// We may have to log the request which lacks scheme (e.g.,
|
||||||
// http/1.1 with origin form).
|
// http/1.1 with origin form).
|
||||||
uri += "http://";
|
uri += "http://";
|
||||||
} else {
|
} else {
|
||||||
uri += downstream->get_request_http2_scheme();
|
uri += scheme;
|
||||||
uri += "://";
|
uri += "://";
|
||||||
}
|
}
|
||||||
if (authority) {
|
|
||||||
uri += authority;
|
uri += authority;
|
||||||
} else {
|
|
||||||
uri += host;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server-wide OPTIONS takes following form in proxy request:
|
|
||||||
//
|
|
||||||
// OPTIONS http://example.org HTTP/1.1
|
|
||||||
//
|
|
||||||
// Notice that no slash after authority. See
|
|
||||||
// http://tools.ietf.org/html/rfc7230#section-5.3.4
|
|
||||||
if (downstream->get_request_path() != "*") {
|
|
||||||
uri += downstream->get_request_path();
|
uri += downstream->get_request_path();
|
||||||
}
|
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -787,11 +769,14 @@ void ClientHandler::write_accesslog(Downstream *downstream) {
|
||||||
downstream, ipaddr_.c_str(),
|
downstream, ipaddr_.c_str(),
|
||||||
http2::to_method_string(downstream->get_request_method()),
|
http2::to_method_string(downstream->get_request_method()),
|
||||||
|
|
||||||
(downstream->get_request_method() != HTTP_CONNECT &&
|
downstream->get_request_method() == HTTP_CONNECT
|
||||||
(get_config()->http2_proxy || get_config()->client_proxy))
|
? downstream->get_request_http2_authority().c_str()
|
||||||
|
: (get_config()->http2_proxy || get_config()->client_proxy)
|
||||||
? construct_absolute_request_uri(downstream).c_str()
|
? construct_absolute_request_uri(downstream).c_str()
|
||||||
: downstream->get_request_path().empty()
|
: downstream->get_request_path().empty()
|
||||||
? downstream->get_request_http2_authority().c_str()
|
? downstream->get_request_method() == HTTP_OPTIONS
|
||||||
|
? "*"
|
||||||
|
: "-"
|
||||||
: downstream->get_request_path().c_str(),
|
: downstream->get_request_path().c_str(),
|
||||||
|
|
||||||
alpn_.c_str(),
|
alpn_.c_str(),
|
||||||
|
|
|
@ -251,10 +251,10 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
|
|
||||||
downstream_->set_request_pending(false);
|
downstream_->set_request_pending(false);
|
||||||
|
|
||||||
|
auto method = downstream_->get_request_method();
|
||||||
auto no_host_rewrite = get_config()->no_host_rewrite ||
|
auto no_host_rewrite = get_config()->no_host_rewrite ||
|
||||||
get_config()->http2_proxy ||
|
get_config()->http2_proxy ||
|
||||||
get_config()->client_proxy ||
|
get_config()->client_proxy || method == HTTP_CONNECT;
|
||||||
downstream_->get_request_method() == HTTP_CONNECT;
|
|
||||||
|
|
||||||
// http2session_ has already in CONNECTED state, so we can get
|
// http2session_ has already in CONNECTED state, so we can get
|
||||||
// addr_idx here.
|
// addr_idx here.
|
||||||
|
@ -299,17 +299,23 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
nva.reserve(nheader + 8 + cookies.size() +
|
nva.reserve(nheader + 8 + cookies.size() +
|
||||||
get_config()->add_request_headers.size());
|
get_config()->add_request_headers.size());
|
||||||
|
|
||||||
nva.push_back(http2::make_nv_lc(
|
nva.push_back(http2::make_nv_lc(":method", http2::to_method_string(method)));
|
||||||
":method", http2::to_method_string(downstream_->get_request_method())));
|
|
||||||
|
|
||||||
auto &scheme = downstream_->get_request_http2_scheme();
|
auto &scheme = downstream_->get_request_http2_scheme();
|
||||||
|
|
||||||
nva.push_back(http2::make_nv_lc(":authority", authority));
|
nva.push_back(http2::make_nv_lc(":authority", authority));
|
||||||
|
|
||||||
if (downstream_->get_request_method() != HTTP_CONNECT) {
|
if (method != HTTP_CONNECT) {
|
||||||
assert(!scheme.empty());
|
assert(!scheme.empty());
|
||||||
|
|
||||||
nva.push_back(http2::make_nv_ls(":scheme", scheme));
|
nva.push_back(http2::make_nv_ls(":scheme", scheme));
|
||||||
nva.push_back(http2::make_nv_ls(":path", downstream_->get_request_path()));
|
|
||||||
|
auto &path = downstream_->get_request_path();
|
||||||
|
if (method == HTTP_OPTIONS && path.empty()) {
|
||||||
|
nva.push_back(http2::make_nv_ll(":path", "*"));
|
||||||
|
} else {
|
||||||
|
nva.push_back(http2::make_nv_ls(":path", path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
http2::copy_headers_to_nva(nva, downstream_->get_request_headers());
|
http2::copy_headers_to_nva(nva, downstream_->get_request_headers());
|
||||||
|
|
|
@ -299,7 +299,9 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
|
||||||
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 (method_token == HTTP_OPTIONS && path->value == "*") {
|
||||||
|
// Server-wide OPTIONS request. Path is empty.
|
||||||
|
} else 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));
|
||||||
} else {
|
} else {
|
||||||
auto &value = path->value;
|
auto &value = path->value;
|
||||||
|
|
|
@ -213,7 +213,8 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
->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 method = downstream_->get_request_method();
|
||||||
|
auto connect_method = method == HTTP_CONNECT;
|
||||||
|
|
||||||
// For HTTP/1.0 request, there is no authority in request. In that
|
// For HTTP/1.0 request, there is no authority in request. In that
|
||||||
// case, we use backend server's host nonetheless.
|
// case, we use backend server's host nonetheless.
|
||||||
|
@ -232,10 +233,11 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
downstream_->assemble_request_cookie();
|
downstream_->assemble_request_cookie();
|
||||||
|
|
||||||
// Assume that method and request path do not contain \r\n.
|
// Assume that method and request path do not contain \r\n.
|
||||||
std::string hdrs = http2::to_method_string(downstream_->get_request_method());
|
std::string hdrs = http2::to_method_string(method);
|
||||||
hdrs += ' ';
|
hdrs += ' ';
|
||||||
|
|
||||||
auto &scheme = downstream_->get_request_http2_scheme();
|
auto &scheme = downstream_->get_request_http2_scheme();
|
||||||
|
auto &path = downstream_->get_request_path();
|
||||||
|
|
||||||
if (connect_method) {
|
if (connect_method) {
|
||||||
hdrs += authority;
|
hdrs += authority;
|
||||||
|
@ -246,19 +248,12 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
hdrs += scheme;
|
hdrs += scheme;
|
||||||
hdrs += "://";
|
hdrs += "://";
|
||||||
hdrs += authority;
|
hdrs += authority;
|
||||||
|
hdrs += path;
|
||||||
// Server-wide OPTIONS takes following form in proxy request:
|
} else if (method == HTTP_OPTIONS && path.empty()) {
|
||||||
//
|
// Server-wide OPTIONS
|
||||||
// OPTIONS http://example.org HTTP/1.1
|
hdrs += "*";
|
||||||
//
|
|
||||||
// Notice that no slash after authority. See
|
|
||||||
// http://tools.ietf.org/html/rfc7230#section-5.3.4
|
|
||||||
if (downstream_->get_request_path() != "*") {
|
|
||||||
hdrs += downstream_->get_request_path();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// No proxy case.
|
hdrs += path;
|
||||||
hdrs += downstream_->get_request_path();
|
|
||||||
}
|
}
|
||||||
hdrs += " HTTP/1.1\r\nHost: ";
|
hdrs += " HTTP/1.1\r\nHost: ";
|
||||||
hdrs += authority;
|
hdrs += authority;
|
||||||
|
|
|
@ -224,7 +224,7 @@ void rewrite_request_host_path_from_uri(Downstream *downstream, const char *uri,
|
||||||
//
|
//
|
||||||
// Notice that no slash after authority. See
|
// Notice that no slash after authority. See
|
||||||
// http://tools.ietf.org/html/rfc7230#section-5.3.4
|
// http://tools.ietf.org/html/rfc7230#section-5.3.4
|
||||||
downstream->set_request_path("*");
|
downstream->set_request_path("");
|
||||||
// we ignore query component here
|
// we ignore query component here
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -258,10 +258,13 @@ int htp_hdrs_completecb(http_parser *htp) {
|
||||||
|
|
||||||
downstream->set_request_connection_close(!http_should_keep_alive(htp));
|
downstream->set_request_connection_close(!http_should_keep_alive(htp));
|
||||||
|
|
||||||
|
auto method = downstream->get_request_method();
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << http2::to_method_string(downstream->get_request_method()) << " "
|
ss << http2::to_method_string(method) << " "
|
||||||
<< downstream->get_request_path() << " "
|
<< (method == HTTP_CONNECT ? downstream->get_request_http2_authority()
|
||||||
|
: downstream->get_request_path()) << " "
|
||||||
<< "HTTP/" << downstream->get_request_major() << "."
|
<< "HTTP/" << downstream->get_request_major() << "."
|
||||||
<< downstream->get_request_minor() << "\n";
|
<< downstream->get_request_minor() << "\n";
|
||||||
const auto &headers = downstream->get_request_headers();
|
const auto &headers = downstream->get_request_headers();
|
||||||
|
@ -284,13 +287,12 @@ int htp_hdrs_completecb(http_parser *htp) {
|
||||||
|
|
||||||
downstream->inspect_http1_request();
|
downstream->inspect_http1_request();
|
||||||
|
|
||||||
if (downstream->get_request_method() != HTTP_CONNECT) {
|
if (method != HTTP_CONNECT) {
|
||||||
http_parser_url u{};
|
http_parser_url u{};
|
||||||
// make a copy of request path, since we may set request path
|
// make a copy of request path, since we may set request path
|
||||||
// while we are refering to original request path.
|
// while we are refering to original request path.
|
||||||
auto uri = downstream->get_request_path();
|
auto path = downstream->get_request_path();
|
||||||
rv = http_parser_parse_url(uri.c_str(),
|
rv = http_parser_parse_url(path.c_str(), path.size(), 0, &u);
|
||||||
downstream->get_request_path().size(), 0, &u);
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
// Expect to respond with 400 bad request
|
// Expect to respond with 400 bad request
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -302,8 +304,12 @@ int htp_hdrs_completecb(http_parser *htp) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method == HTTP_OPTIONS && path == "*") {
|
||||||
|
downstream->set_request_path("");
|
||||||
|
} else {
|
||||||
downstream->set_request_path(
|
downstream->set_request_path(
|
||||||
http2::rewrite_clean_path(std::begin(uri), std::end(uri)));
|
http2::rewrite_clean_path(std::begin(path), std::end(path)));
|
||||||
|
}
|
||||||
|
|
||||||
auto host = downstream->get_request_header(http2::HD_HOST);
|
auto host = downstream->get_request_header(http2::HD_HOST);
|
||||||
if (host) {
|
if (host) {
|
||||||
|
@ -316,7 +322,7 @@ int htp_hdrs_completecb(http_parser *htp) {
|
||||||
downstream->set_request_http2_scheme("http");
|
downstream->set_request_http2_scheme("http");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rewrite_request_host_path_from_uri(downstream, uri.c_str(), u);
|
rewrite_request_host_path_from_uri(downstream, path.c_str(), u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,6 +337,8 @@ int htp_hdrs_completecb(http_parser *htp) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mruby hook may change method value
|
||||||
|
|
||||||
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,6 +227,8 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
|
||||||
downstream->set_request_http2_authority(host->value);
|
downstream->set_request_http2_authority(host->value);
|
||||||
if (get_config()->http2_proxy || get_config()->client_proxy) {
|
if (get_config()->http2_proxy || get_config()->client_proxy) {
|
||||||
downstream->set_request_path(path->value);
|
downstream->set_request_path(path->value);
|
||||||
|
} else if (method_token == HTTP_OPTIONS && path->value == "*") {
|
||||||
|
// Server-wide OPTIONS request. Path is empty.
|
||||||
} else {
|
} else {
|
||||||
downstream->set_request_path(http2::rewrite_clean_path(
|
downstream->set_request_path(http2::rewrite_clean_path(
|
||||||
std::begin(path->value), std::end(path->value)));
|
std::begin(path->value), std::end(path->value)));
|
||||||
|
|
Loading…
Reference in New Issue