httpclient: move code for sending the request body to a separate function

Tue, 17 Feb 2026 20:03:06 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 17 Feb 2026 20:03:06 +0100
changeset 679
4885cd4c3754
parent 678
9908159eff0e
child 680
02935baa186b

httpclient: move code for sending the request body to a separate function

src/server/proxy/httpclient.c file | annotate | diff | comparison | revisions
--- a/src/server/proxy/httpclient.c	Tue Feb 17 17:43:10 2026 +0100
+++ b/src/server/proxy/httpclient.c	Tue Feb 17 20:03:06 2026 +0100
@@ -252,6 +252,57 @@
     return client_io(ev, event);
 }
 
+static int client_send_request_body(HttpClient *client) {
+    size_t rbody_readsize = client->req_buffer_alloc;
+    size_t rbody_buf_offset = 0;
+    if(client->req_content_length == -1) {
+        // chunked transfer encoding:
+        // don't fill req_buffer completely, reserve some space for
+        // a chunk header, that will be inserted at the beginning
+        rbody_readsize -= 16;
+        rbody_buf_offset = 16;
+    }
+    while(!client->request_body_complete) {
+        ssize_t r = client->request_body_read(client, client->req_buffer + rbody_buf_offset, rbody_readsize, client->request_body_read_userdata);
+        if(r <= 0) {
+            if(r == HTTP_CLIENT_CALLBACK_WOULD_BLOCK) {
+                return 1;
+            } else if(r == 0) {
+                // EOF
+                client->request_body_complete = 1;
+                break;
+            } else {
+                // error
+                client->error = 1;
+                return 1;
+            }
+        }
+
+        size_t startpos = 0;
+        if(client->req_content_length == -1) {
+            char chunkheader[16];
+            int chunkheaderlen = snprintf(chunkheader, 16, "%zx\r\n", (size_t)r);
+            startpos = 16 - chunkheaderlen;
+            memcpy(client->req_buffer + startpos, chunkheader, chunkheaderlen);
+        }
+
+        client->req_contentlength_pos += r;
+        client->req_buffer_pos = startpos;
+        client->req_buffer_len = r;
+        if(client_send_request(client)) {
+            return 1;
+        }
+    }
+
+    if(client->req_content_length > 0 && client->req_content_length != client->req_contentlength_pos) {
+        // incomplete request body
+        client->error = 1;
+        return 1;
+    }
+    
+    return 0;
+}
+
 static int client_io(EventHandler *ev, Event *event) {
     HttpClient *client = event->cookie;
     if(client->req_buffer_pos < client->req_buffer_len) {
@@ -262,38 +313,11 @@
     
     // do we need to send a request body?
     if(client->req_content_length != 0) {
-        while(!client->request_body_complete) {
-            ssize_t r = client->request_body_read(client, client->req_buffer, client->req_buffer_alloc, client->request_body_read_userdata);
-            if(r <= 0) {
-                if(r == HTTP_CLIENT_CALLBACK_WOULD_BLOCK) {
-                    return 1;
-                } else if(r == 0) {
-                    // EOF
-                    client->request_body_complete = 1;
-                    break;
-                } else {
-                    // error
-                    client->error = 1;
-                    return 0;
-                }
-            }
-            client->req_contentlength_pos += r;
-            client->req_buffer_pos = 0;
-            client->req_buffer_len = r;
-            if(client_send_request(client)) {
-                return client->error == 0;
-            }
-        }
-        
-        if(client->req_content_length > 0 && client->req_content_length != client->req_contentlength_pos) {
-            // incomplete request body
-            client->error = 1;
-            return 0;
+        if(client_send_request_body(client)) {
+            return client->error == 0;
         }
     }
     
-    
-    
     // writing complete, switch to read events
     event->events = EVENT_POLLIN;
     

mercurial