diff --git a/sys/man/8/ipserv b/sys/man/8/ipserv index fe30e42be..697879411 100644 --- a/sys/man/8/ipserv +++ b/sys/man/8/ipserv @@ -1,6 +1,6 @@ .TH IPSERV 8 .SH NAME -telnetd, rlogind, rexexec, ftpd, socksd \- Internet remote access daemons +telnetd, rlogind, rexexec, ftpd, socksd, hproxy \- Internet remote access daemons .SH SYNOPSIS .B ip/telnetd .RB [ -adnptN ] @@ -24,6 +24,8 @@ telnetd, rlogind, rexexec, ftpd, socksd \- Internet remote access daemons .B -o .I outside ] +.PP +.B ip/hproxy .SH DESCRIPTION These programs support remote access across the Internet. All expect the network connection to be standard input, output, and error. They are normally @@ -200,6 +202,9 @@ and .I outside will default to .BR /net . +.PP +.I Hproxy +is a simple HTTP proxy server. .SH FILES .B /lib/namepace .br @@ -218,6 +223,8 @@ will default to .B /sys/src/cmd/ip/ftpd.c .br .B /sys/src/cmd/ip/socksd.c +.br +.B /sys/src/cmd/ip/hproxy.c .SH "SEE ALSO" .IR ftpfs (4), .IR pop3 (8) diff --git a/sys/src/cmd/ip/hproxy.c b/sys/src/cmd/ip/hproxy.c new file mode 100644 index 000000000..ba8025cdf --- /dev/null +++ b/sys/src/cmd/ip/hproxy.c @@ -0,0 +1,96 @@ +#include +#include + +enum { bufsize = 8*1024 }; +char buf[bufsize+1], addr[128], *proto, *host, *port, *path; + +void +main(void) +{ + char *f[3], *p, *e; + int con, fd, n, r; + + /* read all the headers */ + n = 0; + do { + if(n >= bufsize) + return; + if((r = read(0, buf+n, bufsize-n)) <= 0) + return; + n += r; + buf[n] = 0; + } while(strstr(buf, "\r\n\r\n") == nil); + + /* remove keep alive headers */ + if(p = cistrstr(buf, "\nConnection:")) + if(e = strchr(p+1, '\n')) + strcpy(p, e); + if(p = cistrstr(buf, "\nProxy-Connection:")) + if(e = strchr(p+1, '\n')) + strcpy(p, e); + + /* crack first line of http request */ + if(e = strchr(buf, '\n')) + *e++ = 0; + r = tokenize(buf, f, 3); + if(r < 2) + return; + if(r == 2) + f[2] = "HTTP/1.0"; + proto = f[1]; + if(p = strstr(proto, "://")){ + *p = 0; + host = p + 3; + } else { + host = proto; + proto = "http"; + } + port = proto; + path = ""; + if(p = strchr(host, '/')){ + *p++ = 0; + path = p; + } + if(*host == '[') + host++; + if(p = strrchr(host, ':')){ + *p++ = 0; + port = p; + } + if(p = strrchr(host, ']')) + *p = 0; + + snprint(addr, sizeof(addr), "tcp!%s!%s", host, port); + + alarm(30000); + fd = dial(addr, 0, 0, 0); + alarm(0); + + con = cistrcmp(f[0], "CONNECT") == 0; + if(con){ + if(fd < 0) + print("%s 500 Connection Failed\r\n\r\n%r\n", f[2]); + else + print("%s 200 Connection Established\r\n\r\n", f[2]); + } + if(fd < 0) + return; + + switch(rfork(RFPROC|RFFDG|RFNOWAIT)){ + case -1: + return; + case 0: + dup(fd, 0); + break; + default: + dup(fd, 1); + if(!con) + print("%s /%s %s\r\n%s", f[0], path, f[2], e); + } + + while((r = read(0, buf, sizeof(buf))) > 0) + if(write(1, buf, r) != r) + break; + + postnote(PNGROUP, getpid(), "kill"); +}