Hi,

I can confirm this patch (from the 6.9 source) makes httpd work with Android Nextcloud client 3.16, where the unpatched httpd does not work.

Thanks very much!

Cheers,
Steve Williams


On 15/05/2021 9:14 a.m., Florian Obser wrote:
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? */



Reply via email to