Turns out it's not that difficult to do this correctly since we already
wait until we read all http headers from the fcgi upstream. We just need
to delay writing of the http header until we know if the body is empty
or not.
OK?
diff --git httpd.h httpd.h
index b3a40b3af68..c4adfba232d 100644
--- httpd.h
+++ httpd.h
@@ -300,6 +300,7 @@ struct fcgi_data {
int end;
int status;
int headersdone;
+ int headerssent;
};
struct range {
diff --git server_fcgi.c server_fcgi.c
index 64a0e9d2abb..e1e9704c920 100644
--- server_fcgi.c
+++ server_fcgi.c
@@ -114,6 +114,7 @@ server_fcgi(struct httpd *env, struct client *clt)
clt->clt_fcgi.toread = sizeof(struct fcgi_record_header);
clt->clt_fcgi.status = 200;
clt->clt_fcgi.headersdone = 0;
+ clt->clt_fcgi.headerssent = 0;
if (clt->clt_srvevb != NULL)
evbuffer_free(clt->clt_srvevb);
@@ -544,22 +545,20 @@ server_fcgi_read(struct bufferevent *bev, void *arg)
if (!clt->clt_fcgi.headersdone) {
clt->clt_fcgi.headersdone =
server_fcgi_getheaders(clt);
- if (clt->clt_fcgi.headersdone) {
- if (server_fcgi_header(clt,
- clt->clt_fcgi.status)
- == -1) {
- server_abort_http(clt,
- 500,
- "malformed fcgi "
- "headers");
- return;
- }
- }
if (!EVBUFFER_LENGTH(clt->clt_srvevb))
break;
}
/* FALLTHROUGH */
case FCGI_END_REQUEST:
+ if (clt->clt_fcgi.headersdone &&
+ !clt->clt_fcgi.headerssent) {
+ if (server_fcgi_header(clt,
+ clt->clt_fcgi.status) == -1) {
+ server_abort_http(clt, 500,
+ "malformed fcgi headers");
+ return;
+ }
+ }
if (server_fcgi_writechunk(clt) == -1) {
server_abort_http(clt, 500,
"encoding error");
@@ -600,6 +599,8 @@ server_fcgi_header(struct client *clt, unsigned int code)
char tmbuf[32];
struct kv *kv, *cl, key;
+ clt->clt_fcgi.headerssent = 1;
+
if (desc == NULL || (error = server_httperror_byid(code)) == NULL)
return (-1);
@@ -615,6 +616,12 @@ server_fcgi_header(struct client *clt, unsigned int code)
if (kv_add(&resp->http_headers, "Server", HTTPD_SERVERNAME) == NULL)
return (-1);
+ if (clt->clt_fcgi.type == FCGI_END_REQUEST ||
+ EVBUFFER_LENGTH(clt->clt_srvevb) == 0) {
+ /* Can't chunk encode an empty body. */
+ clt->clt_fcgi.chunked = 0;
+ }
+
/* Set chunked encoding */
if (clt->clt_fcgi.chunked) {
/* XXX Should we keep and handle Content-Length instead? */
--
I'm not entirely sure you are real.