src/server/safs/proxy.c

changeset 706
df64b4b79912
parent 700
658f4c02b4c5
--- a/src/server/safs/proxy.c	Wed Feb 25 22:38:51 2026 +0100
+++ b/src/server/safs/proxy.c	Wed Feb 25 23:14:47 2026 +0100
@@ -37,6 +37,7 @@
 
 #include "../util/pblock.h"
 #include "../util/util.h"
+#include "../util/io.h"
 #include "../proxy/httpclient.h"
 
 
@@ -44,6 +45,8 @@
     Session *sn;
     Request *rq;
     
+    HttpClient *client;
+    
     /*
      * request header rewrite map
      * name: header name
@@ -59,11 +62,28 @@
     pblock  *response_header_rewrite;
     
     /*
+     * event structure for sn->csd
+     */
+    Event event;
+    
+    /*
      * Has the response started (proxy_response_start called)
      */
     int response_started;
+    
+    /*
+     * reference counter
+     */
+    int ref;
 } ProxyRequest;
 
+static void proxy_unref(ProxyRequest *proxy) {
+    if(--proxy->ref == 0) {
+        http_client_free(proxy->client);
+        free(proxy);
+    }
+}
+
 static int proxy_response_start(HttpClient *client, int status, char *message, void *userdata) {
     ProxyRequest *proxy = userdata;
     
@@ -110,9 +130,25 @@
         ret = REQ_ABORTED;
     }
     
-    http_client_free(client);
+    nsapi_function_return(proxy->sn, proxy->rq, ret);
     
-    nsapi_function_return(proxy->sn, proxy->rq, ret);
+    proxy_unref(proxy);
+}
+
+static int proxy_request_read_event(EventHandler *eh, Event *event) {
+    ProxyRequest *proxy = event->cookie;
+    if(http_client_process(proxy->client)) {
+        if(proxy->client->error == 0) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int proxy_request_read_finished(EventHandler *eh, Event *event) {
+    ProxyRequest *proxy = event->cookie;
+    proxy_unref(proxy);
+    return 0;
 }
 
 static ssize_t proxy_request_read(HttpClient *client, void *buf, size_t nbytes, void *userdata) {
@@ -120,8 +156,25 @@
     int ret = netbuf_getbytes(proxy->sn->inbuf, buf, nbytes);
     if(ret == NETBUF_EOF) {
         ret = 0;
+    } else if(ret < 0) {
+        IOStream *st = proxy->sn->csd;
+        if(st->io_errno == EWOULDBLOCK) {
+            ret = HTTP_CLIENT_CALLBACK_WOULD_BLOCK;
+            // is there already an poll event for csd?
+            if(!proxy->event.cookie) {
+                proxy->ref++;
+                proxy->event.cookie = proxy;
+                proxy->event.fn = proxy_request_read_event;
+                proxy->event.finish = proxy_request_read_finished;
+                if(event_pollin(client->ev, st, &proxy->event)) {
+                    ret = HTTP_CLIENT_CALLBACK_ERROR;
+                }
+            }
+        } else {
+            ret = HTTP_CLIENT_CALLBACK_ERROR;
+        }
     }
-    // TODO: handle errors
+    
     return ret;
 }
 
@@ -228,12 +281,13 @@
     // or other SAFs
     pblock_removekey(pb_key_content_type, rq->srvhdrs);
     
-    ProxyRequest *proxy = pool_malloc(sn->pool, sizeof(ProxyRequest));
+    ProxyRequest *proxy = malloc(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;
+    proxy->ref = 1;
     
     // Some request/response headers should be removed or altered
     // An empty string means, the header should be removed
@@ -249,6 +303,7 @@
     if(!client) {
         return REQ_ABORTED;
     }
+    proxy->client = client;
     
     if(http_client_set_method(client, method)) {
         http_client_free(client);

mercurial