From: Stefan Fritsch Date: Sun, 28 Feb 2010 17:25:44 +0000 (+0000) Subject: Backport mod_reqtimeout from trunk. X-Git-Tag: 2.2.15~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7be672482c29676b595993e30524645f9b2b39e2;p=thirdparty%2Fapache%2Fhttpd.git Backport mod_reqtimeout from trunk. Reviewed by: sf, jorton, rjung To take trawick's comment into account, I have changed enabled=yes into enabled=most. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@917211 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/Apache.dsw b/Apache.dsw index 7f07e53a317..d48fdd291e5 100644 --- a/Apache.dsw +++ b/Apache.dsw @@ -249,6 +249,9 @@ Package=<4> Project_Dep_Name mod_proxy_http End Project Dependency Begin Project Dependency + Project_Dep_Name mod_reqtimeout + End Project Dependency + Begin Project Dependency Project_Dep_Name mod_rewrite End Project Dependency Begin Project Dependency @@ -2181,6 +2184,27 @@ Package=<4> ############################################################################### +Project: "mod_reqtimeout"=.\modules\filters\mod_reqtimeout.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libapr + End Project Dependency + Begin Project Dependency + Project_Dep_Name libaprutil + End Project Dependency + Begin Project Dependency + Project_Dep_Name libhttpd + End Project Dependency +}}} + +############################################################################### + Project: "mod_rewrite"=.\modules\mappers\mod_rewrite.dsp - Package Owner=<4> Package=<5> diff --git a/CHANGES b/CHANGES index e7a2b9750ae..6ffa7215d69 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,9 @@ Changes with Apache 2.2.15 access control is still vulnerable, unless using OpenSSL >= 0.9.8l. [Joe Orton, Ruediger Pluem, Hartmut Keil ] + *) mod_reqtimeout: New module to set timeouts and minimum data rates for + receiving requests from the client. [Stefan Fritsch] + *) mod_proxy_ajp: Really regard the operation a success, when the client aborted the connection. In addition adjust the log message if the client aborted the connection. [Ruediger Pluem] diff --git a/Makefile.win b/Makefile.win index 5dbb85a3d25..f2ec733258a 100644 --- a/Makefile.win +++ b/Makefile.win @@ -355,6 +355,7 @@ _build: $(MAKE) $(MAKEOPT) -f mod_ext_filter.mak CFG="mod_ext_filter - Win32 $(LONG)" RECURSE=0 $(CTARGET) $(MAKE) $(MAKEOPT) -f mod_filter.mak CFG="mod_filter - Win32 $(LONG)" RECURSE=0 $(CTARGET) $(MAKE) $(MAKEOPT) -f mod_include.mak CFG="mod_include - Win32 $(LONG)" RECURSE=0 $(CTARGET) + $(MAKE) $(MAKEOPT) -f mod_reqtimeout.mak CFG="mod_reqtimeout - Win32 $(LONG)" RECURSE=0 $(CTARGET) $(MAKE) $(MAKEOPT) -f mod_substitute.mak CFG="mod_substitute - Win32 $(LONG)" RECURSE=0 $(CTARGET) cd ..\.. cd modules\generators @@ -542,6 +543,7 @@ _copybin: copy modules\filters\$(LONG)\mod_ext_filter.$(src_so) "$(inst_so)" <.y copy modules\filters\$(LONG)\mod_filter.$(src_so) "$(inst_so)" <.y copy modules\filters\$(LONG)\mod_include.$(src_so) "$(inst_so)" <.y + copy modules\filters\$(LONG)\mod_reqtimeout.$(src_so) "$(inst_so)" <.y copy modules\filters\$(LONG)\mod_substitute.$(src_so) "$(inst_so)" <.y copy modules\generators\$(LONG)\mod_asis.$(src_so) "$(inst_so)" <.y copy modules\generators\$(LONG)\mod_autoindex.$(src_so) "$(inst_so)" <.y diff --git a/STATUS b/STATUS index ef9af7308fd..4f818d9ea4d 100644 --- a/STATUS +++ b/STATUS @@ -101,32 +101,6 @@ PATCHES PROPOSED TO BACKPORT FROM TRUNK: sf: Couldn't the linux 2.4 bug be worked around by calling access twice? Once with R_OK and once with X_OK. - * mod_reqtimeout: New module to limit time waiting for requests from clients. - Backport current version from trunk. - Trunk Patch: http://svn.apache.org/viewvc?rev=821591&view=rev - http://svn.apache.org/viewvc?rev=821792&view=rev - http://svn.apache.org/viewvc?rev=821990&view=rev - http://svn.apache.org/viewvc?rev=822509&view=rev - http://svn.apache.org/viewvc?rev=822857&view=rev - http://svn.apache.org/viewvc?rev=825177&view=rev - http://svn.apache.org/viewvc?rev=834499&view=rev - http://svn.apache.org/viewvc?rev=885121&view=rev - http://svn.apache.org/viewvc?rev=900018&view=rev - http://svn.apache.org/viewvc?rev=902434&view=rev - http://svn.apache.org/viewvc?rev=902593&view=rev - http://svn.apache.org/viewvc?rev=916866&view=rev - http://svn.apache.org/viewvc?rev=917151&view=rev - 2.2.x Patch: http://people.apache.org/~sf/mod_reqtimeout.2.2-v2.patch - http://people.apache.org/~sf/mod_reqtimeout.2.2-windows-build.patch - http://svn.apache.org/viewvc?rev=917151&view=rev - +1: sf, jorton, rjung - trawick: combo of Status=Experimental/enabled=yes seems strange, - sf: I am fine with any other combination of Status/enabled. - rjung: mod_substitute as another recent example started its 2.2.x - life with status "Extension" and enabled "most" and an additional - docs comment about being experimental (see r602738). I'm fine with - either result. - * Ensure each subrequest has a shallow copy of headers_in so that the parent request headers are not corrupted. Eliminates a problematic optimization in the case of no request body. PR 48359 diff --git a/build/installwinconf.awk b/build/installwinconf.awk index 8ca7554d9ce..d23d7f7f17b 100644 --- a/build/installwinconf.awk +++ b/build/installwinconf.awk @@ -147,6 +147,7 @@ BEGIN { print "#LoadModule proxy_connect_module modules/mod_proxy_connect.so" > dstfl; print "#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so" > dstfl; print "#LoadModule proxy_http_module modules/mod_proxy_http.so" > dstfl; + print "#LoadModule reqtimeout_module modules/mod_reqtimeout.so" > dstfl; print "#LoadModule rewrite_module modules/mod_rewrite.so" > dstfl; print "LoadModule setenvif_module modules/mod_setenvif.so" > dstfl; print "#LoadModule speling_module modules/mod_speling.so" > dstfl; diff --git a/docs/manual/mod/allmodules.xml b/docs/manual/mod/allmodules.xml index eb817961c78..ccab58ed44e 100644 --- a/docs/manual/mod/allmodules.xml +++ b/docs/manual/mod/allmodules.xml @@ -64,6 +64,7 @@ mod_proxy_ftp.xml mod_proxy_http.xml mod_proxy_scgi.xml + mod_reqtimeout.xml mod_rewrite.xml mod_setenvif.xml mod_so.xml diff --git a/docs/manual/mod/mod_reqtimeout.xml b/docs/manual/mod/mod_reqtimeout.xml new file mode 100644 index 00000000000..ca71cc1547f --- /dev/null +++ b/docs/manual/mod/mod_reqtimeout.xml @@ -0,0 +1,141 @@ + + + + + + + + + +mod_reqtimeout +Set timeout and minimum data rate for receiving requests + +Experimental +mod_reqtimeout.c +reqtimeout_module +Available in Apache 2.2.15 and later + +
Examples + +
    +
  1. + Allow 10 seconds to receive the request including the headers and + 30 seconds for receiving the request body: + + + RequestReadTimeout header=10 body=30 + +
  2. + +
  3. + Allow at least 10 seconds to receive the request body. + If the client sends data, increase the timeout by 1 second for every + 1000 bytes received, with no upper limit for the timeout (exept for + the limit given indirectly by + LimitRequestBody): + + + RequestReadTimeout body=10,MinRate=1000 + +
  4. + +
  5. + Allow at least 10 seconds to receive the request including the headers. + If the client sends data, increase the timeout by 1 second for every + 500 bytes received. But do not allow more than 30 seconds for the + request including the headers: + + + RequestReadTimeout header=10-30,MinRate=500 + +
  6. + +
+
+ + +RequestReadTimeout +Set timeout values for receiving request headers and body from client. + +RequestReadTimeout +[header=timeout[[-maxtimeout],MinRate=rate] +[body=timeout[[-maxtimeout],MinRate=rate] + +Unset; no limit +server configvirtual host + + + +

This directive can set various timeouts for receiving the request headers + and the request body from the client. If the client fails to send headers or + body within the configured time, a 408 REQUEST TIME OUT error + is sent.

+ +

For SSL virtual hosts, the header timeout values include the time needed + to do the initial SSL handshake. The body timeout values include the time + needed for SSL renegotiation (if necessary).

+ +

When an AcceptFilter is in use + (usually the case on Linux and FreeBSD), the socket is not sent to the + server process before at least one byte (or the whole request for + httpready) is received. The header timeout configured with + RequestReadTimeout is only effective after the server process has + received the socket.

+ +

For each of the two timeout types (header or body), there are three ways + to specify the timeout: +

+ +
    + +
  • Fixed timeout value:
    + + type=timeout + +

    The time in seconds allowed for reading all of the request headers or + body, respectively. A value of 0 means no limit.

    +
  • + +
  • Timeout value that is increased when data is + received:
    + + type=timeout,MinRate=data_rate + + +

    Same as above, but whenever data is received, the timeout value is + increased according to the specified minimum data rate (in bytes per + second).

    +
  • + +
  • Timeout value that is increased when data is received, with an + upper bound:
    + + type=timeout-maxtimeout,MinRate=data_rate + + +

    Same as above, but the timeout will not be increased above the second + value of the specified timeout range.

    +
  • + +
+ +
+ +
+ +
diff --git a/docs/manual/mod/mod_reqtimeout.xml.meta b/docs/manual/mod/mod_reqtimeout.xml.meta new file mode 100644 index 00000000000..42accd8f965 --- /dev/null +++ b/docs/manual/mod/mod_reqtimeout.xml.meta @@ -0,0 +1,12 @@ + + + + + mod_reqtimeout + /mod/ + .. + + + en + + diff --git a/modules/filters/config.m4 b/modules/filters/config.m4 index 9c1f608350a..247d4f65a33 100644 --- a/modules/filters/config.m4 +++ b/modules/filters/config.m4 @@ -4,6 +4,7 @@ dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]]) APACHE_MODPATH_INIT(filters) +APACHE_MODULE(reqtimeout, Limit time waiting for request from client, , , most) APACHE_MODULE(ext_filter, external filter module, , , most) APACHE_MODULE(include, Server Side Includes, , , yes) APACHE_MODULE(filter, Smart Filtering, , , yes) diff --git a/modules/filters/mod_reqtimeout.c b/modules/filters/mod_reqtimeout.c new file mode 100644 index 00000000000..215a04c0f81 --- /dev/null +++ b/modules/filters/mod_reqtimeout.c @@ -0,0 +1,431 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_connection.h" +#include "http_protocol.h" +#include "http_log.h" +#include "util_filter.h" +#define APR_WANT_STRFUNC +#include "apr_strings.h" + +module AP_MODULE_DECLARE_DATA reqtimeout_module; + +typedef struct +{ + int header_timeout; /* timeout for reading the req hdrs in secs */ + int header_max_timeout; /* max timeout for req hdrs in secs */ + int header_min_rate; /* min rate for reading req hdrs in bytes/s */ + apr_time_t header_rate_factor; + int body_timeout; /* timeout for reading the req body in secs */ + int body_max_timeout; /* max timeout for req body in secs */ + int body_min_rate; /* timeout for reading the req body in secs */ + apr_time_t body_rate_factor; +} reqtimeout_srv_cfg; + +typedef struct +{ + apr_time_t timeout_at; + apr_time_t max_timeout_at; + int min_rate; + int new_timeout; + int new_max_timeout; + int in_keep_alive; + char *type; + apr_time_t rate_factor; +} reqtimeout_con_cfg; + +typedef struct +{ + apr_socket_t *socket; +} reqtimeout_ctx; + +static const char *const reqtimeout_filter_name = "reqtimeout"; + +static void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb) +{ + apr_off_t len; + apr_time_t new_timeout_at; + + if (apr_brigade_length(bb, 0, &len) != APR_SUCCESS || len <= 0) + return; + + new_timeout_at = ccfg->timeout_at + len * ccfg->rate_factor; + if (ccfg->max_timeout_at > 0 && new_timeout_at > ccfg->max_timeout_at) { + ccfg->timeout_at = ccfg->max_timeout_at; + } + else { + ccfg->timeout_at = new_timeout_at; + } +} + +static apr_status_t reqtimeout_filter(ap_filter_t *f, + apr_bucket_brigade *bb, + ap_input_mode_t mode, + apr_read_type_e block, + apr_off_t readbytes) +{ + reqtimeout_ctx *ctx; + apr_time_t time_left; + apr_time_t now; + apr_status_t rv; + apr_interval_time_t saved_sock_timeout = -1; + reqtimeout_con_cfg *ccfg; + + ctx = f->ctx; + AP_DEBUG_ASSERT(ctx != NULL); + + ccfg = ap_get_module_config(f->c->conn_config, &reqtimeout_module); + AP_DEBUG_ASSERT(ccfg != NULL); + + if (ccfg->in_keep_alive) { + /* For this read, the normal keep-alive timeout must be used */ + ccfg->in_keep_alive = 0; + return ap_get_brigade(f->next, bb, mode, block, readbytes); + } + + now = apr_time_now(); + if (ccfg->new_timeout > 0) { + /* set new timeout */ + ccfg->timeout_at = now + apr_time_from_sec(ccfg->new_timeout); + ccfg->new_timeout = 0; + if (ccfg->new_max_timeout > 0) { + ccfg->max_timeout_at = now + apr_time_from_sec(ccfg->new_max_timeout); + ccfg->new_max_timeout = 0; + } + } + else if (ccfg->timeout_at == 0) { + /* no timeout set */ + return ap_get_brigade(f->next, bb, mode, block, readbytes); + } + + time_left = ccfg->timeout_at - now; + if (time_left <= 0) { + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, + "Request %s read timeout", ccfg->type); + return APR_TIMEUP; + } + + if (block == APR_NONBLOCK_READ || mode == AP_MODE_INIT + || mode == AP_MODE_EATCRLF) { + rv = ap_get_brigade(f->next, bb, mode, block, readbytes); + if (ccfg->min_rate > 0 && rv == APR_SUCCESS) { + extend_timeout(ccfg, bb); + } + return rv; + } + + if (time_left < apr_time_from_sec(1)) { + time_left = apr_time_from_sec(1); + } + + rv = apr_socket_timeout_get(ctx->socket, &saved_sock_timeout); + AP_DEBUG_ASSERT(rv == APR_SUCCESS); + + if (saved_sock_timeout >= time_left) { + rv = apr_socket_timeout_set(ctx->socket, time_left); + AP_DEBUG_ASSERT(rv == APR_SUCCESS); + } + else { + saved_sock_timeout = -1; + } + + rv = ap_get_brigade(f->next, bb, mode, block, readbytes); + + if (saved_sock_timeout != -1) { + apr_socket_timeout_set(ctx->socket, saved_sock_timeout); + } + + if (ccfg->min_rate > 0 && rv == APR_SUCCESS) { + extend_timeout(ccfg, bb); + } + + if (rv == APR_TIMEUP) { + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, + "Request %s read timeout", ccfg->type); + } + return rv; +} + +static int reqtimeout_pre_conn(conn_rec *c, void *csd) +{ + reqtimeout_ctx *ctx; + reqtimeout_con_cfg *ccfg; + reqtimeout_srv_cfg *cfg; + + 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 */ + return OK; + } + + ctx = apr_pcalloc(c->pool, sizeof(reqtimeout_ctx)); + ctx->socket = csd; + + 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; + ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg); + + ap_add_input_filter("reqtimeout", ctx, NULL, c); + return OK; +} + +static int reqtimeout_after_headers(request_rec *r) +{ + reqtimeout_srv_cfg *cfg; + reqtimeout_con_cfg *ccfg = + ap_get_module_config(r->connection->conn_config, &reqtimeout_module); + + if (ccfg == NULL) { + /* not configured for this vhost */ + 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; + 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"; + + return OK; +} + +static int reqtimeout_after_body(request_rec *r) +{ + reqtimeout_srv_cfg *cfg; + reqtimeout_con_cfg *ccfg = + ap_get_module_config(r->connection->conn_config, &reqtimeout_module); + + if (ccfg == NULL) { + /* not configured for this vhost */ + 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; + 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"; + + return OK; +} + +static void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s) +{ + 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; + + return cfg; +} + +#define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == -1) ? b->val : a->val; +static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_) +{ + reqtimeout_srv_cfg *base = base_; + reqtimeout_srv_cfg *add = add_; + reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg)); + + MERGE_INT(cfg, base, add, header_timeout); + MERGE_INT(cfg, base, add, header_max_timeout); + MERGE_INT(cfg, base, add, header_min_rate); + MERGE_INT(cfg, base, add, body_timeout); + 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; + + return cfg; +} + +static const char *parse_int(apr_pool_t *p, const char *arg, int *val) { + char *endptr; + *val = strtol(arg, &endptr, 10); + + if (arg == endptr) { + return apr_psprintf(p, "Value '%s' not numerical", endptr); + } + if (*endptr != '\0') { + return apr_psprintf(p, "Cannot parse '%s'", endptr); + } + if (*val < 0) { + return "Value must be non-negative"; + } + return NULL; +} + +static const char *set_reqtimeout_param(reqtimeout_srv_cfg *conf, + apr_pool_t *p, + const char *key, + const char *val) +{ + const char *ret = NULL; + char *rate_str = NULL, *initial_str, *max_str = NULL; + int rate = 0, initial = 0, max = 0; + enum { PARAM_HEADER, PARAM_BODY } type; + + if (!strcasecmp(key, "header")) { + type = PARAM_HEADER; + } + else if (!strcasecmp(key, "body")) { + type = PARAM_BODY; + } + else { + return "Unknown RequestReadTimeout parameter"; + } + + if ((rate_str = ap_strcasestr(val, ",minrate="))) { + initial_str = apr_pstrndup(p, val, rate_str - val); + rate_str += strlen(",minrate="); + ret = parse_int(p, rate_str, &rate); + if (ret) + return ret; + + if (rate == 0) + return "Minimum data rate must be larger than 0"; + + if ((max_str = strchr(initial_str, '-'))) { + *max_str++ = '\0'; + ret = parse_int(p, max_str, &max); + if (ret) + return ret; + } + + ret = parse_int(p, initial_str, &initial); + } + else { + if (ap_strchr_c(val, '-')) + return "Must set MinRate option if using timeout range"; + ret = parse_int(p, val, &initial); + } + + if (ret) + return ret; + + if (max && initial >= max) { + return "Maximum timeout must be larger than initial timeout"; + } + + if (type == PARAM_HEADER) { + conf->header_timeout = initial; + conf->header_max_timeout = max; + conf->header_min_rate = rate; + if (rate) + conf->header_rate_factor = apr_time_from_sec(1) / rate; + } + else { + conf->body_timeout = initial; + conf->body_max_timeout = max; + conf->body_min_rate = rate; + if (rate) + conf->body_rate_factor = apr_time_from_sec(1) / rate; + } + return ret; +} + +static const char *set_reqtimeouts(cmd_parms *cmd, void *mconfig, + const char *arg) +{ + reqtimeout_srv_cfg *conf = + ap_get_module_config(cmd->server->module_config, + &reqtimeout_module); + + while (*arg) { + char *word, *val; + const char *err; + + word = ap_getword_conf(cmd->pool, &arg); + val = strchr(word, '='); + if (!val) { + return "Invalid RequestReadTimeout parameter. Parameter must be " + "in the form 'key=value'"; + } + else + *val++ = '\0'; + + err = set_reqtimeout_param(conf, cmd->pool, word, val); + + if (err) + return apr_psprintf(cmd->temp_pool, "RequestReadTimeout: %s=%s: %s", + word, val, err); + } + + return NULL; + +} + +static void reqtimeout_hooks(apr_pool_t *pool) +{ + /* + * mod_ssl is AP_FTYPE_CONNECTION + 5 and mod_reqtimeout needs to + * be called before mod_ssl. Otherwise repeated reads during the ssl + * handshake can prevent the timeout from triggering. + */ + ap_register_input_filter(reqtimeout_filter_name, reqtimeout_filter, NULL, + AP_FTYPE_CONNECTION + 8); + ap_hook_pre_connection(reqtimeout_pre_conn, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_post_read_request(reqtimeout_after_headers, NULL, NULL, + APR_HOOK_MIDDLE); + ap_hook_log_transaction(reqtimeout_after_body, NULL, NULL, + APR_HOOK_MIDDLE); +} + +static const command_rec reqtimeout_cmds[] = { + AP_INIT_RAW_ARGS("RequestReadTimeout", set_reqtimeouts, NULL, RSRC_CONF, + "Set various timeout parameters for reading request " + "headers and body"), + {NULL} +}; + +module AP_MODULE_DECLARE_DATA reqtimeout_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + reqtimeout_create_srv_config, /* create per-server config structures */ + reqtimeout_merge_srv_config, /* merge per-server config structures */ + reqtimeout_cmds, /* table of config file commands */ + reqtimeout_hooks +}; diff --git a/modules/filters/mod_reqtimeout.dsp b/modules/filters/mod_reqtimeout.dsp new file mode 100644 index 00000000000..0afa4683ad7 --- /dev/null +++ b/modules/filters/mod_reqtimeout.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_reqtimeout" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=mod_reqtimeout - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mod_reqtimeout.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_reqtimeout.mak" CFG="mod_reqtimeout - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_reqtimeout - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_reqtimeout - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mod_reqtimeout - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_RL_DECLARE_EXPORT" /Fd"Release\mod_reqtimeout_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /fo"Release/mod_reqtimeout.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_reqtimeout.so" /d LONG_NAME="reqtimeout_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_reqtimeout.so" /base:@..\..\os\win32\BaseAddr.ref,mod_reqtimeout.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_reqtimeout.so" /base:@..\..\os\win32\BaseAddr.ref,mod_reqtimeout.so /opt:ref +# Begin Special Build Tool +TargetPath=.\Release\mod_reqtimeout.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "mod_reqtimeout - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_RL_DECLARE_EXPORT" /Fd"Debug\mod_reqtimeout_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"Debug/mod_reqtimeout.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_reqtimeout.so" /d LONG_NAME="reqtimeout_module for Apache" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_reqtimeout.so" /base:@..\..\os\win32\BaseAddr.ref,mod_reqtimeout.so +# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_reqtimeout.so" /base:@..\..\os\win32\BaseAddr.ref,mod_reqtimeout.so +# Begin Special Build Tool +TargetPath=.\Debug\mod_reqtimeout.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "mod_reqtimeout - Win32 Release" +# Name "mod_reqtimeout - Win32 Debug" +# Begin Source File + +SOURCE=.\mod_reqtimeout.c +# End Source File +# Begin Source File + +SOURCE=..\..\build\win32\httpd.rc +# End Source File +# End Target +# End Project diff --git a/os/win32/BaseAddr.ref b/os/win32/BaseAddr.ref index e6f05d61a13..5c555e6093f 100644 --- a/os/win32/BaseAddr.ref +++ b/os/win32/BaseAddr.ref @@ -81,3 +81,4 @@ mod_case_filter_in.so 0x6F9B0000 0x00010000 mod_filter.so 0x6F9A0000 0x00010000 mod_dav_lock.so 0x6F990000 0x00010000 mod_substitute.so 0x6F980000 0x00010000 +mod_reqtimeout.so 0x6F970000 0x00010000