shithub: riscv

Download patch

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");
+}