<status>Extension</status>
<sourcefile>mod_reqtimeout.c</sourcefile>
<identifier>reqtimeout_module</identifier>
-<compatibility>Available in Apache 2.2.15 and later</compatibility>
+<compatibility>Available in Apache HTTPD 2.2.15 and later</compatibility>
<section id="examples"><title>Examples</title>
<description>Set timeout values for receiving request headers and body from client.
</description>
<syntax>RequestReadTimeout
-[header=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>]
-[body=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>]
+[header=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>]
+[body=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>]
</syntax>
-<default>Unset; no limit</default>
+<default>header=20-40,MinRate=500 body=20,MinRate=500</default>
<contextlist><context>server config</context><context>virtual host</context>
</contextlist>
+<compatibility>Available in version 2.2.15 and later; defaulted to disabled in
+version 2.3.14 and earlier.</compatibility>
<usage>
<p>This directive can set various timeouts for receiving the request headers
body, respectively. A value of 0 means no limit.</p>
</li>
+ <li><strong>Disable module for a vhost:</strong>:<br />
+
+ <example>header=0 body=0</example>
+
+ <p>This disables <module>mod_reqtimeout</module> completely.</p>
+ </li>
+
<li><strong>Timeout value that is increased when data is
received</strong>:<br />
<example>
module AP_MODULE_DECLARE_DATA reqtimeout_module;
+#define UNSET -1
+#define MRT_DEFAULT_HEADER_TIMEOUT 20
+#define MRT_DEFAULT_HEADER_MAX_TIMEOUT 40
+#define MRT_DEFAULT_HEADER_MIN_RATE 500
+#define MRT_DEFAULT_BODY_TIMEOUT 20
+#define MRT_DEFAULT_BODY_MAX_TIMEOUT 0
+#define MRT_DEFAULT_BODY_MIN_RATE 500
+
typedef struct
{
int header_timeout; /* timeout for reading the req hdrs in secs */
} reqtimeout_con_cfg;
static const char *const reqtimeout_filter_name = "reqtimeout";
+static int default_header_rate_factor;
+static int default_body_rate_factor;
static void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb)
{
apr_time_t time_left;
apr_time_t now;
apr_status_t rv;
- apr_interval_time_t saved_sock_timeout = -1;
+ apr_interval_time_t saved_sock_timeout = UNSET;
reqtimeout_con_cfg *ccfg = f->ctx;
if (ccfg->in_keep_alive) {
cfg = ap_get_module_config(c->base_server->module_config,
&reqtimeout_module);
AP_DEBUG_ASSERT(cfg != NULL);
- if (cfg->header_timeout <= 0 && cfg->body_timeout <= 0) {
- /* not configured for this vhost */
+ if (cfg->header_timeout == 0 && cfg->body_timeout == 0) {
+ /* disabled for this vhost */
return DECLINED;
}
ccfg = apr_pcalloc(c->pool, sizeof(reqtimeout_con_cfg));
- ccfg->new_timeout = cfg->header_timeout;
- ccfg->new_max_timeout = cfg->header_max_timeout;
ccfg->type = "header";
- ccfg->min_rate = cfg->header_min_rate;
- ccfg->rate_factor = cfg->header_rate_factor;
+ if (cfg->header_timeout != UNSET) {
+ ccfg->new_timeout = cfg->header_timeout;
+ ccfg->new_max_timeout = cfg->header_max_timeout;
+ ccfg->min_rate = cfg->header_min_rate;
+ ccfg->rate_factor = cfg->header_rate_factor;
+ }
+ else {
+ ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT;
+ ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT;
+ ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE;
+ ccfg->rate_factor = default_header_rate_factor;
+ }
ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg);
ap_add_input_filter("reqtimeout", ccfg, NULL, c);
reqtimeout_con_cfg *ccfg =
ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
- if (ccfg == NULL) {
- /* not configured for this connection */
+ if (ccfg == NULL || r->method_number == M_CONNECT) {
+ /* either disabled for this connection or a CONNECT request */
return OK;
}
-
cfg = ap_get_module_config(r->connection->base_server->module_config,
&reqtimeout_module);
AP_DEBUG_ASSERT(cfg != NULL);
ccfg->timeout_at = 0;
ccfg->max_timeout_at = 0;
- if (r->method_number != M_CONNECT) {
- ccfg->new_timeout = cfg->body_timeout;
+ ccfg->type = "body";
+ if (cfg->body_timeout != UNSET) {
+ ccfg->new_timeout = cfg->body_timeout;
ccfg->new_max_timeout = cfg->body_max_timeout;
- ccfg->min_rate = cfg->body_min_rate;
- ccfg->rate_factor = cfg->body_rate_factor;
- ccfg->type = "body";
+ ccfg->min_rate = cfg->body_min_rate;
+ ccfg->rate_factor = cfg->body_rate_factor;
+ }
+ else {
+ ccfg->new_timeout = MRT_DEFAULT_BODY_TIMEOUT;
+ ccfg->new_max_timeout = MRT_DEFAULT_BODY_MAX_TIMEOUT;
+ ccfg->min_rate = MRT_DEFAULT_BODY_MIN_RATE;
+ ccfg->rate_factor = default_body_rate_factor;
}
-
return OK;
}
ccfg->timeout_at = 0;
ccfg->max_timeout_at = 0;
ccfg->in_keep_alive = 1;
- ccfg->new_timeout = cfg->header_timeout;
- ccfg->new_max_timeout = cfg->header_max_timeout;
- ccfg->min_rate = cfg->header_min_rate;
- ccfg->rate_factor = cfg->header_rate_factor;
-
ccfg->type = "header";
+ if (ccfg->new_timeout != UNSET) {
+ ccfg->new_timeout = cfg->header_timeout;
+ ccfg->new_max_timeout = cfg->header_max_timeout;
+ ccfg->min_rate = cfg->header_min_rate;
+ ccfg->rate_factor = cfg->header_rate_factor;
+ }
+ else {
+ ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT;
+ ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT;
+ ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE;
+ ccfg->rate_factor = default_header_rate_factor;
+ }
return OK;
}
{
reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
- cfg->header_timeout = -1;
- cfg->header_max_timeout = -1;
- cfg->header_min_rate = -1;
- cfg->body_timeout = -1;
- cfg->body_max_timeout = -1;
- cfg->body_min_rate = -1;
+ cfg->header_timeout = UNSET;
+ cfg->header_max_timeout = UNSET;
+ cfg->header_min_rate = UNSET;
+ cfg->body_timeout = UNSET;
+ cfg->body_max_timeout = UNSET;
+ cfg->body_min_rate = UNSET;
return cfg;
}
-#define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == -1) ? b->val : a->val;
+#define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == UNSET) ? b->val : a->val;
static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_)
{
reqtimeout_srv_cfg *base = base_;
MERGE_INT(cfg, base, add, body_max_timeout);
MERGE_INT(cfg, base, add, body_min_rate);
- cfg->header_rate_factor = (cfg->header_min_rate == -1) ? base->header_rate_factor :
- add->header_rate_factor;
- cfg->body_rate_factor = (cfg->body_min_rate == -1) ? base->body_rate_factor :
- add->body_rate_factor;
-
+ cfg->header_rate_factor = (cfg->header_min_rate == UNSET) ?
+ base->header_rate_factor : add->header_rate_factor;
+ cfg->body_rate_factor = (cfg->body_min_rate == UNSET) ?
+ base->body_rate_factor : add->body_rate_factor;
return cfg;
}
APR_HOOK_MIDDLE);
ap_hook_log_transaction(reqtimeout_after_body, NULL, NULL,
APR_HOOK_MIDDLE);
+
+#if MRT_DEFAULT_HEADER_MIN_RATE > 0
+ default_header_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_HEADER_MIN_RATE;
+#endif
+#if MRT_DEFAULT_BODY_MIN_RATE > 0
+ default_body_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_BODY_MIN_RATE;
+#endif
}
static const command_rec reqtimeout_cmds[] = {