From 1a66393b258cc1577c8a62b8e4855276e28a963e 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 c8e7183..6c219ff 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -171,6 +171,20 @@ static int growbuf(unsigned char **buf, int *bufsize, int need){ return 0; } +/* 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; } @@ -285,7 +299,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 @@ -354,7 +368,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); @@ -412,6 +426,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);