From 43ae0389bf96570dedc665452b03a4172214c3f9 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Mon, 12 Oct 2026 21:56:27 +0300 Subject: [PATCH] Keep the server connection when only the request method changes A kept-alive client connection reuses the connection to the server while requests go to the same host. The check compared the start of the request line up to the end of the host, method included, so a POST after a GET to the same host, or a GET after a POST, closed the server connection and opened another one. Only the host and port are compared now. Co-Authored-By: Claude Opus 5.5 --- src/proxy.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/proxy.c b/src/proxy.c index 072c2cd..daefc75 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -183,6 +183,20 @@ static uint64_t fillwhole(struct clientparam *param, DIRECTION which, uint64_t l } #endif +/* Whether a request line names the host the previous one did, whatever its + method: the connection to the server is kept for the same host only, and + a POST after a GET to it is no reason to open another one. */ +static int samehost(const unsigned char *line, int len, const unsigned char *host, int hostlen){ + const unsigned char *p = (const unsigned char *)memchr(line, ' ', len); + + if(!p || hostlen <= 0) return 0; + p++; + if(!strncasecmp((const char *)p, "http://", 7)) p += 7; + if((int)(p - line) + hostlen >= len || strncasecmp((const char *)p, (const char *)host, hostlen)) + return 0; + return p[hostlen] == '/' || p[hostlen] == ' '; +} + static void freeptr(void *p){ void **pp = (void **)p; if(*pp) { free(*pp); *pp = NULL; } @@ -297,7 +311,7 @@ void * proxychild(struct clientparam* param) { int clhdrofs_req = -1; int isconnect = 0; int redirect = 0; - int prefix = 0, ckeepalive=0; + int prefix = 0, hostofs = 0, ckeepalive=0; int ftp = 0; int ssoff = 0; #ifndef ANONYMOUS @@ -366,7 +380,7 @@ for(;;){ buf[i] = 0; if(req) { - if(!param->transparent && !param->srv->transparent && (i<=prefix || strncasecmp((char *)buf, (char *)req, prefix))){ + if(!param->transparent && !param->srv->transparent && !samehost(buf, i, req + hostofs, prefix - hostofs)){ ckeepalive = 0; if(param->remsock != INVALID_SOCKET){ param->srv->so._shutdown(param->sostate, param->remsock, SHUT_RDWR); @@ -424,6 +438,7 @@ for(;;){ *se = 0; } prefix = (int)(se - buf); + hostofs = (int)(sb - buf); su = (unsigned char*)strrchr((char *)sb, '@'); if(su) { su = (unsigned char *)strdup((char *)sb);