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 <noreply@anthropic.com>
This commit is contained in:
Vladimir Dubrovin 2026-10-12 21:56:27 +03:00
parent b5e9459d64
commit 1a66393b25

View File

@ -171,6 +171,20 @@ static int growbuf(unsigned char **buf, int *bufsize, int need){
return 0; 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){ static void freeptr(void *p){
void **pp = (void **)p; void **pp = (void **)p;
if(*pp) { free(*pp); *pp = NULL; } if(*pp) { free(*pp); *pp = NULL; }
@ -285,7 +299,7 @@ void * proxychild(struct clientparam* param) {
int clhdrofs_req = -1; int clhdrofs_req = -1;
int isconnect = 0; int isconnect = 0;
int redirect = 0; int redirect = 0;
int prefix = 0, ckeepalive=0; int prefix = 0, hostofs = 0, ckeepalive=0;
int ftp = 0; int ftp = 0;
int ssoff = 0; int ssoff = 0;
#ifndef ANONYMOUS #ifndef ANONYMOUS
@ -354,7 +368,7 @@ for(;;){
buf[i] = 0; buf[i] = 0;
if(req) { 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; ckeepalive = 0;
if(param->remsock != INVALID_SOCKET){ if(param->remsock != INVALID_SOCKET){
param->srv->so._shutdown(param->sostate, param->remsock, SHUT_RDWR); param->srv->so._shutdown(param->sostate, param->remsock, SHUT_RDWR);
@ -412,6 +426,7 @@ for(;;){
*se = 0; *se = 0;
} }
prefix = (int)(se - buf); prefix = (int)(se - buf);
hostofs = (int)(sb - buf);
su = (unsigned char*)strrchr((char *)sb, '@'); su = (unsigned char*)strrchr((char *)sb, '@');
if(su) { if(su) {
su = (unsigned char *)strdup((char *)sb); su = (unsigned char *)strdup((char *)sb);