ref: fdfce9d864a71d2da773a5e024f463def3dcfb43
parent: 51915912e96ebea4f170c77da682dfa5f6782a28
author: cinap_lenrek <[email protected]>
date: Fri Jul 6 11:49:33 EDT 2012
hproxy: simple http proxy server
--- 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 @@
.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 @@
.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 @@
.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)
--- /dev/null
+++ b/sys/src/cmd/ip/hproxy.c
@@ -1,0 +1,96 @@
+#include <u.h>
+#include <libc.h>
+
+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");
+}