File 0001-handle-expect-100-continue-differen.patch of Package apache2-mod_fastcgi
From: Yehuda Sadeh <yehuda@hq.newdream.net>
Date: Fri, 25 Feb 2011 11:09:19 -0800
Subject: [PATCH] handle expect-100-continue differently
When expecting a 100-continue, wait for the application to return
that status before trying to read the data. That won't trigger the
apache early response.
---
fcgi.h | 3 ++-
fcgi_protocol.c | 15 ++++++++++++++-
mod_fastcgi.c | 25 +++++++++++++++++++++----
3 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/fcgi.h b/fcgi.h
index 1f3111c..0aebc16 100644
--- a/fcgi.h
+++ b/fcgi.h
@@ -294,6 +294,7 @@ typedef struct {
char *fs_stderr;
int fs_stderr_len;
int parseHeader; /* TRUE iff parsing response headers */
+ int gotCont;
request_rec *r;
int readingEndRequestBody;
FCGI_EndRequestBody endRequestBody;
@@ -498,7 +499,7 @@ int fcgi_pm_main(void *dummy, child_info *info);
*/
void fcgi_protocol_queue_begin_request(fcgi_request *fr);
void fcgi_protocol_queue_client_buffer(fcgi_request *fr);
-int fcgi_protocol_queue_env(request_rec *r, fcgi_request *fr, env_status *env);
+int fcgi_protocol_queue_env(request_rec *r, fcgi_request *fr, env_status *env, int *expect_cont);
int fcgi_protocol_dequeue(pool *p, fcgi_request *fr);
/*
diff --git a/fcgi_protocol.c b/fcgi_protocol.c
index 55da311..f80c5a5 100644
--- a/fcgi_protocol.c
+++ b/fcgi_protocol.c
@@ -221,9 +221,11 @@ static void add_pass_header_vars(fcgi_request *fr)
* complete ENV was buffered, FALSE otherwise. Note: envp is updated to
* reflect the current position in the ENV.
*/
-int fcgi_protocol_queue_env(request_rec *r, fcgi_request *fr, env_status *env)
+int fcgi_protocol_queue_env(request_rec *r, fcgi_request *fr, env_status *env,
+ int *expect_cont)
{
int charCount;
+ const char *name, *val;
if (env->envp == NULL) {
ap_add_common_vars(r);
@@ -237,15 +239,26 @@ int fcgi_protocol_queue_env(request_rec *r, fcgi_request *fr, env_status *env)
env->envp = ap_create_environment(r->pool, r->subprocess_env);
env->pass = PREP;
}
+ *expect_cont = 0;
while (*env->envp) {
+ ap_log_error(FCGI_LOG_WARN_NOERRNO, fcgi_apache_main_server,
+ "FastCGI: JJJ envp=%s", *env->envp);
switch (env->pass)
{
case PREP:
env->equalPtr = strchr(*env->envp, '=');
ASSERT(env->equalPtr != NULL);
+ name = *env->envp;
+ val = env->equalPtr + 1;
env->nameLen = env->equalPtr - *env->envp;
env->valueLen = strlen(++env->equalPtr);
+ ap_log_error(FCGI_LOG_WARN_NOERRNO, fcgi_apache_main_server,
+ "FastCGI: JJJ name='%.*s' val='%.*s'", env->nameLen, *env->envp, env->valueLen, val);
+ if (val && env->nameLen == sizeof("HTTP_EXPECT") - 1 &&
+ strncasecmp(name, "HTTP_EXPECT", env->nameLen) == 0 &&
+ strncasecmp(val, "100-continue", env->valueLen) == 0)
+ *expect_cont = 1;
build_env_header(env->nameLen, env->valueLen, env->headerBuff, &env->headerLen);
env->totalLen = env->headerLen + env->nameLen + env->valueLen;
env->pass = HEADER;
diff --git a/mod_fastcgi.c b/mod_fastcgi.c
index 67a70aa..e3c1e48 100644
--- a/mod_fastcgi.c
+++ b/mod_fastcgi.c
@@ -646,7 +646,7 @@ static void close_connection_to_fs(fcgi_request *fr)
static const char *process_headers(request_rec *r, fcgi_request *fr)
{
char *p, *next, *name, *value;
- int len, flag;
+ int len, flag, newl;
int hasLocation = FALSE;
ASSERT(fr->parseHeader == SCAN_CGI_READING_HEADERS);
@@ -661,11 +661,18 @@ static const char *process_headers(request_rec *r, fcgi_request *fr)
p = (char *)fr->header->elts;
len = fr->header->nelts;
flag = 0;
+ newl = 1;
while(len-- && flag < 2) {
- switch(*p) {
+ if (newl && !fr->gotCont && strncasecmp(p, "Status: 100", 11) == 0) {
+ fr->gotCont = 1;
+ ap_log_error(FCGI_LOG_WARN_NOERRNO, fcgi_apache_main_server,
+ "FastCGI: JJJ gotCont=1");
+ }
+ switch(*p) {
case '\r':
break;
case '\n':
+ newl = 1;
flag++;
break;
case '\0':
@@ -674,6 +681,7 @@ static const char *process_headers(request_rec *r, fcgi_request *fr)
name = "Invalid Character";
goto BadHeader;
default:
+ newl = 0;
flag = 0;
break;
}
@@ -1597,6 +1605,7 @@ static int npipe_io(fcgi_request * const fr)
pool * const rp = r->pool;
int is_connected = 0;
DWORD recv_count = 0;
+ int expect_cont = 0;
dynamic_last_io_time.tv_sec = 0;
dynamic_last_io_time.tv_usec = 0;
@@ -1637,7 +1646,7 @@ static int npipe_io(fcgi_request * const fr)
{
case STATE_ENV_SEND:
- if (fcgi_protocol_queue_env(r, fr, &env_status) == 0)
+ if (fcgi_protocol_queue_env(r, fr, &env_status, &expect_cont) == 0)
{
goto SERVER_SEND;
}
@@ -2010,6 +2019,7 @@ static int socket_io(fcgi_request * const fr)
env_status env;
pool *rp = r->pool;
int is_connected = 0;
+ int expect_cont = 0;
dynamic_last_io_time.tv_sec = 0;
dynamic_last_io_time.tv_usec = 0;
@@ -2046,7 +2056,7 @@ static int socket_io(fcgi_request * const fr)
{
case STATE_ENV_SEND:
- if (fcgi_protocol_queue_env(r, fr, &env) == 0)
+ if (fcgi_protocol_queue_env(r, fr, &env, &expect_cont) == 0)
{
goto SERVER_SEND;
}
@@ -2056,6 +2066,9 @@ static int socket_io(fcgi_request * const fr)
/* fall through */
case STATE_CLIENT_RECV:
+ if (expect_cont && !fr->gotCont) {
+ goto SERVER_SEND;
+ }
if (read_from_client_n_queue(fr))
{
@@ -2328,6 +2341,10 @@ SERVER_SEND:
state = STATE_ERROR;
break;
}
+ if (expect_cont && fr->gotCont) {
+ state = STATE_CLIENT_RECV;
+ continue;
+ }
}
if (fr->exitStatusSet)