defer reading request body until handle subrequest

read request body in dynamic handlers supporting request body
(mod_cgi, mod_fastcgi, mod_proxy, mod_scgi, mod_webdav)

(In the future, each dynamic handler might choose whether or not to
 buffer request body or to stream request body to backend as request
 body is received.)

modify mod_webdav to mark request in handle_physical hook, and move
the main logic to handle_subrequest hook, where the main logic is
for other dynamic handlers.
This commit is contained in:
Glenn Strauss 2016-04-08 03:32:45 -04:00
parent 635ab6f802
commit 8f27ff8cd4
6 changed files with 86 additions and 11 deletions

View File

@ -1339,6 +1339,11 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) {
if (con->mode != p->id) return HANDLER_GO_ON;
if (NULL == hctx) return HANDLER_GO_ON;
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
if (-1 == hctx->fd) {
buffer *handler = cgi_get_handler(p->conf.cgi, con->physical.path);
if (!handler) return HANDLER_GO_ON; /*(should not happen; checked in cgi_is_handled())*/

View File

@ -3096,6 +3096,11 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
/* not my job */
if (con->mode != p->id) return HANDLER_GO_ON;
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
return (hctx->state != FCGI_STATE_READ)
? fcgi_send_request(srv, hctx)
: HANDLER_WAIT_FOR_EVENT;

View File

@ -908,6 +908,11 @@ SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
/* not my job */
if (con->mode != p->id) return HANDLER_GO_ON;
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
return (hctx->state != PROXY_STATE_READ)
? proxy_send_request(srv, hctx)
: HANDLER_WAIT_FOR_EVENT;

View File

@ -2453,6 +2453,11 @@ SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
/* not my job */
if (con->mode != p->id) return HANDLER_GO_ON;
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
return (hctx->state != FCGI_STATE_READ)
? scgi_send_request(srv, hctx)
: HANDLER_WAIT_FOR_EVENT;

View File

@ -4,6 +4,7 @@
#include "log.h"
#include "buffer.h"
#include "response.h"
#include "connections.h"
#include "plugin.h"
@ -1199,7 +1200,8 @@ static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer
return has_lock;
}
URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) {
plugin_data *p = p_d;
buffer *b;
DIR *dir;
@ -1250,6 +1252,11 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
if (con->request.content_length) {
xmlDocPtr xml;
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
xmlNode *rootnode = xmlDocGetRootElement(xml);
@ -1616,13 +1623,16 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
}
/* is a exclusive lock set on the source */
if (!webdav_has_lock(srv, con, p, con->uri.path)) {
/* (check for lock once before potentially reading large input) */
if (0 == cq->bytes_in && !webdav_has_lock(srv, con, p, con->uri.path)) {
con->http_status = 423;
return HANDLER_FINISHED;
}
assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
/* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
* - most important Content-Range
@ -2054,6 +2064,11 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
if (con->request.content_length) {
xmlDocPtr xml;
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
xmlNode *rootnode = xmlDocGetRootElement(xml);
@ -2210,6 +2225,11 @@ propmatch_cleanup:
xmlDocPtr xml;
buffer *hdr_if = NULL;
if (con->state == CON_STATE_READ_POST) {
handler_t r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
hdr_if = ds->value;
}
@ -2482,6 +2502,46 @@ propmatch_cleanup:
}
SUBREQUEST_FUNC(mod_webdav_subrequest_handler) {
handler_t r;
plugin_data *p = p_d;
if (con->mode != p->id) return HANDLER_GO_ON;
r = mod_webdav_subrequest_handler_huge(srv, con, p_d);
if (con->http_status >= 400) con->mode = DIRECT;
return r;
}
PHYSICALPATH_FUNC(mod_webdav_physical_handler) {
plugin_data *p = p_d;
if (!p->conf.enabled) return HANDLER_GO_ON;
/* physical path is setup */
if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
UNUSED(srv);
switch (con->request.http_method) {
case HTTP_METHOD_PROPFIND:
case HTTP_METHOD_PROPPATCH:
case HTTP_METHOD_PUT:
case HTTP_METHOD_COPY:
case HTTP_METHOD_MOVE:
case HTTP_METHOD_MKCOL:
case HTTP_METHOD_DELETE:
case HTTP_METHOD_LOCK:
case HTTP_METHOD_UNLOCK:
con->mode = p->id;
break;
default:
break;
}
return HANDLER_GO_ON;
}
/* this function is called at dlopen() time and inits the callbacks */
int mod_webdav_plugin_init(plugin *p);
@ -2491,7 +2551,8 @@ int mod_webdav_plugin_init(plugin *p) {
p->init = mod_webdav_init;
p->handle_uri_clean = mod_webdav_uri_handler;
p->handle_physical = mod_webdav_subrequest_handler;
p->handle_physical = mod_webdav_physical_handler;
p->handle_subrequest = mod_webdav_subrequest_handler;
p->set_defaults = mod_webdav_set_defaults;
p->cleanup = mod_webdav_free;

View File

@ -7,7 +7,6 @@
#include "chunk.h"
#include "configfile.h"
#include "connections.h"
#include "plugin.h"
@ -750,11 +749,6 @@ handler_t http_response_prepare(server *srv, connection *con) {
}
if (con->state == CON_STATE_READ_POST) {
r = connection_handle_read_post_state(srv, con);
if (r != HANDLER_GO_ON) return r;
}
switch(r = plugins_call_handle_subrequest(srv, con)) {
case HANDLER_GO_ON:
/* request was not handled, looks like we are done */