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",
"frontend-http2-settings-timeout",
"backend-http2-settings-timeout",
"api-max-request-body",
]
LOGVARS = [

View File

@ -1183,6 +1183,9 @@ void fill_default_config() {
downstreamconf.response_buffer_size = 128_k;
downstreamconf.family = AF_UNSPEC;
}
auto &apiconf = mod_config()->api;
apiconf.max_request_body = 16_k;
}
} // namespace
@ -1914,6 +1917,12 @@ HTTP:
HTTP status code. If error status code comes from
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:
--frontend-http2-dump-request-header=<PATH>
Dumps request headers received by HTTP/2 frontend to the
@ -2447,6 +2456,7 @@ int main(int argc, char **argv) {
&flag, 124},
{SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument,
&flag, 125},
{SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126},
{nullptr, 0, nullptr, 0}};
int option_index = 0;
@ -3036,6 +3046,10 @@ int main(int argc, char **argv) {
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT,
StringRef{optarg});
break;
case 126:
// --api-max-request-body
cmdcfgs.emplace_back(SHRPX_OPT_API_MAX_REQUEST_BODY, StringRef{optarg});
break;
default:
break;
}

View File

@ -87,6 +87,15 @@ int APIDownstreamConnection::push_request_headers() {
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;
}
@ -98,7 +107,15 @@ int APIDownstreamConnection::push_upload_data_chunk(const uint8_t *data,
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);
// 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();
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 error_body = StringRef::from_lit("400 Bad Request");
@ -127,6 +144,19 @@ int APIDownstreamConnection::end_upload_data() {
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.conn.downstream = std::make_shared<DownstreamConfig>();
const auto &downstreamconf = config.conn.downstream;

View File

@ -915,6 +915,7 @@ enum {
SHRPX_OPTID_ADD_RESPONSE_HEADER,
SHRPX_OPTID_ADD_X_FORWARDED_FOR,
SHRPX_OPTID_ALTSVC,
SHRPX_OPTID_API_MAX_REQUEST_BODY,
SHRPX_OPTID_BACKEND,
SHRPX_OPTID_BACKEND_ADDRESS_FAMILY,
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;
}
break;
case 'y':
if (util::strieq_l("api-max-request-bod", name, 19)) {
return SHRPX_OPTID_API_MAX_REQUEST_BODY;
}
break;
}
break;
case 21:
@ -2712,6 +2718,8 @@ int parse_config(Config *config, const StringRef &opt, const StringRef &optarg,
case SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT:
return parse_duration(&config->http2.downstream.timeout.settings, opt,
optarg);
case SHRPX_OPTID_API_MAX_REQUEST_BODY:
return parse_uint_with_unit(&config->api.max_request_body, opt, optarg);
case SHRPX_OPTID_CONF:
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");
constexpr auto SHRPX_OPT_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;
@ -649,6 +651,11 @@ struct ConnectionConfig {
std::shared_ptr<DownstreamConfig> downstream;
};
struct APIConfig {
// Maximum request body size for one API request
size_t max_request_body;
};
struct Config {
HttpProxy downstream_http_proxy;
HttpConfig http;
@ -656,6 +663,7 @@ struct Config {
TLSConfig tls;
LoggingConfig logging;
ConnectionConfig conn;
APIConfig api;
ImmutableString pid_file;
ImmutableString conf_path;
ImmutableString user;