src/server/safs/proxy.c

changeset 672
226bfd584075
parent 671
879005903b2b
--- a/src/server/safs/proxy.c	Sat Feb 14 18:08:24 2026 +0100
+++ b/src/server/safs/proxy.c	Sun Feb 15 11:16:50 2026 +0100
@@ -30,6 +30,8 @@
 
 #include <sys/socket.h>
 #include <arpa/inet.h>
+#include <ctype.h>
+#include <string.h>
 
 #include "../util/pblock.h"
 #include "../proxy/httpclient.h"
@@ -74,22 +76,83 @@
     
 }
 
-typedef struct ProxyData {
+typedef struct ProxyRequest {
     Session *sn;
     Request *rq;
-} ProxyData;
+    
+    /*
+     * request header rewrite map
+     * name: header name
+     * value: header value or an empty string, if the header should be removed
+     */
+    pblock *request_header_rewrite;
+    
+    /*
+     * response header rewrite map
+     * name: header name
+     * value: header value or an empty string, if the header should be removed
+     */
+    pblock  *response_header_rewrite;
+    
+    /*
+     * Has the response started (proxy_response_start called)
+     */
+    int response_started;
+} ProxyRequest;
 
 static int proxy_response_start(HttpClient *client, int status, char *message, void *userdata) {
-    ProxyData *proxy = userdata;
+    ProxyRequest *proxy = userdata;
+    
+    HeaderArray *headers = client->response_headers;
+    while(headers) {
+        for(int i=0;i<headers->len;i++) {
+            cxmutstr name = headers->headers[i].name;
+            cxmutstr value = headers->headers[i].value;
+            // NSAPI uses lower case header names internally
+            for(int c=0;c<name.length;c++) {
+                name.ptr[c] = tolower(name.ptr[c]);
+            }
+            // HttpClient does not 0-terminate strings
+            name.ptr[name.length] = 0;
+            // check if this header should be modified
+            char *rewrite = pblock_findval(name.ptr, proxy->response_header_rewrite);
+            if(rewrite) {
+                value = cx_mutstr(rewrite);
+                if(value.length == 0) {
+                    // empty header value -> skip
+                    continue;
+                }
+            }
+            
+            // add header to response
+            pblock_nvlinsert(name.ptr, name.length, value.ptr, value.length, proxy->rq->srvhdrs);
+        }
+        headers = headers->next;
+    }
     
     protocol_status(proxy->sn, proxy->rq, status, message);
     protocol_start_response(proxy->sn, proxy->rq);
+    proxy->response_started = 1;
     
     return 0;
 }
 
+static void proxy_response_finished(HttpClient *client, void *userdata) {
+    ProxyRequest *proxy = userdata;
+    
+    int ret = REQ_PROCEED;
+    if(!proxy->response_started) {
+        protocol_status(proxy->sn, proxy->rq, 502, NULL);
+        ret = REQ_ABORTED;
+    }
+    
+    http_client_free(client);
+    
+    nsapi_function_return(proxy->sn, proxy->rq, ret);
+}
+
 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) {
-    ProxyData *proxy = userdata;
+    ProxyRequest *proxy = userdata;
     ssize_t ret = net_write(proxy->sn->csd, buf, nbytes);
     // TODO: handle errors
     return ret;
@@ -105,6 +168,24 @@
         return REQ_ABORTED;
     }
     
+    // remove some response headers, that were previously set by ObjectType
+    // or other SAFs
+    pblock_removekey(pb_key_content_type, rq->srvhdrs);
+    
+    ProxyRequest *proxy = pool_malloc(sn->pool, sizeof(ProxyRequest));
+    proxy->sn = sn;
+    proxy->rq = rq;
+    proxy->request_header_rewrite = pblock_create_pool(sn->pool, 16);
+    proxy->response_header_rewrite = pblock_create_pool(sn->pool, 16);
+    proxy->response_started = 0;
+    
+    // some request/response headers should be removed or altered
+    // an empty string means, the header should be removed
+    pblock_nvinsert("host", "", proxy->request_header_rewrite);
+    pblock_nvinsert("connection", "", proxy->request_header_rewrite);
+    pblock_nvinsert("server", "", proxy->response_header_rewrite);
+    pblock_nvinsert("connection", "", proxy->response_header_rewrite);
+    
     // setup HttpClient
     HttpClient *client = http_client_new(ev);
     if(!client) {
@@ -127,20 +208,28 @@
     address.sin_family = AF_INET;
     address.sin_port = htons(8080);
     http_client_set_addr(client, (struct sockaddr*)&address, sizeof(address));    
+    http_client_add_request_header(client, cx_mutstr("host"), cx_mutstr("localhost:8080"));
     
     // add request headers to the client
     CxIterator i = pblock_iterator(rq->headers);
     cx_foreach(pb_entry*, entry, i) {
-        // TODO: don't pass all headers
-        if(http_client_add_request_header(client, cx_mutstr(entry->param->name), cx_mutstr(entry->param->value))) {
+        cxmutstr header_value;
+        char *rewrite_header = pblock_findval(entry->param->name, proxy->request_header_rewrite);
+        if(rewrite_header) {
+            header_value = cx_mutstr(rewrite_header);
+            if(header_value.length == 0) {
+                continue;
+            }
+        } else {
+            header_value = cx_mutstr(entry->param->value);
+        }
+        
+        if(http_client_add_request_header(client, cx_mutstr(entry->param->name), header_value)) {
             http_client_free(client);
             return REQ_ABORTED;
         }
     }
     
-    ProxyData *proxy = pool_malloc(sn->pool, sizeof(ProxyData));
-    proxy->sn = sn;
-    proxy->rq = rq;
     client->response_start = proxy_response_start;
     client->response_start_userdata = proxy;
     client->response_body_write = proxy_response_write;
@@ -158,6 +247,8 @@
 
 
 
+/* --------------------------------- Tests --------------------------------- */
+
 static CX_TEST(test_safs_proxy_get_uri_from_clfreq) {
     CX_TEST_DO {
         cxstring ret;

mercurial