nghttpx: Add --api-max-request-body option to set maximum API request body size

This commit is contained in:
Tatsuhiro Tsujikawa 2016-06-04 17:24:54 +09:00
parent 951ef0c6d5
commit 8288f5713b
5 changed files with 63 additions and 2 deletions

View File

@ -132,6 +132,7 @@ OPTIONS = [
"no-kqueue", "no-kqueue",
"frontend-http2-settings-timeout", "frontend-http2-settings-timeout",
"backend-http2-settings-timeout", "backend-http2-settings-timeout",
"api-max-request-body",
] ]
LOGVARS = [ LOGVARS = [

View File

@ -1183,6 +1183,9 @@ void fill_default_config() {
downstreamconf.response_buffer_size = 128_k; downstreamconf.response_buffer_size = 128_k;
downstreamconf.family = AF_UNSPEC; downstreamconf.family = AF_UNSPEC;
} }
auto &apiconf = mod_config()->api;
apiconf.max_request_body = 16_k;
} }
} // namespace } // namespace
@ -1914,6 +1917,12 @@ HTTP:
HTTP status code. If error status code comes from HTTP status code. If error status code comes from
backend server, the custom error pages are not used. backend server, the custom error pages are not used.
API:
--api-max-request-body=<SIZE>
Set the maximum size of request body for API request.
Default: )" << util::utos_unit(get_config()->api.max_request_body)
<< R"(
Debug: Debug:
--frontend-http2-dump-request-header=<PATH> --frontend-http2-dump-request-header=<PATH>
Dumps request headers received by HTTP/2 frontend to the Dumps request headers received by HTTP/2 frontend to the
@ -2447,6 +2456,7 @@ int main(int argc, char **argv) {
&flag, 124}, &flag, 124},
{SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument, {SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument,
&flag, 125}, &flag, 125},
{SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
@ -3036,6 +3046,10 @@ int main(int argc, char **argv) {
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT, cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT,
StringRef{optarg}); StringRef{optarg});
break; break;
case 126:
// --api-max-request-body
cmdcfgs.emplace_back(SHRPX_OPT_API_MAX_REQUEST_BODY, StringRef{optarg});
break;
default: default:
break; break;
} }

View File

@ -87,6 +87,15 @@ int APIDownstreamConnection::push_request_headers() {
return 0; return 0;
} }
// This works with req.fs.content_length == -1
if (req.fs.content_length >
static_cast<int64_t>(get_config()->api.max_request_body)) {
send_reply(
413, http2::get_status_string(downstream_->get_block_allocator(), 413));
return 0;
}
return 0; return 0;
} }
@ -98,7 +107,15 @@ int APIDownstreamConnection::push_upload_data_chunk(const uint8_t *data,
auto output = downstream_->get_request_buf(); auto output = downstream_->get_request_buf();
// TODO limit the maximum payload size auto &apiconf = get_config()->api;
if (output->rleft() + datalen > apiconf.max_request_body) {
send_reply(
413, http2::get_status_string(downstream_->get_block_allocator(), 413));
return 0;
}
output->append(data, datalen); output->append(data, datalen);
// We don't have to call Upstream::resume_read() here, because // We don't have to call Upstream::resume_read() here, because
@ -116,7 +133,7 @@ int APIDownstreamConnection::end_upload_data() {
auto output = downstream_->get_request_buf(); auto output = downstream_->get_request_buf();
struct iovec iov; struct iovec iov;
auto iovcnt = output->riovec(&iov, 1); auto iovcnt = output->riovec(&iov, 2);
constexpr auto body = StringRef::from_lit("200 OK"); constexpr auto body = StringRef::from_lit("200 OK");
constexpr auto error_body = StringRef::from_lit("400 Bad Request"); constexpr auto error_body = StringRef::from_lit("400 Bad Request");
@ -127,6 +144,19 @@ int APIDownstreamConnection::end_upload_data() {
return 0; return 0;
} }
std::unique_ptr<uint8_t[]> large_buf;
// If data spans in multiple chunks, pull them up into one
// contiguous buffer.
if (iovcnt > 1) {
large_buf = make_unique<uint8_t[]>(output->rleft());
auto len = output->rleft();
output->remove(large_buf.get(), len);
iov.iov_base = large_buf.get();
iov.iov_len = len;
}
Config config{}; Config config{};
config.conn.downstream = std::make_shared<DownstreamConfig>(); config.conn.downstream = std::make_shared<DownstreamConfig>();
const auto &downstreamconf = config.conn.downstream; const auto &downstreamconf = config.conn.downstream;

View File

@ -915,6 +915,7 @@ enum {
SHRPX_OPTID_ADD_RESPONSE_HEADER, SHRPX_OPTID_ADD_RESPONSE_HEADER,
SHRPX_OPTID_ADD_X_FORWARDED_FOR, SHRPX_OPTID_ADD_X_FORWARDED_FOR,
SHRPX_OPTID_ALTSVC, SHRPX_OPTID_ALTSVC,
SHRPX_OPTID_API_MAX_REQUEST_BODY,
SHRPX_OPTID_BACKEND, SHRPX_OPTID_BACKEND,
SHRPX_OPTID_BACKEND_ADDRESS_FAMILY, SHRPX_OPTID_BACKEND_ADDRESS_FAMILY,
SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND, SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND,
@ -1429,6 +1430,11 @@ int option_lookup_token(const char *name, size_t namelen) {
return SHRPX_OPTID_VERIFY_CLIENT_CACERT; return SHRPX_OPTID_VERIFY_CLIENT_CACERT;
} }
break; break;
case 'y':
if (util::strieq_l("api-max-request-bod", name, 19)) {
return SHRPX_OPTID_API_MAX_REQUEST_BODY;
}
break;
} }
break; break;
case 21: case 21:
@ -2712,6 +2718,8 @@ int parse_config(Config *config, const StringRef &opt, const StringRef &optarg,
case SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT: case SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT:
return parse_duration(&config->http2.downstream.timeout.settings, opt, return parse_duration(&config->http2.downstream.timeout.settings, opt,
optarg); optarg);
case SHRPX_OPTID_API_MAX_REQUEST_BODY:
return parse_uint_with_unit(&config->api.max_request_body, opt, optarg);
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";

View File

@ -280,6 +280,8 @@ constexpr auto SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT =
StringRef::from_lit("frontend-http2-settings-timeout"); StringRef::from_lit("frontend-http2-settings-timeout");
constexpr auto SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT = constexpr auto SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT =
StringRef::from_lit("backend-http2-settings-timeout"); StringRef::from_lit("backend-http2-settings-timeout");
constexpr auto SHRPX_OPT_API_MAX_REQUEST_BODY =
StringRef::from_lit("api-max-request-body");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -649,6 +651,11 @@ struct ConnectionConfig {
std::shared_ptr<DownstreamConfig> downstream; std::shared_ptr<DownstreamConfig> downstream;
}; };
struct APIConfig {
// Maximum request body size for one API request
size_t max_request_body;
};
struct Config { struct Config {
HttpProxy downstream_http_proxy; HttpProxy downstream_http_proxy;
HttpConfig http; HttpConfig http;
@ -656,6 +663,7 @@ struct Config {
TLSConfig tls; TLSConfig tls;
LoggingConfig logging; LoggingConfig logging;
ConnectionConfig conn; ConnectionConfig conn;
APIConfig api;
ImmutableString pid_file; ImmutableString pid_file;
ImmutableString conf_path; ImmutableString conf_path;
ImmutableString user; ImmutableString user;