src/server/proxy/httpclient.c

changeset 675
edacba8beedb
parent 674
6a031133a498
child 676
d43f1dd8b18e
--- a/src/server/proxy/httpclient.c	Sun Feb 15 13:30:29 2026 +0100
+++ b/src/server/proxy/httpclient.c	Mon Feb 16 17:43:14 2026 +0100
@@ -142,6 +142,13 @@
 }
 
 int http_client_add_request_header_copy(HttpClient *client, cxstring name, cxstring value) {
+    if(!client->mp) {
+        client->mp = cxMempoolCreate(64, CX_MEMPOOL_TYPE_PURE);
+        if(!client->mp) {
+            return 1;
+        }
+    }
+    
     cxmutstr n = cx_strdup_a(client->mp->allocator, name);
     cxmutstr v = cx_strdup_a(client->mp->allocator, value);
     
@@ -156,6 +163,18 @@
     return err;
 }
 
+int http_client_set_content_length(HttpClient *client, int64_t contentlength) {
+    client->req_content_length = contentlength;
+    char ctlen_buf[32];
+    size_t len = snprintf(ctlen_buf, 32, "%" PRId64, contentlength);
+    return http_client_add_request_header_copy(client, cx_str("content-length"), cx_strn(ctlen_buf, len));
+}
+
+int http_client_enable_chunked_transfer_encoding(HttpClient *client) {
+    client->req_content_length = -1;
+    return http_client_add_request_header(client, cx_mutstr("transfer-encoding"), cx_mutstr("chunked"));
+}
+
 int http_client_start(HttpClient *client) {
     int socketfd = socket(AF_INET, SOCK_STREAM, 0);
     if(socketfd < 0) {
@@ -192,7 +211,7 @@
 
 static int create_req_buffer(HttpClient *client) {
     CxBuffer buf;
-    if(cxBufferInit(&buf, cxDefaultAllocator, NULL, 1024, CX_BUFFER_AUTO_EXTEND)) {
+    if(cxBufferInit(&buf, cxDefaultAllocator, NULL, HTTP_CLIENT_BUFFER_SIZE, CX_BUFFER_AUTO_EXTEND)) {
         return 1;
     }
     
@@ -216,6 +235,7 @@
     }
     cxBufferPutString(&buf, "\r\n");
     client->req_buffer = buf.space;
+    client->req_buffer_alloc = buf.capacity;
     client->req_buffer_len = buf.size;
     
     return 0;
@@ -236,13 +256,44 @@
     HttpClient *client = event->cookie;
     if(client->req_buffer_pos < client->req_buffer_len) {
         if(client_send_request(client)) {
-            if(client->error) {
-                return 0; // TODO: set error
+            return client->error == 0;
+        }
+    }
+    
+    // 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;
+                }
             }
-            return 1;
-        } 
+            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;
+        }
     }
     
+    
+    
     // writing complete, switch to read events
     event->events = EVENT_POLLIN;
     
@@ -338,7 +389,15 @@
 
 static int client_send_request(HttpClient *client) {
     size_t nbytes = client->req_buffer_len - client->req_buffer_pos;
-    ssize_t w = write(client->socketfd, client->req_buffer + client->req_buffer_pos, nbytes);
+    ssize_t w;
+    while((w = write(client->socketfd, client->req_buffer + client->req_buffer_pos, nbytes)) > 0) {
+        client->req_buffer_pos += w;
+        nbytes = client->req_buffer_len - client->req_buffer_pos;
+        if(nbytes == 0) {
+            break;
+        }
+    }
+    
     if(w <= 0) {
         if(errno != EAGAIN) {
             // TODO: log correct host
@@ -348,8 +407,6 @@
         return 1;
     }
     
-    client->req_buffer_pos += w;
-    
     return client->req_buffer_pos < client->req_buffer_len;
 }
 

mercurial