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",
|
"no-kqueue",
|
||||||
"frontend-http2-settings-timeout",
|
"frontend-http2-settings-timeout",
|
||||||
"backend-http2-settings-timeout",
|
"backend-http2-settings-timeout",
|
||||||
|
"api-max-request-body",
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
|
|
14
src/shrpx.cc
14
src/shrpx.cc
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue