nghttpx: Structured configurations for http and http2

This commit is contained in:
Tatsuhiro Tsujikawa 2016-01-18 17:00:20 +09:00
parent f3e1dc7a4f
commit 16549bb276
12 changed files with 346 additions and 273 deletions

View File

@ -900,7 +900,6 @@ void fill_default_config() {
mod_config()->verbose = false; mod_config()->verbose = false;
mod_config()->daemon = false; mod_config()->daemon = false;
mod_config()->server_name = "nghttpx nghttp2/" NGHTTP2_VERSION;
mod_config()->host = strcopy("*"); mod_config()->host = strcopy("*");
mod_config()->port = 3000; mod_config()->port = 3000;
@ -926,25 +925,10 @@ void fill_default_config() {
// Timeout for pooled (idle) connections // Timeout for pooled (idle) connections
mod_config()->downstream_idle_read_timeout = 2.; mod_config()->downstream_idle_read_timeout = 2.;
// window bits for HTTP/2 and SPDY upstream/downstream connection
// per stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please
// note that SPDY/3 default is 64KiB.
mod_config()->http2_upstream_window_bits = 16;
mod_config()->http2_downstream_window_bits = 16;
// HTTP/2 SPDY/3.1 has connection-level flow control. The default
// window size for HTTP/2 is 64KiB - 1. SPDY/3's default is 64KiB
mod_config()->http2_upstream_connection_window_bits = 16;
mod_config()->http2_downstream_connection_window_bits = 16;
mod_config()->upstream_no_tls = false; mod_config()->upstream_no_tls = false;
mod_config()->downstream_no_tls = false; mod_config()->downstream_no_tls = false;
mod_config()->num_worker = 1; mod_config()->num_worker = 1;
mod_config()->http2_max_concurrent_streams = 100;
mod_config()->add_x_forwarded_for = false;
mod_config()->strip_incoming_x_forwarded_for = false;
mod_config()->no_via = false;
mod_config()->accesslog_file = nullptr; mod_config()->accesslog_file = nullptr;
mod_config()->accesslog_syslog = false; mod_config()->accesslog_syslog = false;
mod_config()->accesslog_format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT); mod_config()->accesslog_format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT);
@ -966,7 +950,6 @@ void fill_default_config() {
mod_config()->pid = getpid(); mod_config()->pid = getpid();
mod_config()->backend_ipv4 = false; mod_config()->backend_ipv4 = false;
mod_config()->backend_ipv6 = false; mod_config()->backend_ipv6 = false;
mod_config()->downstream_http_proxy_port = 0;
mod_config()->read_rate = 0; mod_config()->read_rate = 0;
mod_config()->read_burst = 0; mod_config()->read_burst = 0;
mod_config()->write_rate = 0; mod_config()->write_rate = 0;
@ -975,25 +958,9 @@ void fill_default_config() {
mod_config()->worker_read_burst = 0; mod_config()->worker_read_burst = 0;
mod_config()->worker_write_rate = 0; mod_config()->worker_write_rate = 0;
mod_config()->worker_write_burst = 0; mod_config()->worker_write_burst = 0;
mod_config()->http2_upstream_dump_request_header = nullptr;
mod_config()->http2_upstream_dump_response_header = nullptr;
mod_config()->http2_no_cookie_crumbling = false;
mod_config()->upstream_frame_debug = false;
mod_config()->padding = 0; mod_config()->padding = 0;
mod_config()->worker_frontend_connections = 0; mod_config()->worker_frontend_connections = 0;
nghttp2_option_new(&mod_config()->http2_option);
nghttp2_option_set_no_auto_window_update(get_config()->http2_option, 1);
nghttp2_option_set_no_recv_client_magic(get_config()->http2_option, 1);
nghttp2_option_new(&mod_config()->http2_client_option);
nghttp2_option_set_no_auto_window_update(get_config()->http2_client_option,
1);
nghttp2_option_set_peer_max_concurrent_streams(
get_config()->http2_client_option, 100);
mod_config()->no_location_rewrite = false;
mod_config()->no_host_rewrite = true;
mod_config()->argc = 0; mod_config()->argc = 0;
mod_config()->argv = nullptr; mod_config()->argv = nullptr;
mod_config()->downstream_connections_per_host = 8; mod_config()->downstream_connections_per_host = 8;
@ -1001,11 +968,7 @@ void fill_default_config() {
mod_config()->listener_disable_timeout = 0.; mod_config()->listener_disable_timeout = 0.;
mod_config()->downstream_request_buffer_size = 16_k; mod_config()->downstream_request_buffer_size = 16_k;
mod_config()->downstream_response_buffer_size = 16_k; mod_config()->downstream_response_buffer_size = 16_k;
mod_config()->no_server_push = false;
mod_config()->host_unix = false; mod_config()->host_unix = false;
mod_config()->http2_downstream_connections_per_worker = 0;
mod_config()->header_field_buffer = 64_k;
mod_config()->max_header_fields = 100;
mod_config()->downstream_addr_group_catch_all = 0; mod_config()->downstream_addr_group_catch_all = 0;
mod_config()->fastopen = 0; mod_config()->fastopen = 0;
@ -1040,12 +1003,57 @@ void fill_default_config() {
tlsconf.tls_proto_mask = 0; tlsconf.tls_proto_mask = 0;
tlsconf.insecure = false; tlsconf.insecure = false;
} }
auto &httpconf = mod_config()->http;
{
auto &xffconf = httpconf.xff;
xffconf.add = false;
xffconf.strip_incoming = false;
}
httpconf.server_name = "nghttpx nghttp2/" NGHTTP2_VERSION;
httpconf.no_via = false;
httpconf.no_location_rewrite = false;
httpconf.no_host_rewrite = true;
httpconf.header_field_buffer = 64_k;
httpconf.max_header_fields = 100;
auto &http2conf = mod_config()->http2;
{
auto &upstreamconf = http2conf.upstream;
// window bits for HTTP/2 and SPDY upstream connection per
// stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please note
// that SPDY/3 default is 64KiB.
upstreamconf.window_bits = 16;
// HTTP/2 SPDY/3.1 has connection-level flow control. The default
// window size for HTTP/2 is 64KiB - 1. SPDY/3's default is 64KiB
upstreamconf.connection_window_bits = 16;
nghttp2_option_new(&upstreamconf.option);
nghttp2_option_set_no_auto_window_update(upstreamconf.option, 1);
nghttp2_option_set_no_recv_client_magic(upstreamconf.option, 1);
}
{
auto &downstreamconf = http2conf.downstream;
downstreamconf.window_bits = 16;
downstreamconf.connection_window_bits = 16;
downstreamconf.connections_per_worker = 0;
nghttp2_option_new(&downstreamconf.option);
nghttp2_option_set_no_auto_window_update(downstreamconf.option, 1);
nghttp2_option_set_peer_max_concurrent_streams(downstreamconf.option, 100);
}
http2conf.max_concurrent_streams = 100;
http2conf.no_cookie_crumbling = false;
http2conf.no_server_push = false;
} }
} // namespace } // namespace
namespace { namespace {
void print_version(std::ostream &out) { void print_version(std::ostream &out) {
out << get_config()->server_name.c_str() << std::endl; out << get_config()->http.server_name.c_str() << std::endl;
} }
} // namespace } // namespace
@ -1450,29 +1458,29 @@ HTTP/2 and SPDY:
-c, --http2-max-concurrent-streams=<N> -c, --http2-max-concurrent-streams=<N>
Set the maximum number of the concurrent streams in one Set the maximum number of the concurrent streams in one
HTTP/2 and SPDY session. HTTP/2 and SPDY session.
Default: )" << get_config()->http2_max_concurrent_streams << R"( Default: )" << get_config()->http2.max_concurrent_streams << R"(
--frontend-http2-window-bits=<N> --frontend-http2-window-bits=<N>
Sets the per-stream initial window size of HTTP/2 SPDY Sets the per-stream initial window size of HTTP/2 SPDY
frontend connection. For HTTP/2, the size is 2**<N>-1. frontend connection. For HTTP/2, the size is 2**<N>-1.
For SPDY, the size is 2**<N>. For SPDY, the size is 2**<N>.
Default: )" << get_config()->http2_upstream_window_bits << R"( Default: )" << get_config()->http2.upstream.window_bits << R"(
--frontend-http2-connection-window-bits=<N> --frontend-http2-connection-window-bits=<N>
Sets the per-connection window size of HTTP/2 and SPDY Sets the per-connection window size of HTTP/2 and SPDY
frontend connection. For HTTP/2, the size is frontend connection. For HTTP/2, the size is
2**<N>-1. For SPDY, the size is 2**<N>. 2**<N>-1. For SPDY, the size is 2**<N>.
Default: )" << get_config()->http2_upstream_connection_window_bits Default: )" << get_config()->http2.upstream.connection_window_bits
<< R"( << R"(
--frontend-no-tls --frontend-no-tls
Disable SSL/TLS on frontend connections. Disable SSL/TLS on frontend connections.
--backend-http2-window-bits=<N> --backend-http2-window-bits=<N>
Sets the initial window size of HTTP/2 backend Sets the initial window size of HTTP/2 backend
connection to 2**<N>-1. connection to 2**<N>-1.
Default: )" << get_config()->http2_downstream_window_bits << R"( Default: )" << get_config()->http2.downstream.window_bits << R"(
--backend-http2-connection-window-bits=<N> --backend-http2-connection-window-bits=<N>
Sets the per-connection window size of HTTP/2 backend Sets the per-connection window size of HTTP/2 backend
connection to 2**<N>-1. connection to 2**<N>-1.
Default: )" Default: )"
<< get_config()->http2_downstream_connection_window_bits << R"( << get_config()->http2.downstream.connection_window_bits << R"(
--backend-no-tls --backend-no-tls
Disable SSL/TLS on backend connections. Disable SSL/TLS on backend connections.
--http2-no-cookie-crumbling --http2-no-cookie-crumbling
@ -1650,13 +1658,13 @@ HTTP:
Set maximum buffer size for incoming HTTP request header Set maximum buffer size for incoming HTTP request header
field list. This is the sum of header name and value in field list. This is the sum of header name and value in
bytes. bytes.
Default: )" << util::utos_unit(get_config()->header_field_buffer) Default: )"
<< R"( << util::utos_unit(get_config()->http.header_field_buffer) << R"(
--max-header-fields=<N> --max-header-fields=<N>
Set maximum number of incoming HTTP request header Set maximum number of incoming HTTP request header
fields, which appear in one request or response header fields, which appear in one request or response header
field list. field list.
Default: )" << get_config()->max_header_fields << R"( Default: )" << get_config()->http.max_header_fields << R"(
Debug: Debug:
--frontend-http2-dump-request-header=<PATH> --frontend-http2-dump-request-header=<PATH>
@ -2374,8 +2382,12 @@ int main(int argc, char **argv) {
} }
} }
if (get_config()->http2_upstream_dump_request_header_file) { auto &http2conf = mod_config()->http2;
auto path = get_config()->http2_upstream_dump_request_header_file.get(); {
auto &dumpconf = http2conf.upstream.debug.dump;
if (dumpconf.request_header_file) {
auto path = dumpconf.request_header_file.get();
auto f = open_file_for_write(path); auto f = open_file_for_write(path);
if (f == nullptr) { if (f == nullptr) {
@ -2384,7 +2396,7 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
mod_config()->http2_upstream_dump_request_header = f; dumpconf.request_header = f;
if (get_config()->uid != 0) { if (get_config()->uid != 0) {
if (chown_to_running_user(path) == -1) { if (chown_to_running_user(path) == -1) {
@ -2395,8 +2407,8 @@ int main(int argc, char **argv) {
} }
} }
if (get_config()->http2_upstream_dump_response_header_file) { if (dumpconf.response_header_file) {
auto path = get_config()->http2_upstream_dump_response_header_file.get(); auto path = dumpconf.response_header_file.get();
auto f = open_file_for_write(path); auto f = open_file_for_write(path);
if (f == nullptr) { if (f == nullptr) {
@ -2405,7 +2417,7 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
mod_config()->http2_upstream_dump_response_header = f; dumpconf.response_header = f;
if (get_config()->uid != 0) { if (get_config()->uid != 0) {
if (chown_to_running_user(path) == -1) { if (chown_to_running_user(path) == -1) {
@ -2415,6 +2427,7 @@ int main(int argc, char **argv) {
} }
} }
} }
}
auto &tlsconf = mod_config()->tls; auto &tlsconf = mod_config()->tls;
@ -2617,16 +2630,18 @@ int main(int argc, char **argv) {
} }
} }
if (get_config()->forwarded_by_node_type == FORWARDED_NODE_OBFUSCATED && auto &fwdconf = mod_config()->http.forwarded;
get_config()->forwarded_by_obfuscated.empty()) {
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED &&
fwdconf.by_obfuscated.empty()) {
std::random_device rd; std::random_device rd;
std::mt19937 gen(rd()); std::mt19937 gen(rd());
auto &dst = mod_config()->forwarded_by_obfuscated; auto &dst = fwdconf.by_obfuscated;
dst = "_"; dst = "_";
dst += util::random_alpha_digit(gen, SHRPX_OBFUSCATED_NODE_LENGTH); dst += util::random_alpha_digit(gen, SHRPX_OBFUSCATED_NODE_LENGTH);
} }
if (get_config()->upstream_frame_debug) { if (get_config()->http2.upstream.debug.frame_debug) {
// To make it sync to logging // To make it sync to logging
set_output(stderr); set_output(stderr);
if (isatty(fileno(stdout))) { if (isatty(fileno(stdout))) {
@ -2635,8 +2650,8 @@ int main(int argc, char **argv) {
reset_timer(); reset_timer();
} }
mod_config()->http2_upstream_callbacks = create_http2_upstream_callbacks(); mod_config()->http2.upstream.callbacks = create_http2_upstream_callbacks();
mod_config()->http2_downstream_callbacks = mod_config()->http2.downstream.callbacks =
create_http2_downstream_callbacks(); create_http2_downstream_callbacks();
if (event_loop() != 0) { if (event_loop() != 0) {

View File

@ -404,14 +404,16 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
setup_upstream_io_callback(); setup_upstream_io_callback();
} }
if ((get_config()->forwarded_params & FORWARDED_FOR) && auto &fwdconf = get_config()->http.forwarded;
get_config()->forwarded_for_node_type == FORWARDED_NODE_OBFUSCATED) {
if (get_config()->forwarded_for_obfuscated.empty()) { if ((fwdconf.params & FORWARDED_FOR) &&
fwdconf.for_node_type == FORWARDED_NODE_OBFUSCATED) {
if (fwdconf.for_obfuscated.empty()) {
forwarded_for_obfuscated_ = "_"; forwarded_for_obfuscated_ = "_";
forwarded_for_obfuscated_ += util::random_alpha_digit( forwarded_for_obfuscated_ += util::random_alpha_digit(
worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH); worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH);
} else { } else {
forwarded_for_obfuscated_ = get_config()->forwarded_for_obfuscated; forwarded_for_obfuscated_ = fwdconf.for_obfuscated;
} }
} }
} }
@ -1120,8 +1122,10 @@ int ClientHandler::proxy_protocol_read() {
} }
const std::string &ClientHandler::get_forwarded_by() { const std::string &ClientHandler::get_forwarded_by() {
if (get_config()->forwarded_by_node_type == FORWARDED_NODE_OBFUSCATED) { auto &fwdconf = get_config()->http.forwarded;
return get_config()->forwarded_by_obfuscated;
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED) {
return fwdconf.by_obfuscated;
} }
if (!local_hostport_.empty()) { if (!local_hostport_.empty()) {
return local_hostport_; return local_hostport_;
@ -1158,7 +1162,7 @@ const std::string &ClientHandler::get_forwarded_by() {
} }
const std::string &ClientHandler::get_forwarded_for() const { const std::string &ClientHandler::get_forwarded_for() const {
if (get_config()->forwarded_for_node_type == FORWARDED_NODE_OBFUSCATED) { if (get_config()->http.forwarded.for_node_type == FORWARDED_NODE_OBFUSCATED) {
return forwarded_for_obfuscated_; return forwarded_for_obfuscated_;
} }

View File

@ -1447,7 +1447,7 @@ int parse_config(const char *opt, const char *optarg,
return parse_uint(&mod_config()->num_worker, opt, optarg); return parse_uint(&mod_config()->num_worker, opt, optarg);
#endif // !NOTHREADS #endif // !NOTHREADS
case SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS: case SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS:
return parse_uint(&mod_config()->http2_max_concurrent_streams, opt, optarg); return parse_uint(&mod_config()->http2.max_concurrent_streams, opt, optarg);
case SHRPX_OPTID_LOG_LEVEL: case SHRPX_OPTID_LOG_LEVEL:
if (Log::set_severity_level_by_name(optarg) == -1) { if (Log::set_severity_level_by_name(optarg) == -1) {
LOG(ERROR) << opt << ": Invalid severity level: " << optarg; LOG(ERROR) << opt << ": Invalid severity level: " << optarg;
@ -1472,15 +1472,15 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_ADD_X_FORWARDED_FOR: case SHRPX_OPTID_ADD_X_FORWARDED_FOR:
mod_config()->add_x_forwarded_for = util::strieq(optarg, "yes"); mod_config()->http.xff.add = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR: case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR:
mod_config()->strip_incoming_x_forwarded_for = util::strieq(optarg, "yes"); mod_config()->http.xff.strip_incoming = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_NO_VIA: case SHRPX_OPTID_NO_VIA:
mod_config()->no_via = util::strieq(optarg, "yes"); mod_config()->http.no_via = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT: case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT:
@ -1541,9 +1541,9 @@ int parse_config(const char *opt, const char *optarg,
size_t *resp; size_t *resp;
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) { if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
resp = &mod_config()->http2_upstream_window_bits; resp = &mod_config()->http2.upstream.window_bits;
} else { } else {
resp = &mod_config()->http2_downstream_window_bits; resp = &mod_config()->http2.downstream.window_bits;
} }
errno = 0; errno = 0;
@ -1569,9 +1569,9 @@ int parse_config(const char *opt, const char *optarg,
size_t *resp; size_t *resp;
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) { if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) {
resp = &mod_config()->http2_upstream_connection_window_bits; resp = &mod_config()->http2.upstream.connection_window_bits;
} else { } else {
resp = &mod_config()->http2_downstream_connection_window_bits; resp = &mod_config()->http2.downstream.connection_window_bits;
} }
errno = 0; errno = 0;
@ -1786,19 +1786,22 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER: case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER:
mod_config()->http2_upstream_dump_request_header_file = strcopy(optarg); mod_config()->http2.upstream.debug.dump.request_header_file =
strcopy(optarg);
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER: case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER:
mod_config()->http2_upstream_dump_response_header_file = strcopy(optarg); mod_config()->http2.upstream.debug.dump.response_header_file =
strcopy(optarg);
return 0; return 0;
case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING: case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING:
mod_config()->http2_no_cookie_crumbling = util::strieq(optarg, "yes"); mod_config()->http2.no_cookie_crumbling = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_FRONTEND_FRAME_DEBUG: case SHRPX_OPTID_FRONTEND_FRAME_DEBUG:
mod_config()->upstream_frame_debug = util::strieq(optarg, "yes"); mod_config()->http2.upstream.debug.frame_debug =
util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_PADDING: case SHRPX_OPTID_PADDING:
@ -1845,7 +1848,7 @@ int parse_config(const char *opt, const char *optarg,
} }
} }
mod_config()->altsvcs.push_back(std::move(altsvc)); mod_config()->http.altsvcs.push_back(std::move(altsvc));
return 0; return 0;
} }
@ -1857,16 +1860,16 @@ int parse_config(const char *opt, const char *optarg,
return -1; return -1;
} }
if (optid == SHRPX_OPTID_ADD_REQUEST_HEADER) { if (optid == SHRPX_OPTID_ADD_REQUEST_HEADER) {
mod_config()->add_request_headers.push_back(std::move(p)); mod_config()->http.add_request_headers.push_back(std::move(p));
} else { } else {
mod_config()->add_response_headers.push_back(std::move(p)); mod_config()->http.add_response_headers.push_back(std::move(p));
} }
return 0; return 0;
} }
case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS: case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS:
return parse_uint(&mod_config()->worker_frontend_connections, opt, optarg); return parse_uint(&mod_config()->worker_frontend_connections, opt, optarg);
case SHRPX_OPTID_NO_LOCATION_REWRITE: case SHRPX_OPTID_NO_LOCATION_REWRITE:
mod_config()->no_location_rewrite = util::strieq(optarg, "yes"); mod_config()->http.no_location_rewrite = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_NO_HOST_REWRITE: case SHRPX_OPTID_NO_HOST_REWRITE:
@ -1941,11 +1944,11 @@ int parse_config(const char *opt, const char *optarg,
} }
case SHRPX_OPTID_NO_SERVER_PUSH: case SHRPX_OPTID_NO_SERVER_PUSH:
mod_config()->no_server_push = util::strieq(optarg, "yes"); mod_config()->http2.no_server_push = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER: case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER:
return parse_uint(&mod_config()->http2_downstream_connections_per_worker, return parse_uint(&mod_config()->http2.downstream.connections_per_worker,
opt, optarg); opt, optarg);
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE: case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
mod_config()->tls.ocsp.fetch_ocsp_response_file = strcopy(optarg); mod_config()->tls.ocsp.fetch_ocsp_response_file = strcopy(optarg);
@ -1958,10 +1961,10 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_HEADER_FIELD_BUFFER: case SHRPX_OPTID_HEADER_FIELD_BUFFER:
return parse_uint_with_unit(&mod_config()->header_field_buffer, opt, return parse_uint_with_unit(&mod_config()->http.header_field_buffer, opt,
optarg); optarg);
case SHRPX_OPTID_MAX_HEADER_FIELDS: case SHRPX_OPTID_MAX_HEADER_FIELDS:
return parse_uint(&mod_config()->max_header_fields, opt, optarg); return parse_uint(&mod_config()->http.max_header_fields, opt, optarg);
case SHRPX_OPTID_INCLUDE: { case SHRPX_OPTID_INCLUDE: {
if (included_set.count(optarg)) { if (included_set.count(optarg)) {
LOG(ERROR) << opt << ": " << optarg << " has already been included"; LOG(ERROR) << opt << ": " << optarg << " has already been included";
@ -1992,7 +1995,7 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_HOST_REWRITE: case SHRPX_OPTID_HOST_REWRITE:
mod_config()->no_host_rewrite = !util::strieq(optarg, "yes"); mod_config()->http.no_host_rewrite = !util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: { case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: {
@ -2065,23 +2068,24 @@ int parse_config(const char *opt, const char *optarg,
mod_config()->accept_proxy_protocol = util::strieq(optarg, "yes"); mod_config()->accept_proxy_protocol = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_ADD_FORWARDED: case SHRPX_OPTID_ADD_FORWARDED: {
mod_config()->forwarded_params = FORWARDED_NONE; auto &fwdconf = mod_config()->http.forwarded;
fwdconf.params = FORWARDED_NONE;
for (const auto &param : util::parse_config_str_list(optarg)) { for (const auto &param : util::parse_config_str_list(optarg)) {
if (util::strieq(param, "by")) { if (util::strieq(param, "by")) {
mod_config()->forwarded_params |= FORWARDED_BY; fwdconf.params |= FORWARDED_BY;
continue; continue;
} }
if (util::strieq(param, "for")) { if (util::strieq(param, "for")) {
mod_config()->forwarded_params |= FORWARDED_FOR; fwdconf.params |= FORWARDED_FOR;
continue; continue;
} }
if (util::strieq(param, "host")) { if (util::strieq(param, "host")) {
mod_config()->forwarded_params |= FORWARDED_HOST; fwdconf.params |= FORWARDED_HOST;
continue; continue;
} }
if (util::strieq(param, "proto")) { if (util::strieq(param, "proto")) {
mod_config()->forwarded_params |= FORWARDED_PROTO; fwdconf.params |= FORWARDED_PROTO;
continue; continue;
} }
@ -2091,8 +2095,9 @@ int parse_config(const char *opt, const char *optarg,
} }
return 0; return 0;
}
case SHRPX_OPTID_STRIP_INCOMING_FORWARDED: case SHRPX_OPTID_STRIP_INCOMING_FORWARDED:
mod_config()->strip_incoming_forwarded = util::strieq(optarg, "yes"); mod_config()->http.forwarded.strip_incoming = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_FORWARDED_BY: case SHRPX_OPTID_FORWARDED_BY:
@ -2105,23 +2110,23 @@ int parse_config(const char *opt, const char *optarg,
return -1; return -1;
} }
auto &fwdconf = mod_config()->http.forwarded;
switch (optid) { switch (optid) {
case SHRPX_OPTID_FORWARDED_BY: case SHRPX_OPTID_FORWARDED_BY:
mod_config()->forwarded_by_node_type = fwdconf.by_node_type = static_cast<shrpx_forwarded_node_type>(type);
static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') { if (optarg[0] == '_') {
mod_config()->forwarded_by_obfuscated = optarg; fwdconf.by_obfuscated = optarg;
} else { } else {
mod_config()->forwarded_by_obfuscated = ""; fwdconf.by_obfuscated = "";
} }
break; break;
case SHRPX_OPTID_FORWARDED_FOR: case SHRPX_OPTID_FORWARDED_FOR:
mod_config()->forwarded_for_node_type = fwdconf.for_node_type = static_cast<shrpx_forwarded_node_type>(type);
static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') { if (optarg[0] == '_') {
mod_config()->forwarded_for_obfuscated = optarg; fwdconf.for_obfuscated = optarg;
} else { } else {
mod_config()->forwarded_for_obfuscated = ""; fwdconf.for_obfuscated = "";
} }
break; break;
} }

View File

@ -289,6 +289,7 @@ struct HttpProxy {
std::string host; std::string host;
// userinfo in http proxy URI, not percent-encoded form // userinfo in http proxy URI, not percent-encoded form
std::string userinfo; std::string userinfo;
// port in http proxy URI
uint16_t port; uint16_t port;
}; };
@ -371,23 +372,76 @@ struct TLSConfig {
bool insecure; bool insecure;
}; };
struct Config { struct HttpConfig {
struct {
// obfuscated value used in "by" parameter of Forwarded header
// field.
std::string by_obfuscated;
// obfuscated value used in "for" parameter of Forwarded header
// field. This is only used when user defined static obfuscated
// string is provided.
std::string for_obfuscated;
// bitwise-OR of one or more of shrpx_forwarded_param values.
uint32_t params;
// type of value recorded in "by" parameter of Forwarded header
// field.
shrpx_forwarded_node_type by_node_type;
// type of value recorded in "for" parameter of Forwarded header
// field.
shrpx_forwarded_node_type for_node_type;
bool strip_incoming;
} forwarded;
struct {
bool add;
bool strip_incoming;
} xff;
std::vector<AltSvc> altsvcs; std::vector<AltSvc> altsvcs;
std::vector<std::pair<std::string, std::string>> add_request_headers; std::vector<std::pair<std::string, std::string>> add_request_headers;
std::vector<std::pair<std::string, std::string>> add_response_headers; std::vector<std::pair<std::string, std::string>> add_response_headers;
StringRef server_name;
size_t header_field_buffer;
size_t max_header_fields;
bool no_via;
bool no_location_rewrite;
bool no_host_rewrite;
};
struct Http2Config {
struct {
struct {
struct {
std::unique_ptr<char[]> request_header_file;
std::unique_ptr<char[]> response_header_file;
FILE *request_header;
FILE *response_header;
} dump;
bool frame_debug;
} debug;
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
size_t window_bits;
size_t connection_window_bits;
} upstream;
struct {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
size_t window_bits;
size_t connection_window_bits;
size_t connections_per_worker;
} downstream;
size_t max_concurrent_streams;
bool no_cookie_crumbling;
bool no_server_push;
};
struct Config {
std::vector<LogFragment> accesslog_format; std::vector<LogFragment> accesslog_format;
std::vector<DownstreamAddrGroup> downstream_addr_groups; std::vector<DownstreamAddrGroup> downstream_addr_groups;
Router router; Router router;
HttpProxy downstream_http_proxy; HttpProxy downstream_http_proxy;
HttpConfig http;
Http2Config http2;
TLSConfig tls; TLSConfig tls;
// obfuscated value used in "by" parameter of Forwarded header
// field.
std::string forwarded_by_obfuscated;
// obfuscated value used in "for" parameter of Forwarded header
// field. This is only used when user defined static obfuscated
// string is provided.
std::string forwarded_for_obfuscated;
StringRef server_name;
ev_tstamp http2_upstream_read_timeout; ev_tstamp http2_upstream_read_timeout;
ev_tstamp upstream_read_timeout; ev_tstamp upstream_read_timeout;
ev_tstamp upstream_write_timeout; ev_tstamp upstream_write_timeout;
@ -402,28 +456,14 @@ struct Config {
std::unique_ptr<char[]> host; std::unique_ptr<char[]> host;
std::unique_ptr<char[]> pid_file; std::unique_ptr<char[]> pid_file;
std::unique_ptr<char[]> conf_path; std::unique_ptr<char[]> conf_path;
std::unique_ptr<char[]> http2_upstream_dump_request_header_file;
std::unique_ptr<char[]> http2_upstream_dump_response_header_file;
std::unique_ptr<char[]> accesslog_file; std::unique_ptr<char[]> accesslog_file;
std::unique_ptr<char[]> errorlog_file; std::unique_ptr<char[]> errorlog_file;
std::unique_ptr<char[]> user; std::unique_ptr<char[]> user;
std::unique_ptr<char[]> mruby_file; std::unique_ptr<char[]> mruby_file;
FILE *http2_upstream_dump_request_header;
FILE *http2_upstream_dump_response_header;
nghttp2_session_callbacks *http2_upstream_callbacks;
nghttp2_session_callbacks *http2_downstream_callbacks;
nghttp2_option *http2_option;
nghttp2_option *http2_client_option;
char **original_argv; char **original_argv;
char **argv; char **argv;
char *cwd; char *cwd;
size_t num_worker; size_t num_worker;
size_t http2_max_concurrent_streams;
size_t http2_upstream_window_bits;
size_t http2_downstream_window_bits;
size_t http2_upstream_connection_window_bits;
size_t http2_downstream_connection_window_bits;
size_t http2_downstream_connections_per_worker;
size_t downstream_connections_per_host; size_t downstream_connections_per_host;
size_t downstream_connections_per_frontend; size_t downstream_connections_per_frontend;
size_t read_rate; size_t read_rate;
@ -439,20 +479,10 @@ struct Config {
size_t rlimit_nofile; size_t rlimit_nofile;
size_t downstream_request_buffer_size; size_t downstream_request_buffer_size;
size_t downstream_response_buffer_size; size_t downstream_response_buffer_size;
size_t header_field_buffer;
size_t max_header_fields;
// The index of catch-all group in downstream_addr_groups. // The index of catch-all group in downstream_addr_groups.
size_t downstream_addr_group_catch_all; size_t downstream_addr_group_catch_all;
// downstream protocol; this will be determined by given options. // downstream protocol; this will be determined by given options.
shrpx_proto downstream_proto; shrpx_proto downstream_proto;
// bitwise-OR of one or more of shrpx_forwarded_param values.
uint32_t forwarded_params;
// type of value recorded in "by" parameter of Forwarded header
// field.
shrpx_forwarded_node_type forwarded_by_node_type;
// type of value recorded in "for" parameter of Forwarded header
// field.
shrpx_forwarded_node_type forwarded_for_node_type;
int syslog_facility; int syslog_facility;
int backlog; int backlog;
int argc; int argc;
@ -463,17 +493,11 @@ struct Config {
// frontend listening port. 0 if frontend listens on UNIX domain // frontend listening port. 0 if frontend listens on UNIX domain
// socket, in this case |host_unix| must be true. // socket, in this case |host_unix| must be true.
uint16_t port; uint16_t port;
// port in http proxy URI
uint16_t downstream_http_proxy_port;
bool verbose; bool verbose;
bool daemon; bool daemon;
bool http2_proxy; bool http2_proxy;
bool http2_bridge; bool http2_bridge;
bool client_proxy; bool client_proxy;
bool add_x_forwarded_for;
bool strip_incoming_x_forwarded_for;
bool strip_incoming_forwarded;
bool no_via;
bool upstream_no_tls; bool upstream_no_tls;
bool downstream_no_tls; bool downstream_no_tls;
// Send accesslog to syslog, ignoring accesslog_file. // Send accesslog to syslog, ignoring accesslog_file.
@ -485,11 +509,6 @@ struct Config {
bool client_mode; bool client_mode;
bool backend_ipv4; bool backend_ipv4;
bool backend_ipv6; bool backend_ipv6;
bool http2_no_cookie_crumbling;
bool upstream_frame_debug;
bool no_location_rewrite;
bool no_host_rewrite;
bool no_server_push;
// true if host contains UNIX domain socket path // true if host contains UNIX domain socket path
bool host_unix; bool host_unix;
bool accept_proxy_protocol; bool accept_proxy_protocol;

View File

@ -44,7 +44,7 @@ std::string create_error_html(unsigned int status_code) {
res += "</title><body><h1>"; res += "</title><body><h1>";
res += status; res += status;
res += "</h1><footer>"; res += "</h1><footer>";
const auto &server_name = get_config()->server_name; const auto &server_name = get_config()->http.server_name;
res.append(server_name.c_str(), server_name.size()); res.append(server_name.c_str(), server_name.size());
res += " at port "; res += " at port ";
res += util::utos(get_config()->port); res += util::utos(get_config()->port);

View File

@ -256,8 +256,11 @@ int Http2DownstreamConnection::push_request_headers() {
const auto &req = downstream_->request(); const auto &req = downstream_->request();
auto &httpconf = get_config()->http;
auto &http2conf = get_config()->http2;
auto no_host_rewrite = auto no_host_rewrite =
get_config()->no_host_rewrite || get_config()->http2_proxy || httpconf.no_host_rewrite || get_config()->http2_proxy ||
get_config()->client_proxy || req.method == HTTP_CONNECT; get_config()->client_proxy || req.method == HTTP_CONNECT;
// http2session_ has already in CONNECTED state, so we can get // http2session_ has already in CONNECTED state, so we can get
@ -278,7 +281,7 @@ int Http2DownstreamConnection::push_request_headers() {
downstream_->set_request_downstream_host(authority.str()); downstream_->set_request_downstream_host(authority.str());
size_t num_cookies = 0; size_t num_cookies = 0;
if (!get_config()->http2_no_cookie_crumbling) { if (!http2conf.no_cookie_crumbling) {
num_cookies = downstream_->count_crumble_request_cookie(); num_cookies = downstream_->count_crumble_request_cookie();
} }
@ -294,7 +297,7 @@ int Http2DownstreamConnection::push_request_headers() {
// 9. forwarded (optional) // 9. forwarded (optional)
auto nva = std::vector<nghttp2_nv>(); auto nva = std::vector<nghttp2_nv>();
nva.reserve(req.fs.headers().size() + 9 + num_cookies + nva.reserve(req.fs.headers().size() + 9 + num_cookies +
get_config()->add_request_headers.size()); httpconf.add_request_headers.size());
nva.push_back( nva.push_back(
http2::make_nv_lc_nocopy(":method", http2::to_method_string(req.method))); http2::make_nv_lc_nocopy(":method", http2::to_method_string(req.method)));
@ -328,7 +331,7 @@ int Http2DownstreamConnection::push_request_headers() {
chunked_encoding = true; chunked_encoding = true;
} }
if (!get_config()->http2_no_cookie_crumbling) { if (!http2conf.no_cookie_crumbling) {
downstream_->crumble_request_cookie(nva); downstream_->crumble_request_cookie(nva);
} }
@ -337,12 +340,13 @@ int Http2DownstreamConnection::push_request_headers() {
std::string forwarded_value; std::string forwarded_value;
auto fwd = get_config()->strip_incoming_forwarded auto &fwdconf = httpconf.forwarded;
? nullptr
: req.fs.header(http2::HD_FORWARDED);
if (get_config()->forwarded_params) { auto fwd =
auto params = get_config()->forwarded_params; fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
if (fwdconf.params) {
auto params = fwdconf.params;
if (get_config()->http2_proxy || get_config()->client_proxy || if (get_config()->http2_proxy || get_config()->client_proxy ||
req.method == HTTP_CONNECT) { req.method == HTTP_CONNECT) {
@ -370,12 +374,14 @@ int Http2DownstreamConnection::push_request_headers() {
forwarded_value = fwd->value; forwarded_value = fwd->value;
} }
std::string xff_value; auto &xffconf = httpconf.xff;
auto xff = get_config()->strip_incoming_x_forwarded_for
? nullptr auto xff = xffconf.strip_incoming ? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR); : req.fs.header(http2::HD_X_FORWARDED_FOR);
if (get_config()->add_x_forwarded_for) { std::string xff_value;
if (xffconf.add) {
if (xff) { if (xff) {
xff_value = (*xff).value; xff_value = (*xff).value;
xff_value += ", "; xff_value += ", ";
@ -394,7 +400,7 @@ int Http2DownstreamConnection::push_request_headers() {
std::string via_value; std::string via_value;
auto via = req.fs.header(http2::HD_VIA); auto via = req.fs.header(http2::HD_VIA);
if (get_config()->no_via) { if (httpconf.no_via) {
if (via) { if (via) {
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value));
} }
@ -415,7 +421,7 @@ int Http2DownstreamConnection::push_request_headers() {
nva.push_back(http2::make_nv_ll("te", "trailers")); nva.push_back(http2::make_nv_ll("te", "trailers"));
} }
for (auto &p : get_config()->add_request_headers) { for (auto &p : httpconf.add_request_headers) {
nva.push_back(http2::make_nv_nocopy(p.first, p.second)); nva.push_back(http2::make_nv_nocopy(p.first, p.second));
} }

View File

@ -1309,9 +1309,10 @@ int Http2Session::connection_made() {
} }
} }
rv = nghttp2_session_client_new2(&session_, auto &http2conf = get_config()->http2;
get_config()->http2_downstream_callbacks,
this, get_config()->http2_client_option); rv = nghttp2_session_client_new2(&session_, http2conf.downstream.callbacks,
this, http2conf.downstream.option);
if (rv != 0) { if (rv != 0) {
return -1; return -1;
@ -1322,12 +1323,12 @@ int Http2Session::connection_made() {
std::array<nghttp2_settings_entry, 3> entry; std::array<nghttp2_settings_entry, 3> entry;
size_t nentry = 2; size_t nentry = 2;
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = get_config()->http2_max_concurrent_streams; entry[0].value = http2conf.max_concurrent_streams;
entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
entry[1].value = (1 << get_config()->http2_downstream_window_bits) - 1; entry[1].value = (1 << http2conf.downstream.window_bits) - 1;
if (get_config()->no_server_push || get_config()->http2_proxy || if (http2conf.no_server_push || get_config()->http2_proxy ||
get_config()->client_proxy) { get_config()->client_proxy) {
entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
entry[nentry].value = 0; entry[nentry].value = 0;
@ -1340,9 +1341,9 @@ int Http2Session::connection_made() {
return -1; return -1;
} }
if (get_config()->http2_downstream_connection_window_bits > 16) { auto connection_window_bits = http2conf.downstream.connection_window_bits;
int32_t delta = if (connection_window_bits > 16) {
(1 << get_config()->http2_downstream_connection_window_bits) - 1 - int32_t delta = (1 << connection_window_bits) - 1 -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta); rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
if (rv != 0) { if (rv != 0) {

View File

@ -154,7 +154,7 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
const uint8_t *name, size_t namelen, const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen, uint8_t flags, const uint8_t *value, size_t valuelen, uint8_t flags,
void *user_data) { void *user_data) {
if (get_config()->upstream_frame_debug) { if (get_config()->http2.upstream.debug.frame_debug) {
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);
} }
@ -170,9 +170,11 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
auto &req = downstream->request(); auto &req = downstream->request();
auto &httpconf = get_config()->http;
if (req.fs.buffer_size() + namelen + valuelen > if (req.fs.buffer_size() + namelen + valuelen >
get_config()->header_field_buffer || httpconf.header_field_buffer ||
req.fs.num_fields() >= get_config()->max_header_fields) { req.fs.num_fields() >= httpconf.max_header_fields) {
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) { if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
return 0; return 0;
} }
@ -263,8 +265,10 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
<< downstream->get_stream_id() << "\n" << ss.str(); << downstream->get_stream_id() << "\n" << ss.str();
} }
if (get_config()->http2_upstream_dump_request_header) { auto &dump = get_config()->http2.upstream.debug.dump;
http2::dump_nv(get_config()->http2_upstream_dump_request_header, nva);
if (dump.request_header) {
http2::dump_nv(dump.request_header, nva);
} }
auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH); auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH);
@ -398,7 +402,7 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) {
namespace { namespace {
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) { void *user_data) {
if (get_config()->upstream_frame_debug) { if (get_config()->http2.upstream.debug.frame_debug) {
verbose_on_frame_recv_callback(session, frame, user_data); verbose_on_frame_recv_callback(session, frame, user_data);
} }
auto upstream = static_cast<Http2Upstream *>(user_data); auto upstream = static_cast<Http2Upstream *>(user_data);
@ -500,7 +504,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
namespace { namespace {
int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame, int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) { void *user_data) {
if (get_config()->upstream_frame_debug) { if (get_config()->http2.upstream.debug.frame_debug) {
verbose_on_frame_send_callback(session, frame, user_data); verbose_on_frame_send_callback(session, frame, user_data);
} }
auto upstream = static_cast<Http2Upstream *>(user_data); auto upstream = static_cast<Http2Upstream *>(user_data);
@ -860,9 +864,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
int rv; int rv;
rv = nghttp2_session_server_new2(&session_, auto &http2conf = get_config()->http2;
get_config()->http2_upstream_callbacks, this,
get_config()->http2_option); rv = nghttp2_session_server_new2(&session_, http2conf.upstream.callbacks,
this, http2conf.upstream.option);
assert(rv == 0); assert(rv == 0);
@ -871,10 +876,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
// TODO Maybe call from outside? // TODO Maybe call from outside?
std::array<nghttp2_settings_entry, 2> entry; std::array<nghttp2_settings_entry, 2> entry;
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = get_config()->http2_max_concurrent_streams; entry[0].value = http2conf.max_concurrent_streams;
entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
entry[1].value = (1 << get_config()->http2_upstream_window_bits) - 1; entry[1].value = (1 << http2conf.upstream.window_bits) - 1;
rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(), rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
entry.size()); entry.size());
@ -883,9 +888,9 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
<< nghttp2_strerror(rv); << nghttp2_strerror(rv);
} }
if (get_config()->http2_upstream_connection_window_bits > 16) { if (http2conf.upstream.connection_window_bits > 16) {
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) - int32_t delta = (1 << http2conf.upstream.connection_window_bits) - 1 -
1 - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE; NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta); rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
if (rv != 0) { if (rv != 0) {
@ -1337,7 +1342,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_SERVER)) { if (!resp.fs.header(http2::HD_SERVER)) {
nva.push_back( nva.push_back(
http2::make_nv_ls_nocopy("server", get_config()->server_name)); http2::make_nv_ls_nocopy("server", get_config()->http.server_name));
} }
rv = nghttp2_submit_response(session_, downstream->get_stream_id(), rv = nghttp2_submit_response(session_, downstream->get_stream_id(),
@ -1386,7 +1391,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
: http2::make_nv_ls(":status", : http2::make_nv_ls(":status",
(status_code_str = util::utos(status_code))), (status_code_str = util::utos(status_code))),
http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), http2::make_nv_ll("content-type", "text/html; charset=UTF-8"),
http2::make_nv_ls_nocopy("server", get_config()->server_name), http2::make_nv_ls_nocopy("server", get_config()->http.server_name),
http2::make_nv_ls("content-length", content_length), http2::make_nv_ls("content-length", content_length),
http2::make_nv_ls("date", lgconf->time_http_str)); http2::make_nv_ls("date", lgconf->time_http_str));
@ -1442,8 +1447,10 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
} }
} }
auto &httpconf = get_config()->http;
if (!get_config()->http2_proxy && !get_config()->client_proxy && if (!get_config()->http2_proxy && !get_config()->client_proxy &&
!get_config()->no_location_rewrite) { !httpconf.no_location_rewrite) {
downstream->rewrite_location_response_header(req.scheme); downstream->rewrite_location_response_header(req.scheme);
} }
@ -1470,7 +1477,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
// 4 means :status and possible server, via and x-http2-push header // 4 means :status and possible server, via and x-http2-push header
// field. // field.
nva.reserve(resp.fs.headers().size() + 4 + nva.reserve(resp.fs.headers().size() + 4 +
get_config()->add_response_headers.size()); httpconf.add_response_headers.size());
std::string via_value; std::string via_value;
std::string response_status; std::string response_status;
@ -1506,8 +1513,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers()); http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers());
if (!get_config()->http2_proxy && !get_config()->client_proxy) { if (!get_config()->http2_proxy && !get_config()->client_proxy) {
nva.push_back( nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name));
http2::make_nv_ls_nocopy("server", get_config()->server_name));
} else { } else {
auto server = resp.fs.header(http2::HD_SERVER); auto server = resp.fs.header(http2::HD_SERVER);
if (server) { if (server) {
@ -1516,7 +1522,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
} }
auto via = resp.fs.header(http2::HD_VIA); auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) { if (httpconf.no_via) {
if (via) { if (via) {
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value));
} }
@ -1530,7 +1536,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
nva.push_back(http2::make_nv_ls("via", via_value)); nva.push_back(http2::make_nv_ls("via", via_value));
} }
for (auto &p : get_config()->add_response_headers) { for (auto &p : httpconf.add_response_headers) {
nva.push_back(http2::make_nv_nocopy(p.first, p.second)); nva.push_back(http2::make_nv_nocopy(p.first, p.second));
} }
@ -1544,9 +1550,11 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
log_response_headers(downstream, nva); log_response_headers(downstream, nva);
} }
if (get_config()->http2_upstream_dump_response_header) { auto &http2conf = get_config()->http2;
http2::dump_nv(get_config()->http2_upstream_dump_response_header,
nva.data(), nva.size()); if (http2conf.upstream.debug.dump.response_header) {
http2::dump_nv(http2conf.upstream.debug.dump.response_header, nva.data(),
nva.size());
} }
nghttp2_data_provider data_prd; nghttp2_data_provider data_prd;
@ -1574,7 +1582,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
// * We requires GET or POST for associated resource. Probably we // * We requires GET or POST for associated resource. Probably we
// don't want to push for HEAD request. Not sure other methods // don't want to push for HEAD request. Not sure other methods
// are also eligible for push. // are also eligible for push.
if (!get_config()->no_server_push && if (!http2conf.no_server_push &&
nghttp2_session_get_remote_settings(session_, nghttp2_session_get_remote_settings(session_,
NGHTTP2_SETTINGS_ENABLE_PUSH) == 1 && NGHTTP2_SETTINGS_ENABLE_PUSH) == 1 &&
!get_config()->http2_proxy && !get_config()->client_proxy && !get_config()->http2_proxy && !get_config()->client_proxy &&
@ -1875,7 +1883,7 @@ int Http2Upstream::submit_push_promise(const std::string &scheme,
} }
bool Http2Upstream::push_enabled() const { bool Http2Upstream::push_enabled() const {
return !(get_config()->no_server_push || return !(get_config()->http2.no_server_push ||
nghttp2_session_get_remote_settings( nghttp2_session_get_remote_settings(
session_, NGHTTP2_SETTINGS_ENABLE_PUSH) == 0 || session_, NGHTTP2_SETTINGS_ENABLE_PUSH) == 0 ||
get_config()->http2_proxy || get_config()->client_proxy); get_config()->http2_proxy || get_config()->client_proxy);

View File

@ -217,10 +217,12 @@ int HttpDownstreamConnection::push_request_headers() {
auto connect_method = req.method == HTTP_CONNECT; auto connect_method = req.method == HTTP_CONNECT;
auto &httpconf = get_config()->http;
// 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.
auto authority = StringRef(downstream_hostport); auto authority = StringRef(downstream_hostport);
auto no_host_rewrite = get_config()->no_host_rewrite || auto no_host_rewrite = httpconf.no_host_rewrite ||
get_config()->http2_proxy || get_config()->http2_proxy ||
get_config()->client_proxy || connect_method; get_config()->client_proxy || connect_method;
@ -296,11 +298,13 @@ int HttpDownstreamConnection::push_request_headers() {
auto upstream = downstream_->get_upstream(); auto upstream = downstream_->get_upstream();
auto handler = upstream->get_client_handler(); auto handler = upstream->get_client_handler();
auto fwd = get_config()->strip_incoming_forwarded auto &fwdconf = httpconf.forwarded;
? nullptr
: req.fs.header(http2::HD_FORWARDED); auto fwd =
if (get_config()->forwarded_params) { fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
auto params = get_config()->forwarded_params;
if (fwdconf.params) {
auto params = fwdconf.params;
if (get_config()->http2_proxy || get_config()->client_proxy || if (get_config()->http2_proxy || get_config()->client_proxy ||
connect_method) { connect_method) {
@ -328,11 +332,12 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n"); buf->append("\r\n");
} }
auto xff = get_config()->strip_incoming_x_forwarded_for auto &xffconf = httpconf.xff;
? nullptr
auto xff = xffconf.strip_incoming ? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR); : req.fs.header(http2::HD_X_FORWARDED_FOR);
if (get_config()->add_x_forwarded_for) { if (xffconf.add) {
buf->append("X-Forwarded-For: "); buf->append("X-Forwarded-For: ");
if (xff) { if (xff) {
buf->append((*xff).value); buf->append((*xff).value);
@ -353,7 +358,7 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n"); buf->append("\r\n");
} }
auto via = req.fs.header(http2::HD_VIA); auto via = req.fs.header(http2::HD_VIA);
if (get_config()->no_via) { if (httpconf.no_via) {
if (via) { if (via) {
buf->append("Via: "); buf->append("Via: ");
buf->append((*via).value); buf->append((*via).value);
@ -369,7 +374,7 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n"); buf->append("\r\n");
} }
for (auto &p : get_config()->add_request_headers) { for (auto &p : httpconf.add_request_headers) {
buf->append(p.first); buf->append(p.first);
buf->append(": "); buf->append(": ");
buf->append(p.second); buf->append(p.second);

View File

@ -88,7 +88,7 @@ int htp_uricb(http_parser *htp, const char *data, size_t len) {
// We happen to have the same value for method token. // We happen to have the same value for method token.
req.method = htp->method; req.method = htp->method;
if (req.fs.buffer_size() + len > get_config()->header_field_buffer) { if (req.fs.buffer_size() + len > get_config()->http.header_field_buffer) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Too large URI size=" ULOG(INFO, upstream) << "Too large URI size="
<< req.fs.buffer_size() + len; << req.fs.buffer_size() + len;
@ -115,8 +115,9 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
auto upstream = static_cast<HttpsUpstream *>(htp->data); auto upstream = static_cast<HttpsUpstream *>(htp->data);
auto downstream = upstream->get_downstream(); auto downstream = upstream->get_downstream();
auto &req = downstream->request(); auto &req = downstream->request();
auto &httpconf = get_config()->http;
if (req.fs.buffer_size() + len > get_config()->header_field_buffer) { if (req.fs.buffer_size() + len > httpconf.header_field_buffer) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Too large header block size=" ULOG(INFO, upstream) << "Too large header block size="
<< req.fs.buffer_size() + len; << req.fs.buffer_size() + len;
@ -130,7 +131,7 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
if (req.fs.header_key_prev()) { if (req.fs.header_key_prev()) {
req.fs.append_last_header_key(data, len); req.fs.append_last_header_key(data, len);
} else { } else {
if (req.fs.num_fields() >= get_config()->max_header_fields) { if (req.fs.num_fields() >= httpconf.max_header_fields) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) ULOG(INFO, upstream)
<< "Too many header field num=" << req.fs.num_fields() + 1; << "Too many header field num=" << req.fs.num_fields() + 1;
@ -146,7 +147,7 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
if (req.fs.trailer_key_prev()) { if (req.fs.trailer_key_prev()) {
req.fs.append_last_trailer_key(data, len); req.fs.append_last_trailer_key(data, len);
} else { } else {
if (req.fs.num_fields() >= get_config()->max_header_fields) { if (req.fs.num_fields() >= httpconf.max_header_fields) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) ULOG(INFO, upstream)
<< "Too many header field num=" << req.fs.num_fields() + 1; << "Too many header field num=" << req.fs.num_fields() + 1;
@ -166,7 +167,7 @@ int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) {
auto downstream = upstream->get_downstream(); auto downstream = upstream->get_downstream();
auto &req = downstream->request(); auto &req = downstream->request();
if (req.fs.buffer_size() + len > get_config()->header_field_buffer) { if (req.fs.buffer_size() + len > get_config()->http.header_field_buffer) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Too large header block size=" ULOG(INFO, upstream) << "Too large header block size="
<< req.fs.buffer_size() + len; << req.fs.buffer_size() + len;
@ -802,7 +803,7 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_SERVER)) { if (!resp.fs.header(http2::HD_SERVER)) {
output->append("Server: "); output->append("Server: ");
output->append(get_config()->server_name); output->append(get_config()->http.server_name);
output->append("\r\n"); output->append("\r\n");
} }
@ -839,8 +840,7 @@ void HttpsUpstream::error_reply(unsigned int status_code) {
auto status_str = http2::get_status_string(status_code); auto status_str = http2::get_status_string(status_code);
output->append(status_str); output->append(status_str);
output->append("\r\nServer: "); output->append("\r\nServer: ");
const auto &server_name = get_config()->server_name; output->append(get_config()->http.server_name);
output->append(server_name);
output->append("\r\nContent-Length: "); output->append("\r\nContent-Length: ");
auto cl = util::utos(html.size()); auto cl = util::utos(html.size());
output->append(cl); output->append(cl);
@ -927,8 +927,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
buf->append(http2::get_status_string(resp.http_status)); buf->append(http2::get_status_string(resp.http_status));
buf->append("\r\n"); buf->append("\r\n");
auto &httpconf = get_config()->http;
if (!get_config()->http2_proxy && !get_config()->client_proxy && if (!get_config()->http2_proxy && !get_config()->client_proxy &&
!get_config()->no_location_rewrite) { !httpconf.no_location_rewrite) {
downstream->rewrite_location_response_header( downstream->rewrite_location_response_header(
get_client_handler()->get_upstream_scheme()); get_client_handler()->get_upstream_scheme());
} }
@ -984,10 +986,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
if (!resp.fs.header(http2::HD_ALT_SVC)) { if (!resp.fs.header(http2::HD_ALT_SVC)) {
// We won't change or alter alt-svc from backend for now // We won't change or alter alt-svc from backend for now
if (!get_config()->altsvcs.empty()) { if (!httpconf.altsvcs.empty()) {
buf->append("Alt-Svc: "); buf->append("Alt-Svc: ");
auto &altsvcs = get_config()->altsvcs; auto &altsvcs = httpconf.altsvcs;
write_altsvc(buf, altsvcs[0]); write_altsvc(buf, altsvcs[0]);
for (size_t i = 1; i < altsvcs.size(); ++i) { for (size_t i = 1; i < altsvcs.size(); ++i) {
buf->append(", "); buf->append(", ");
@ -999,7 +1001,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
if (!get_config()->http2_proxy && !get_config()->client_proxy) { if (!get_config()->http2_proxy && !get_config()->client_proxy) {
buf->append("Server: "); buf->append("Server: ");
buf->append(get_config()->server_name); buf->append(httpconf.server_name);
buf->append("\r\n"); buf->append("\r\n");
} else { } else {
auto server = resp.fs.header(http2::HD_SERVER); auto server = resp.fs.header(http2::HD_SERVER);
@ -1011,7 +1013,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
} }
auto via = resp.fs.header(http2::HD_VIA); auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) { if (httpconf.no_via) {
if (via) { if (via) {
buf->append("Via: "); buf->append("Via: ");
buf->append((*via).value); buf->append((*via).value);
@ -1028,7 +1030,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
buf->append("\r\n"); buf->append("\r\n");
} }
for (auto &p : get_config()->add_response_headers) { for (auto &p : httpconf.add_response_headers) {
buf->append(p.first); buf->append(p.first);
buf->append(": "); buf->append(": ");
buf->append(p.second); buf->append(p.second);

View File

@ -173,10 +173,12 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
header_buffer += strlen(nv[i]) + strlen(nv[i + 1]); header_buffer += strlen(nv[i]) + strlen(nv[i + 1]);
} }
auto &httpconf = get_config()->http;
// spdy does not define usage of trailer fields, and we ignores // spdy does not define usage of trailer fields, and we ignores
// them. // them.
if (header_buffer > get_config()->header_field_buffer || if (header_buffer > httpconf.header_field_buffer ||
num_headers > get_config()->max_header_fields) { num_headers > httpconf.max_header_fields) {
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
return; return;
} }
@ -370,31 +372,33 @@ void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
return; return;
} }
auto &http2conf = get_config()->http2;
// If connection-level window control is not enabled (e.g, // If connection-level window control is not enabled (e.g,
// spdy/3), spdylay_session_get_recv_data_length() is always // spdy/3), spdylay_session_get_recv_data_length() is always
// returns 0. // returns 0.
if (spdylay_session_get_recv_data_length(session) > if (spdylay_session_get_recv_data_length(session) >
std::max(SPDYLAY_INITIAL_WINDOW_SIZE, std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
1 << get_config()->http2_upstream_connection_window_bits)) { 1 << http2conf.upstream.connection_window_bits)) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) ULOG(INFO, upstream) << "Flow control error on connection: "
<< "Flow control error on connection: "
<< "recv_window_size=" << "recv_window_size="
<< spdylay_session_get_recv_data_length(session) << ", window_size=" << spdylay_session_get_recv_data_length(session)
<< (1 << get_config()->http2_upstream_connection_window_bits); << ", window_size="
<< (1 << http2conf.upstream.connection_window_bits);
} }
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR); spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
return; return;
} }
if (spdylay_session_get_stream_recv_data_length(session, stream_id) > if (spdylay_session_get_stream_recv_data_length(session, stream_id) >
std::max(SPDYLAY_INITIAL_WINDOW_SIZE, std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
1 << get_config()->http2_upstream_window_bits)) { 1 << http2conf.upstream.window_bits)) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Flow control error: recv_window_size=" ULOG(INFO, upstream) << "Flow control error: recv_window_size="
<< spdylay_session_get_stream_recv_data_length( << spdylay_session_get_stream_recv_data_length(
session, stream_id) session, stream_id)
<< ", initial_window_size=" << ", initial_window_size="
<< (1 << get_config()->http2_upstream_window_bits); << (1 << http2conf.upstream.window_bits);
} }
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR); upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
return; return;
@ -518,10 +522,12 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
&max_buffer, sizeof(max_buffer)); &max_buffer, sizeof(max_buffer));
assert(rv == 0); assert(rv == 0);
auto &http2conf = get_config()->http2;
if (version >= SPDYLAY_PROTO_SPDY3) { if (version >= SPDYLAY_PROTO_SPDY3) {
int val = 1; int val = 1;
flow_control_ = true; flow_control_ = true;
initial_window_size_ = 1 << get_config()->http2_upstream_window_bits; initial_window_size_ = 1 << http2conf.upstream.window_bits;
rv = spdylay_session_set_option( rv = spdylay_session_set_option(
session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val)); session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val));
assert(rv == 0); assert(rv == 0);
@ -532,7 +538,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
// TODO Maybe call from outside? // TODO Maybe call from outside?
std::array<spdylay_settings_entry, 2> entry; std::array<spdylay_settings_entry, 2> entry;
entry[0].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = get_config()->http2_max_concurrent_streams; entry[0].value = http2conf.max_concurrent_streams;
entry[0].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE; entry[0].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE; entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
@ -544,8 +550,8 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
assert(rv == 0); assert(rv == 0);
if (version >= SPDYLAY_PROTO_SPDY3_1 && if (version >= SPDYLAY_PROTO_SPDY3_1 &&
get_config()->http2_upstream_connection_window_bits > 16) { http2conf.upstream.connection_window_bits > 16) {
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) - int32_t delta = (1 << http2conf.upstream.connection_window_bits) -
SPDYLAY_INITIAL_WINDOW_SIZE; SPDYLAY_INITIAL_WINDOW_SIZE;
rv = spdylay_submit_window_update(session_, 0, delta); rv = spdylay_submit_window_update(session_, 0, delta);
assert(rv == 0); assert(rv == 0);
@ -875,7 +881,7 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_SERVER)) { if (!resp.fs.header(http2::HD_SERVER)) {
nva.push_back("server"); nva.push_back("server");
nva.push_back(get_config()->server_name.c_str()); nva.push_back(get_config()->http.server_name.c_str());
} }
nva.push_back(nullptr); nva.push_back(nullptr);
@ -919,7 +925,7 @@ int SpdyUpstream::error_reply(Downstream *downstream,
std::string status_string = http2::get_status_string(status_code); std::string status_string = http2::get_status_string(status_code);
const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1", const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1",
"content-type", "text/html; charset=UTF-8", "server", "content-type", "text/html; charset=UTF-8", "server",
get_config()->server_name.c_str(), "content-length", get_config()->http.server_name.c_str(), "content-length",
content_length.c_str(), "date", content_length.c_str(), "date",
lgconf->time_http_str.c_str(), nullptr}; lgconf->time_http_str.c_str(), nullptr};
@ -997,15 +1003,17 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
DLOG(INFO, downstream) << "HTTP response header completed"; DLOG(INFO, downstream) << "HTTP response header completed";
} }
auto &httpconf = get_config()->http;
if (!get_config()->http2_proxy && !get_config()->client_proxy && if (!get_config()->http2_proxy && !get_config()->client_proxy &&
!get_config()->no_location_rewrite) { !httpconf.no_location_rewrite) {
downstream->rewrite_location_response_header(req.scheme); downstream->rewrite_location_response_header(req.scheme);
} }
// 8 means server, :status, :version and possible via header field. // 8 means server, :status, :version and possible via header field.
auto nv = make_unique<const char *[]>( auto nv =
resp.fs.headers().size() * 2 + 8 + make_unique<const char *[]>(resp.fs.headers().size() * 2 + 8 +
get_config()->add_response_headers.size() * 2 + 1); httpconf.add_response_headers.size() * 2 + 1);
size_t hdidx = 0; size_t hdidx = 0;
std::string via_value; std::string via_value;
@ -1034,7 +1042,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
if (!get_config()->http2_proxy && !get_config()->client_proxy) { if (!get_config()->http2_proxy && !get_config()->client_proxy) {
nv[hdidx++] = "server"; nv[hdidx++] = "server";
nv[hdidx++] = get_config()->server_name.c_str(); nv[hdidx++] = httpconf.server_name.c_str();
} else { } else {
auto server = resp.fs.header(http2::HD_SERVER); auto server = resp.fs.header(http2::HD_SERVER);
if (server) { if (server) {
@ -1044,7 +1052,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
} }
auto via = resp.fs.header(http2::HD_VIA); auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) { if (httpconf.no_via) {
if (via) { if (via) {
nv[hdidx++] = "via"; nv[hdidx++] = "via";
nv[hdidx++] = via->value.c_str(); nv[hdidx++] = via->value.c_str();
@ -1060,7 +1068,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
nv[hdidx++] = via_value.c_str(); nv[hdidx++] = via_value.c_str();
} }
for (auto &p : get_config()->add_response_headers) { for (auto &p : httpconf.add_response_headers) {
nv[hdidx++] = p.first.c_str(); nv[hdidx++] = p.first.c_str();
nv[hdidx++] = p.second.c_str(); nv[hdidx++] = p.second.c_str();
} }

View File

@ -91,7 +91,7 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
} }
if (get_config()->downstream_proto == PROTO_HTTP2) { if (get_config()->downstream_proto == PROTO_HTTP2) {
auto n = get_config()->http2_downstream_connections_per_worker; auto n = get_config()->http2.downstream.connections_per_worker;
size_t group = 0; size_t group = 0;
for (auto &dgrp : dgrps_) { for (auto &dgrp : dgrps_) {
auto m = n; auto m = n;