nghttpx: Add --api-max-request-body option to set maximum API request body size
This commit is contained in:
parent
951ef0c6d5
commit
8288f5713b
|
@ -132,6 +132,7 @@ OPTIONS = [
|
|||
"no-kqueue",
|
||||
"frontend-http2-settings-timeout",
|
||||
"backend-http2-settings-timeout",
|
||||
"api-max-request-body",
|
||||
]
|
||||
|
||||
LOGVARS = [
|
||||
|
|
14
src/shrpx.cc
14
src/shrpx.cc
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue