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()->daemon = false;
mod_config()->server_name = "nghttpx nghttp2/" NGHTTP2_VERSION;
mod_config()->host = strcopy("*");
mod_config()->port = 3000;
@ -926,25 +925,10 @@ void fill_default_config() {
// Timeout for pooled (idle) connections
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()->downstream_no_tls = false;
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_syslog = false;
mod_config()->accesslog_format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT);
@ -966,7 +950,6 @@ void fill_default_config() {
mod_config()->pid = getpid();
mod_config()->backend_ipv4 = false;
mod_config()->backend_ipv6 = false;
mod_config()->downstream_http_proxy_port = 0;
mod_config()->read_rate = 0;
mod_config()->read_burst = 0;
mod_config()->write_rate = 0;
@ -975,25 +958,9 @@ void fill_default_config() {
mod_config()->worker_read_burst = 0;
mod_config()->worker_write_rate = 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()->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()->argv = nullptr;
mod_config()->downstream_connections_per_host = 8;
@ -1001,11 +968,7 @@ void fill_default_config() {
mod_config()->listener_disable_timeout = 0.;
mod_config()->downstream_request_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()->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()->fastopen = 0;
@ -1040,12 +1003,57 @@ void fill_default_config() {
tlsconf.tls_proto_mask = 0;
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 {
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
@ -1450,29 +1458,29 @@ HTTP/2 and SPDY:
-c, --http2-max-concurrent-streams=<N>
Set the maximum number of the concurrent streams in one
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>
Sets the per-stream initial window size of HTTP/2 SPDY
frontend connection. For HTTP/2, the size is 2**<N>-1.
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>
Sets the per-connection window size of HTTP/2 and SPDY
frontend connection. For HTTP/2, the size is
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"(
--frontend-no-tls
Disable SSL/TLS on frontend connections.
--backend-http2-window-bits=<N>
Sets the initial window size of HTTP/2 backend
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>
Sets the per-connection window size of HTTP/2 backend
connection to 2**<N>-1.
Default: )"
<< get_config()->http2_downstream_connection_window_bits << R"(
<< get_config()->http2.downstream.connection_window_bits << R"(
--backend-no-tls
Disable SSL/TLS on backend connections.
--http2-no-cookie-crumbling
@ -1650,13 +1658,13 @@ HTTP:
Set maximum buffer size for incoming HTTP request header
field list. This is the sum of header name and value in
bytes.
Default: )" << util::utos_unit(get_config()->header_field_buffer)
<< R"(
Default: )"
<< util::utos_unit(get_config()->http.header_field_buffer) << R"(
--max-header-fields=<N>
Set maximum number of incoming HTTP request header
fields, which appear in one request or response header
field list.
Default: )" << get_config()->max_header_fields << R"(
Default: )" << get_config()->http.max_header_fields << R"(
Debug:
--frontend-http2-dump-request-header=<PATH>
@ -2374,44 +2382,49 @@ int main(int argc, char **argv) {
}
}
if (get_config()->http2_upstream_dump_request_header_file) {
auto path = get_config()->http2_upstream_dump_request_header_file.get();
auto f = open_file_for_write(path);
auto &http2conf = mod_config()->http2;
{
auto &dumpconf = http2conf.upstream.debug.dump;
if (f == nullptr) {
LOG(FATAL) << "Failed to open http2 upstream request header file: "
<< path;
exit(EXIT_FAILURE);
}
if (dumpconf.request_header_file) {
auto path = dumpconf.request_header_file.get();
auto f = open_file_for_write(path);
mod_config()->http2_upstream_dump_request_header = f;
if (f == nullptr) {
LOG(FATAL) << "Failed to open http2 upstream request header file: "
<< path;
exit(EXIT_FAILURE);
}
if (get_config()->uid != 0) {
if (chown_to_running_user(path) == -1) {
auto error = errno;
LOG(WARN) << "Changing owner of http2 upstream request header file "
<< path << " failed: " << strerror(error);
dumpconf.request_header = f;
if (get_config()->uid != 0) {
if (chown_to_running_user(path) == -1) {
auto error = errno;
LOG(WARN) << "Changing owner of http2 upstream request header file "
<< path << " failed: " << strerror(error);
}
}
}
}
if (get_config()->http2_upstream_dump_response_header_file) {
auto path = get_config()->http2_upstream_dump_response_header_file.get();
auto f = open_file_for_write(path);
if (dumpconf.response_header_file) {
auto path = dumpconf.response_header_file.get();
auto f = open_file_for_write(path);
if (f == nullptr) {
LOG(FATAL) << "Failed to open http2 upstream response header file: "
<< path;
exit(EXIT_FAILURE);
}
if (f == nullptr) {
LOG(FATAL) << "Failed to open http2 upstream response header file: "
<< path;
exit(EXIT_FAILURE);
}
mod_config()->http2_upstream_dump_response_header = f;
dumpconf.response_header = f;
if (get_config()->uid != 0) {
if (chown_to_running_user(path) == -1) {
auto error = errno;
LOG(WARN) << "Changing owner of http2 upstream response header file"
<< " " << path << " failed: " << strerror(error);
if (get_config()->uid != 0) {
if (chown_to_running_user(path) == -1) {
auto error = errno;
LOG(WARN) << "Changing owner of http2 upstream response header file"
<< " " << path << " failed: " << strerror(error);
}
}
}
}
@ -2617,16 +2630,18 @@ int main(int argc, char **argv) {
}
}
if (get_config()->forwarded_by_node_type == FORWARDED_NODE_OBFUSCATED &&
get_config()->forwarded_by_obfuscated.empty()) {
auto &fwdconf = mod_config()->http.forwarded;
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED &&
fwdconf.by_obfuscated.empty()) {
std::random_device rd;
std::mt19937 gen(rd());
auto &dst = mod_config()->forwarded_by_obfuscated;
auto &dst = fwdconf.by_obfuscated;
dst = "_";
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
set_output(stderr);
if (isatty(fileno(stdout))) {
@ -2635,8 +2650,8 @@ int main(int argc, char **argv) {
reset_timer();
}
mod_config()->http2_upstream_callbacks = create_http2_upstream_callbacks();
mod_config()->http2_downstream_callbacks =
mod_config()->http2.upstream.callbacks = create_http2_upstream_callbacks();
mod_config()->http2.downstream.callbacks =
create_http2_downstream_callbacks();
if (event_loop() != 0) {

View File

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

View File

@ -1447,7 +1447,7 @@ int parse_config(const char *opt, const char *optarg,
return parse_uint(&mod_config()->num_worker, opt, optarg);
#endif // !NOTHREADS
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:
if (Log::set_severity_level_by_name(optarg) == -1) {
LOG(ERROR) << opt << ": Invalid severity level: " << optarg;
@ -1472,15 +1472,15 @@ int parse_config(const char *opt, const char *optarg,
return 0;
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;
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;
case SHRPX_OPTID_NO_VIA:
mod_config()->no_via = util::strieq(optarg, "yes");
mod_config()->http.no_via = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT:
@ -1541,9 +1541,9 @@ int parse_config(const char *opt, const char *optarg,
size_t *resp;
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
resp = &mod_config()->http2_upstream_window_bits;
resp = &mod_config()->http2.upstream.window_bits;
} else {
resp = &mod_config()->http2_downstream_window_bits;
resp = &mod_config()->http2.downstream.window_bits;
}
errno = 0;
@ -1569,9 +1569,9 @@ int parse_config(const char *opt, const char *optarg,
size_t *resp;
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 {
resp = &mod_config()->http2_downstream_connection_window_bits;
resp = &mod_config()->http2.downstream.connection_window_bits;
}
errno = 0;
@ -1786,19 +1786,22 @@ int parse_config(const char *opt, const char *optarg,
return 0;
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;
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;
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;
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;
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;
}
@ -1857,16 +1860,16 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
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 {
mod_config()->add_response_headers.push_back(std::move(p));
mod_config()->http.add_response_headers.push_back(std::move(p));
}
return 0;
}
case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS:
return parse_uint(&mod_config()->worker_frontend_connections, opt, optarg);
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;
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:
mod_config()->no_server_push = util::strieq(optarg, "yes");
mod_config()->http2.no_server_push = util::strieq(optarg, "yes");
return 0;
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);
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
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;
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);
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: {
if (included_set.count(optarg)) {
LOG(ERROR) << opt << ": " << optarg << " has already been included";
@ -1992,7 +1995,7 @@ int parse_config(const char *opt, const char *optarg,
return 0;
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;
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");
return 0;
case SHRPX_OPTID_ADD_FORWARDED:
mod_config()->forwarded_params = FORWARDED_NONE;
case SHRPX_OPTID_ADD_FORWARDED: {
auto &fwdconf = mod_config()->http.forwarded;
fwdconf.params = FORWARDED_NONE;
for (const auto &param : util::parse_config_str_list(optarg)) {
if (util::strieq(param, "by")) {
mod_config()->forwarded_params |= FORWARDED_BY;
fwdconf.params |= FORWARDED_BY;
continue;
}
if (util::strieq(param, "for")) {
mod_config()->forwarded_params |= FORWARDED_FOR;
fwdconf.params |= FORWARDED_FOR;
continue;
}
if (util::strieq(param, "host")) {
mod_config()->forwarded_params |= FORWARDED_HOST;
fwdconf.params |= FORWARDED_HOST;
continue;
}
if (util::strieq(param, "proto")) {
mod_config()->forwarded_params |= FORWARDED_PROTO;
fwdconf.params |= FORWARDED_PROTO;
continue;
}
@ -2091,8 +2095,9 @@ int parse_config(const char *opt, const char *optarg,
}
return 0;
}
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;
case SHRPX_OPTID_FORWARDED_BY:
@ -2105,23 +2110,23 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
auto &fwdconf = mod_config()->http.forwarded;
switch (optid) {
case SHRPX_OPTID_FORWARDED_BY:
mod_config()->forwarded_by_node_type =
static_cast<shrpx_forwarded_node_type>(type);
fwdconf.by_node_type = static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') {
mod_config()->forwarded_by_obfuscated = optarg;
fwdconf.by_obfuscated = optarg;
} else {
mod_config()->forwarded_by_obfuscated = "";
fwdconf.by_obfuscated = "";
}
break;
case SHRPX_OPTID_FORWARDED_FOR:
mod_config()->forwarded_for_node_type =
static_cast<shrpx_forwarded_node_type>(type);
fwdconf.for_node_type = static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') {
mod_config()->forwarded_for_obfuscated = optarg;
fwdconf.for_obfuscated = optarg;
} else {
mod_config()->forwarded_for_obfuscated = "";
fwdconf.for_obfuscated = "";
}
break;
}

View File

@ -289,6 +289,7 @@ struct HttpProxy {
std::string host;
// userinfo in http proxy URI, not percent-encoded form
std::string userinfo;
// port in http proxy URI
uint16_t port;
};
@ -371,23 +372,76 @@ struct TLSConfig {
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<std::pair<std::string, std::string>> add_request_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<DownstreamAddrGroup> downstream_addr_groups;
Router router;
HttpProxy downstream_http_proxy;
HttpConfig http;
Http2Config http2;
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 upstream_read_timeout;
ev_tstamp upstream_write_timeout;
@ -402,28 +456,14 @@ struct Config {
std::unique_ptr<char[]> host;
std::unique_ptr<char[]> pid_file;
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[]> errorlog_file;
std::unique_ptr<char[]> user;
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 **argv;
char *cwd;
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_frontend;
size_t read_rate;
@ -439,20 +479,10 @@ struct Config {
size_t rlimit_nofile;
size_t downstream_request_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.
size_t downstream_addr_group_catch_all;
// downstream protocol; this will be determined by given options.
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 backlog;
int argc;
@ -463,17 +493,11 @@ struct Config {
// frontend listening port. 0 if frontend listens on UNIX domain
// socket, in this case |host_unix| must be true.
uint16_t port;
// port in http proxy URI
uint16_t downstream_http_proxy_port;
bool verbose;
bool daemon;
bool http2_proxy;
bool http2_bridge;
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 downstream_no_tls;
// Send accesslog to syslog, ignoring accesslog_file.
@ -485,11 +509,6 @@ struct Config {
bool client_mode;
bool backend_ipv4;
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
bool host_unix;
bool accept_proxy_protocol;

View File

@ -44,7 +44,7 @@ std::string create_error_html(unsigned int status_code) {
res += "</title><body><h1>";
res += status;
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 += " at port ";
res += util::utos(get_config()->port);

View File

@ -256,8 +256,11 @@ int Http2DownstreamConnection::push_request_headers() {
const auto &req = downstream_->request();
auto &httpconf = get_config()->http;
auto &http2conf = get_config()->http2;
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;
// 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());
size_t num_cookies = 0;
if (!get_config()->http2_no_cookie_crumbling) {
if (!http2conf.no_cookie_crumbling) {
num_cookies = downstream_->count_crumble_request_cookie();
}
@ -294,7 +297,7 @@ int Http2DownstreamConnection::push_request_headers() {
// 9. forwarded (optional)
auto nva = std::vector<nghttp2_nv>();
nva.reserve(req.fs.headers().size() + 9 + num_cookies +
get_config()->add_request_headers.size());
httpconf.add_request_headers.size());
nva.push_back(
http2::make_nv_lc_nocopy(":method", http2::to_method_string(req.method)));
@ -328,7 +331,7 @@ int Http2DownstreamConnection::push_request_headers() {
chunked_encoding = true;
}
if (!get_config()->http2_no_cookie_crumbling) {
if (!http2conf.no_cookie_crumbling) {
downstream_->crumble_request_cookie(nva);
}
@ -337,12 +340,13 @@ int Http2DownstreamConnection::push_request_headers() {
std::string forwarded_value;
auto fwd = get_config()->strip_incoming_forwarded
? nullptr
: req.fs.header(http2::HD_FORWARDED);
auto &fwdconf = httpconf.forwarded;
if (get_config()->forwarded_params) {
auto params = get_config()->forwarded_params;
auto fwd =
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 ||
req.method == HTTP_CONNECT) {
@ -370,12 +374,14 @@ int Http2DownstreamConnection::push_request_headers() {
forwarded_value = fwd->value;
}
std::string xff_value;
auto xff = get_config()->strip_incoming_x_forwarded_for
? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
auto &xffconf = httpconf.xff;
if (get_config()->add_x_forwarded_for) {
auto xff = xffconf.strip_incoming ? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
std::string xff_value;
if (xffconf.add) {
if (xff) {
xff_value = (*xff).value;
xff_value += ", ";
@ -394,7 +400,7 @@ int Http2DownstreamConnection::push_request_headers() {
std::string via_value;
auto via = req.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
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"));
}
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));
}

View File

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

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 *value, size_t valuelen, uint8_t flags,
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,
flags, user_data);
}
@ -170,9 +170,11 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
auto &req = downstream->request();
auto &httpconf = get_config()->http;
if (req.fs.buffer_size() + namelen + valuelen >
get_config()->header_field_buffer ||
req.fs.num_fields() >= get_config()->max_header_fields) {
httpconf.header_field_buffer ||
req.fs.num_fields() >= httpconf.max_header_fields) {
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
return 0;
}
@ -263,8 +265,10 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
<< downstream->get_stream_id() << "\n" << ss.str();
}
if (get_config()->http2_upstream_dump_request_header) {
http2::dump_nv(get_config()->http2_upstream_dump_request_header, nva);
auto &dump = get_config()->http2.upstream.debug.dump;
if (dump.request_header) {
http2::dump_nv(dump.request_header, nva);
}
auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH);
@ -398,7 +402,7 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) {
namespace {
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
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);
}
auto upstream = static_cast<Http2Upstream *>(user_data);
@ -500,7 +504,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
namespace {
int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
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);
}
auto upstream = static_cast<Http2Upstream *>(user_data);
@ -860,9 +864,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
int rv;
rv = nghttp2_session_server_new2(&session_,
get_config()->http2_upstream_callbacks, this,
get_config()->http2_option);
auto &http2conf = get_config()->http2;
rv = nghttp2_session_server_new2(&session_, http2conf.upstream.callbacks,
this, http2conf.upstream.option);
assert(rv == 0);
@ -871,10 +876,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
// TODO Maybe call from outside?
std::array<nghttp2_settings_entry, 2> entry;
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].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(),
entry.size());
@ -883,9 +888,9 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
<< nghttp2_strerror(rv);
}
if (get_config()->http2_upstream_connection_window_bits > 16) {
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) -
1 - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
if (http2conf.upstream.connection_window_bits > 16) {
int32_t delta = (1 << http2conf.upstream.connection_window_bits) - 1 -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
if (rv != 0) {
@ -1337,7 +1342,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_SERVER)) {
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(),
@ -1386,7 +1391,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
: http2::make_nv_ls(":status",
(status_code_str = util::utos(status_code))),
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("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 &&
!get_config()->no_location_rewrite) {
!httpconf.no_location_rewrite) {
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
// field.
nva.reserve(resp.fs.headers().size() + 4 +
get_config()->add_response_headers.size());
httpconf.add_response_headers.size());
std::string via_value;
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());
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
nva.push_back(
http2::make_nv_ls_nocopy("server", get_config()->server_name));
nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name));
} else {
auto server = resp.fs.header(http2::HD_SERVER);
if (server) {
@ -1516,7 +1522,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
}
auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
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));
}
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));
}
@ -1544,9 +1550,11 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
log_response_headers(downstream, nva);
}
if (get_config()->http2_upstream_dump_response_header) {
http2::dump_nv(get_config()->http2_upstream_dump_response_header,
nva.data(), nva.size());
auto &http2conf = get_config()->http2;
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;
@ -1574,7 +1582,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
// * We requires GET or POST for associated resource. Probably we
// don't want to push for HEAD request. Not sure other methods
// are also eligible for push.
if (!get_config()->no_server_push &&
if (!http2conf.no_server_push &&
nghttp2_session_get_remote_settings(session_,
NGHTTP2_SETTINGS_ENABLE_PUSH) == 1 &&
!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 {
return !(get_config()->no_server_push ||
return !(get_config()->http2.no_server_push ||
nghttp2_session_get_remote_settings(
session_, NGHTTP2_SETTINGS_ENABLE_PUSH) == 0 ||
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 &httpconf = get_config()->http;
// For HTTP/1.0 request, there is no authority in request. In that
// case, we use backend server's host nonetheless.
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()->client_proxy || connect_method;
@ -296,11 +298,13 @@ int HttpDownstreamConnection::push_request_headers() {
auto upstream = downstream_->get_upstream();
auto handler = upstream->get_client_handler();
auto fwd = get_config()->strip_incoming_forwarded
? nullptr
: req.fs.header(http2::HD_FORWARDED);
if (get_config()->forwarded_params) {
auto params = get_config()->forwarded_params;
auto &fwdconf = httpconf.forwarded;
auto fwd =
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 ||
connect_method) {
@ -328,11 +332,12 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n");
}
auto xff = get_config()->strip_incoming_x_forwarded_for
? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
auto &xffconf = httpconf.xff;
if (get_config()->add_x_forwarded_for) {
auto xff = xffconf.strip_incoming ? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
if (xffconf.add) {
buf->append("X-Forwarded-For: ");
if (xff) {
buf->append((*xff).value);
@ -353,7 +358,7 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n");
}
auto via = req.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
buf->append("Via: ");
buf->append((*via).value);
@ -369,7 +374,7 @@ int HttpDownstreamConnection::push_request_headers() {
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(": ");
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.
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)) {
ULOG(INFO, upstream) << "Too large URI size="
<< 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 downstream = upstream->get_downstream();
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)) {
ULOG(INFO, upstream) << "Too large header block size="
<< 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()) {
req.fs.append_last_header_key(data, len);
} else {
if (req.fs.num_fields() >= get_config()->max_header_fields) {
if (req.fs.num_fields() >= httpconf.max_header_fields) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream)
<< "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()) {
req.fs.append_last_trailer_key(data, len);
} else {
if (req.fs.num_fields() >= get_config()->max_header_fields) {
if (req.fs.num_fields() >= httpconf.max_header_fields) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream)
<< "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 &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)) {
ULOG(INFO, upstream) << "Too large header block size="
<< 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)) {
output->append("Server: ");
output->append(get_config()->server_name);
output->append(get_config()->http.server_name);
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);
output->append(status_str);
output->append("\r\nServer: ");
const auto &server_name = get_config()->server_name;
output->append(server_name);
output->append(get_config()->http.server_name);
output->append("\r\nContent-Length: ");
auto cl = util::utos(html.size());
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("\r\n");
auto &httpconf = get_config()->http;
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
!get_config()->no_location_rewrite) {
!httpconf.no_location_rewrite) {
downstream->rewrite_location_response_header(
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)) {
// 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: ");
auto &altsvcs = get_config()->altsvcs;
auto &altsvcs = httpconf.altsvcs;
write_altsvc(buf, altsvcs[0]);
for (size_t i = 1; i < altsvcs.size(); ++i) {
buf->append(", ");
@ -999,7 +1001,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
buf->append("Server: ");
buf->append(get_config()->server_name);
buf->append(httpconf.server_name);
buf->append("\r\n");
} else {
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);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
buf->append("Via: ");
buf->append((*via).value);
@ -1028,7 +1030,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
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(": ");
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]);
}
auto &httpconf = get_config()->http;
// spdy does not define usage of trailer fields, and we ignores
// them.
if (header_buffer > get_config()->header_field_buffer ||
num_headers > get_config()->max_header_fields) {
if (header_buffer > httpconf.header_field_buffer ||
num_headers > httpconf.max_header_fields) {
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
return;
}
@ -370,31 +372,33 @@ void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
return;
}
auto &http2conf = get_config()->http2;
// If connection-level window control is not enabled (e.g,
// spdy/3), spdylay_session_get_recv_data_length() is always
// returns 0.
if (spdylay_session_get_recv_data_length(session) >
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
1 << get_config()->http2_upstream_connection_window_bits)) {
1 << http2conf.upstream.connection_window_bits)) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream)
<< "Flow control error on connection: "
<< "recv_window_size="
<< spdylay_session_get_recv_data_length(session) << ", window_size="
<< (1 << get_config()->http2_upstream_connection_window_bits);
ULOG(INFO, upstream) << "Flow control error on connection: "
<< "recv_window_size="
<< spdylay_session_get_recv_data_length(session)
<< ", window_size="
<< (1 << http2conf.upstream.connection_window_bits);
}
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
return;
}
if (spdylay_session_get_stream_recv_data_length(session, stream_id) >
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
1 << get_config()->http2_upstream_window_bits)) {
1 << http2conf.upstream.window_bits)) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
<< spdylay_session_get_stream_recv_data_length(
session, stream_id)
<< ", initial_window_size="
<< (1 << get_config()->http2_upstream_window_bits);
<< (1 << http2conf.upstream.window_bits);
}
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
return;
@ -518,10 +522,12 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
&max_buffer, sizeof(max_buffer));
assert(rv == 0);
auto &http2conf = get_config()->http2;
if (version >= SPDYLAY_PROTO_SPDY3) {
int val = 1;
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(
session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val));
assert(rv == 0);
@ -532,7 +538,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
// TODO Maybe call from outside?
std::array<spdylay_settings_entry, 2> entry;
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[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
@ -544,8 +550,8 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
assert(rv == 0);
if (version >= SPDYLAY_PROTO_SPDY3_1 &&
get_config()->http2_upstream_connection_window_bits > 16) {
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) -
http2conf.upstream.connection_window_bits > 16) {
int32_t delta = (1 << http2conf.upstream.connection_window_bits) -
SPDYLAY_INITIAL_WINDOW_SIZE;
rv = spdylay_submit_window_update(session_, 0, delta);
assert(rv == 0);
@ -875,7 +881,7 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_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);
@ -919,7 +925,7 @@ int SpdyUpstream::error_reply(Downstream *downstream,
std::string status_string = http2::get_status_string(status_code);
const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1",
"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",
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";
}
auto &httpconf = get_config()->http;
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);
}
// 8 means server, :status, :version and possible via header field.
auto nv = make_unique<const char *[]>(
resp.fs.headers().size() * 2 + 8 +
get_config()->add_response_headers.size() * 2 + 1);
auto nv =
make_unique<const char *[]>(resp.fs.headers().size() * 2 + 8 +
httpconf.add_response_headers.size() * 2 + 1);
size_t hdidx = 0;
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) {
nv[hdidx++] = "server";
nv[hdidx++] = get_config()->server_name.c_str();
nv[hdidx++] = httpconf.server_name.c_str();
} else {
auto server = resp.fs.header(http2::HD_SERVER);
if (server) {
@ -1044,7 +1052,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
}
auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
nv[hdidx++] = "via";
nv[hdidx++] = via->value.c_str();
@ -1060,7 +1068,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
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.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) {
auto n = get_config()->http2_downstream_connections_per_worker;
auto n = get_config()->http2.downstream.connections_per_worker;
size_t group = 0;
for (auto &dgrp : dgrps_) {
auto m = n;