src/server/proxy/httpclient.c

changeset 690
c7b73000a1ed
parent 688
02360295ec58
child 691
4d8a55a7618b
--- a/src/server/proxy/httpclient.c	Fri Feb 20 14:15:52 2026 +0100
+++ b/src/server/proxy/httpclient.c	Sat Feb 21 11:17:37 2026 +0100
@@ -32,6 +32,7 @@
 
 #include <cx/buffer.h>
 #include <cx/string.h>
+#include <cx/printf.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -891,7 +892,7 @@
     }
 }
 
-static CX_TEST_SUBROUTINE(test_http_client_io, const char *response_str, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz) {
+static CX_TEST_SUBROUTINE(test_http_client_io, cxstring response, int status_code, const char *msg, CxBuffer *out_buf, size_t write_blocksz) {
     EventHandler dummy;
     HttpClient *client = http_client_new(&dummy);
 
@@ -941,8 +942,9 @@
         CX_TEST_ASSERT(ret == 1);
     }
     CX_TEST_ASSERT(req_header_pos == req_header_len);
-
-    size_t response_str_len = strlen(response_str);
+    
+    const char *response_str = response.ptr;
+    size_t response_str_len = response.length;
     size_t response_str_pos = 0;
 
     // send response and do IO
@@ -975,12 +977,12 @@
 }
 
 static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz) {
-    char *response_str = 
+    cxstring response_str = cx_str(
             "HTTP/1.1 200 OK\r\n"
             "Host: localhost\r\n"
             "Content-length: 13\r\n"
             "\r\n"
-            "Hello World!\n";
+            "Hello World!\n");
     CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
     
     CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz);
@@ -1020,8 +1022,45 @@
     }
 }
 
+static CX_TEST_SUBROUTINE(test_http_client_io_large, size_t blocksz) {
+    int ctlen = 1024*1024*32;
+    CxBuffer *resp = cxBufferCreate(NULL, NULL, ctlen + 128, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
+    cx_bprintf(resp,
+            "HTTP/1.1 200 OK\r\n"
+            "Host: localhost\r\n"
+            "Content-length: %d\r\n"
+            "\r\n",
+            ctlen);
+    size_t content_start = resp->pos;
+    CX_TEST_ASSERT(resp->pos + ctlen < resp->capacity);
+    memset(resp->space + resp->pos, 'x', ctlen);
+    resp->pos += ctlen;
+    resp->size += ctlen;
+    
+    CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
+    
+    CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz);
+    CX_TEST_ASSERT(buf->size == ctlen);
+    CX_TEST_ASSERT(!memcmp(buf->space, resp->space + content_start, ctlen));
+    
+    cxBufferFree(resp);
+    cxBufferFree(buf);
+}
+
+static CX_TEST(test_http_client_io_large_128b) {
+    CX_TEST_DO {
+        CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 128);
+    }
+}
+
+static CX_TEST(test_http_client_io_large_4096b) {
+    CX_TEST_DO {
+        CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 1024);
+    }
+}
+
 static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz) {
-    char *response_str = 
+    cxstring response_str = cx_str( 
             "HTTP/1.1 200 OK\r\n"
             "Host: localhost\r\n"
             "Transfer-encoding: chunked\r\n"
@@ -1029,7 +1068,7 @@
             "d\r\n"        
             "Hello World!\n"
             "\r\n"
-            "0\r\n\r\n";
+            "0\r\n\r\n");
     CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
     
     CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz);
@@ -1063,6 +1102,76 @@
     }
 }
 
+static CX_TEST_SUBROUTINE(test_http_client_io_large_chunked_transfer, size_t blocksz) {
+    int chunk1 = 1024*1024*2;
+    int chunk2 = 1024*128;
+    int chunk3 = 123;
+    int chunk4 = 1024*1024*5;
+    int chunk5 = 1024*16;
+    
+    char *chunkbuf = malloc(chunk4);
+    
+    int ctlen = chunk1 + chunk2 + chunk3 + chunk4 + chunk5;
+    CxBuffer *resp = cxBufferCreate(NULL, NULL, ctlen * 128, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
+    cx_bprintf(resp,
+            "HTTP/1.1 200 OK\r\n"
+            "Transfer-encoding: chunked\r\n"
+            "\r\n",
+            ctlen);
+    size_t content_start = resp->pos;
+    CX_TEST_ASSERT(resp->pos + ctlen < resp->capacity);
+    
+    memset(chunkbuf, 'x', chunk1);
+    cx_bprintf(resp, "%x\r\n", chunk1);
+    int chunk1_pos = resp->pos;
+    cxBufferWrite(chunkbuf, 1, chunk1, resp);
+    cxBufferPutString(resp, "\r\n");
+    
+    memset(chunkbuf, '2', chunk2);
+    cx_bprintf(resp, "%x\r\n", chunk2);
+    int chunk2_pos = resp->pos;
+    cxBufferWrite(chunkbuf, 1, chunk2, resp);
+    cxBufferPutString(resp, "\r\n");
+    
+    memset(chunkbuf, 'c', chunk3);
+    cx_bprintf(resp, "%x\r\n", chunk3);
+    int chunk3_pos = resp->pos;
+    cxBufferWrite(chunkbuf, 1, chunk3, resp);
+    cxBufferPutString(resp, "\r\n");
+    
+    memset(chunkbuf, '4', chunk4);
+    cx_bprintf(resp, "%x\r\n", chunk4);
+    int chunk4_pos = resp->pos;
+    cxBufferWrite(chunkbuf, 1, chunk4, resp);
+    cxBufferPutString(resp, "\r\n");
+    
+    memset(chunkbuf, 'z', chunk5);
+    cx_bprintf(resp, "%x\r\n", chunk5);
+    int chunk5_pos = resp->pos;
+    cxBufferWrite(chunkbuf, 1, chunk5, resp);
+    cxBufferPutString(resp, "\r\n0\r\n\r\n");
+    
+    
+    CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS);
+    
+    CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz);
+    CX_TEST_ASSERT(buf->size == ctlen);
+    CX_TEST_ASSERT(!memcmp(buf->space, resp->space + chunk1_pos, chunk1));
+    CX_TEST_ASSERT(!memcmp(buf->space + chunk1, resp->space + chunk2_pos, chunk2));
+    CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2, resp->space + chunk3_pos, chunk3));
+    CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3, resp->space + chunk4_pos, chunk4));
+    CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3 + chunk4, resp->space + chunk5_pos, chunk5));
+    
+    cxBufferFree(resp);
+    cxBufferFree(buf);
+}
+
+static CX_TEST(test_http_client_io_large_chunked_transfer_1024b) {
+    CX_TEST_DO {
+        CX_TEST_CALL_SUBROUTINE(test_http_client_io_large_chunked_transfer, 1024);
+    }
+}
+
 void http_client_add_tests(CxTestSuite *suite) {
     cx_test_register(suite, test_http_client_send_request);
     cx_test_register(suite, test_http_client_send_request_body_chunked);
@@ -1074,8 +1183,11 @@
     cx_test_register(suite, test_http_client_io_simple_3b);
     cx_test_register(suite, test_http_client_io_simple_16b);
     cx_test_register(suite, test_http_client_io_simple_512b);
+    cx_test_register(suite, test_http_client_io_large_128b);
+    cx_test_register(suite, test_http_client_io_large_4096b);
     cx_test_register(suite, test_http_client_io_chunked_transfer_1b);
     cx_test_register(suite, test_http_client_io_chunked_transfer_2b);
     cx_test_register(suite, test_http_client_io_chunked_transfer_8b);
     cx_test_register(suite, test_http_client_io_chunked_transfer_64b);
+    cx_test_register(suite, test_http_client_io_large_chunked_transfer_1024b);
 }

mercurial