Browse Source

Plan 9 from Bell Labs 2008-10-30

David du Colombier 15 years ago
parent
commit
b0438f2648

+ 5 - 5
dist/replica/_plan9.db

@@ -6599,7 +6599,7 @@ sys/lib/ghostscript/wrfont.ps - 664 sys sys 1137463375 18170
 sys/lib/ghostscript/xlatmap - 664 sys sys 1137469677 1750
 sys/lib/ghostscript/zeroline.ps - 664 sys sys 1137463375 2467
 sys/lib/grap.defines - 664 sys sys 944956052 375
-sys/lib/httpd.rewrite - 664 sys sys 954262980 825
+sys/lib/httpd.rewrite - 664 sys sys 1225318416 377
 sys/lib/kbmap - 20000000775 sys sys 1140447136 0
 sys/lib/kbmap/ascii - 664 sys sys 1130763837 5181
 sys/lib/kbmap/azerty - 664 sys sys 1130763837 619
@@ -7867,7 +7867,7 @@ sys/man/8/fsconfig - 664 sys sys 1196638946 8890
 sys/man/8/fshalt - 664 sys sys 1196638947 862
 sys/man/8/getflags - 664 sys sys 1196638947 1713
 sys/man/8/gpsfs - 664 sys sys 1223562059 5097
-sys/man/8/httpd - 664 sys sys 1224114119 6957
+sys/man/8/httpd - 664 sys sys 1225318201 8198
 sys/man/8/init - 664 sys sys 1196638947 1430
 sys/man/8/ipconfig - 664 sys sys 1205960389 8284
 sys/man/8/ipserv - 664 sys sys 1208190062 3272
@@ -12525,8 +12525,8 @@ sys/src/cmd/ip/httpd/classify.c - 664 sys sys 1078840017 9665
 sys/src/cmd/ip/httpd/content.c - 664 sys sys 1015090170 3140
 sys/src/cmd/ip/httpd/emem.c - 664 sys sys 984773807 278
 sys/src/cmd/ip/httpd/hints.c - 664 sys sys 1143759344 6282
-sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1168701369 11538
-sys/src/cmd/ip/httpd/httpsrv.h - 664 sys sys 1142178186 1388
+sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1225318060 11905
+sys/src/cmd/ip/httpd/httpsrv.h - 664 sys sys 1225313811 1532
 sys/src/cmd/ip/httpd/imagemap.c - 664 sys sys 984773808 5229
 sys/src/cmd/ip/httpd/init.c - 664 sys sys 1015090171 2182
 sys/src/cmd/ip/httpd/log.c - 664 sys sys 1214400897 3075
@@ -12534,7 +12534,7 @@ sys/src/cmd/ip/httpd/man2html.c - 664 sys sys 1139667314 9069
 sys/src/cmd/ip/httpd/mkfile - 664 sys sys 1123902339 1353
 sys/src/cmd/ip/httpd/netlib_find.c - 664 sys sys 1015090172 6247
 sys/src/cmd/ip/httpd/netlib_history.c - 664 sys sys 1121977160 4748
-sys/src/cmd/ip/httpd/redirect.c - 664 sys sys 1190834585 2962
+sys/src/cmd/ip/httpd/redirect.c - 664 sys sys 1225318035 3438
 sys/src/cmd/ip/httpd/save.c - 664 sys sys 1015090172 3175
 sys/src/cmd/ip/httpd/sendfd.c - 664 sys sys 1129202621 12264
 sys/src/cmd/ip/httpd/webls.c - 664 sys sys 1120737502 7658

+ 5 - 5
dist/replica/plan9.db

@@ -6599,7 +6599,7 @@ sys/lib/ghostscript/wrfont.ps - 664 sys sys 1137463375 18170
 sys/lib/ghostscript/xlatmap - 664 sys sys 1137469677 1750
 sys/lib/ghostscript/zeroline.ps - 664 sys sys 1137463375 2467
 sys/lib/grap.defines - 664 sys sys 944956052 375
-sys/lib/httpd.rewrite - 664 sys sys 954262980 825
+sys/lib/httpd.rewrite - 664 sys sys 1225318416 377
 sys/lib/kbmap - 20000000775 sys sys 1140447136 0
 sys/lib/kbmap/ascii - 664 sys sys 1130763837 5181
 sys/lib/kbmap/azerty - 664 sys sys 1130763837 619
@@ -7867,7 +7867,7 @@ sys/man/8/fsconfig - 664 sys sys 1196638946 8890
 sys/man/8/fshalt - 664 sys sys 1196638947 862
 sys/man/8/getflags - 664 sys sys 1196638947 1713
 sys/man/8/gpsfs - 664 sys sys 1223562059 5097
-sys/man/8/httpd - 664 sys sys 1224114119 6957
+sys/man/8/httpd - 664 sys sys 1225318201 8198
 sys/man/8/init - 664 sys sys 1196638947 1430
 sys/man/8/ipconfig - 664 sys sys 1205960389 8284
 sys/man/8/ipserv - 664 sys sys 1208190062 3272
@@ -12525,8 +12525,8 @@ sys/src/cmd/ip/httpd/classify.c - 664 sys sys 1078840017 9665
 sys/src/cmd/ip/httpd/content.c - 664 sys sys 1015090170 3140
 sys/src/cmd/ip/httpd/emem.c - 664 sys sys 984773807 278
 sys/src/cmd/ip/httpd/hints.c - 664 sys sys 1143759344 6282
-sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1168701369 11538
-sys/src/cmd/ip/httpd/httpsrv.h - 664 sys sys 1142178186 1388
+sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1225318060 11905
+sys/src/cmd/ip/httpd/httpsrv.h - 664 sys sys 1225313811 1532
 sys/src/cmd/ip/httpd/imagemap.c - 664 sys sys 984773808 5229
 sys/src/cmd/ip/httpd/init.c - 664 sys sys 1015090171 2182
 sys/src/cmd/ip/httpd/log.c - 664 sys sys 1214400897 3075
@@ -12534,7 +12534,7 @@ sys/src/cmd/ip/httpd/man2html.c - 664 sys sys 1139667314 9069
 sys/src/cmd/ip/httpd/mkfile - 664 sys sys 1123902339 1353
 sys/src/cmd/ip/httpd/netlib_find.c - 664 sys sys 1015090172 6247
 sys/src/cmd/ip/httpd/netlib_history.c - 664 sys sys 1121977160 4748
-sys/src/cmd/ip/httpd/redirect.c - 664 sys sys 1190834585 2962
+sys/src/cmd/ip/httpd/redirect.c - 664 sys sys 1225318035 3438
 sys/src/cmd/ip/httpd/save.c - 664 sys sys 1015090172 3175
 sys/src/cmd/ip/httpd/sendfd.c - 664 sys sys 1129202621 12264
 sys/src/cmd/ip/httpd/webls.c - 664 sys sys 1120737502 7658

+ 6 - 0
dist/replica/plan9.log

@@ -36241,3 +36241,9 @@
 1224961204 0 c 386/lib/ape/libap.a - 664 sys sys 1224960113 767492
 1225139404 0 c sys/man/2/sechash - 664 sys sys 1225138636 3584
 1225218609 0 c sys/games/lib/fortunes - 664 sys sys 1225218126 271031
+1225303204 0 c sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1225303240 11829
+1225314004 0 c sys/src/cmd/ip/httpd/httpsrv.h - 664 sys sys 1225313811 1532
+1225319403 0 c sys/lib/httpd.rewrite - 664 sys sys 1225318416 377
+1225319403 1 c sys/man/8/httpd - 664 sys sys 1225318201 8198
+1225319403 2 c sys/src/cmd/ip/httpd/httpd.c - 664 sys sys 1225318060 11905
+1225319403 3 c sys/src/cmd/ip/httpd/redirect.c - 664 sys sys 1225318035 3438

+ 5 - 18
sys/lib/httpd.rewrite

@@ -1,24 +1,11 @@
-# syntax: prefix replacement
-# parsed by splitting into fields separated by spaces and tabs.
-# Anything following a # is ignored.
-#
-# prefix is a literal string match which is applied to each
-# file prefix of each url. The most specific, ie longest
-# pattern wins,  and is applied once (no rescanning).
-# Leave off trailing slash if pattern is a directory.
-#
-# If replacemant is a url, a "Permanently moved" message is returned.
-#
-# If replacement is "basic:" followed by a user name,
-# the http authorization for that user is require to access the subtree.
-#
+# httpd(8) describes the syntax.  to kick-start,
+# for(i in `{seq 50}) hget http://www.your-domain.com/ >/dev/null
+
 # An example of a local redirect
 #/netlib/c++/idioms/index.html.Z /netlib/c++/idioms/index.html
-#
+
 # Redirection to another site
 #/netlib/lapack/lawns http://netlib.org/lapack/lawns
-#
+
 # Home page for virtual host
 #http://www.ampl.com/		/cm/cs/what/ampl/index.html
-
-

+ 60 - 4
sys/man/8/httpd

@@ -110,19 +110,26 @@ some magic programs support POST as well.
 Persistent connections are supported for HTTP/1.1 or later clients;
 all connections close after a magic command is executed.
 The Content-type
-(default application/octet-stream)
+(default
+.BR application/octet-stream )
 and Content-encoding
-(default binary)
+(default
+.BR binary )
 of a file are determined by looking for suffixes of the file name in
 .BR /sys/lib/mimetype .
+.SS Redirection
 .PP
 Each requested URI is looked up in a redirection table, read from
 .BR /sys/lib/httpd.rewrite .
+Fields are separated by spaces and tabs.
+Anything following a
+.L #
+is ignored.
 The first field of each line is a URI;
 the second a replacement path.
 If a prefix of the URI matches a redirection path,
 the URI is rewritten using the corresponding replacement path,
-and a redirect is sent to the HTTP client.
+and a temporary redirect is sent to the HTTP client.
 If the replacement path does not specify a server name,
 and the request has no explicit host,
 then
@@ -138,14 +145,35 @@ the requested server),
 but not both:
 .B http://system/who/rob
 will never match a request.
+If the first field ends in a slash, this is an exact match;
+otherwise it is a prefix match.
+The first field is a literal string, matched against
+each file prefix of each URL.
+The most specific, i.e., longest,
+pattern wins, and is applied once (there is no rescanning).
+.PP
 .I Httpd
 handles replacements prefixed with 
-.B @ 
+.L @ 
 internally,
 treating the request as if it were for the replacement
 (without the
 .BR @ )
 but not informing the client of the rewritten name.
+Replacement URLs prefixed with 
+.L =
+generate a permanent redirection instead of a temporary one.
+.I Httpd
+checks to see if this file has changed once every 50 new TCP connections.
+HTTP 1.1 persistent connection implies many pages
+may come in one browser connection, so to kick-start
+.IR httpd ,
+try
+.IP
+.EX
+for(i in `{seq 50}) hget http://www.your-domain.com/ >/dev/null
+.EE
+.SS "Access Control"
 .PP
 Before opening any file,
 .I httpd
@@ -161,6 +189,9 @@ is a domain name presented to the HTTP client.
 The rest are pairs of user name and password.
 Thus, there can be many user name/password pairs
 valid for a directory.
+.br
+.ne 3
+.SS "Auxiliaries (magic)"
 .PP
 If the requested URI begins with
 .BI  /magic/ server /\f1,
@@ -283,6 +314,31 @@ overrides
 If a listing for a directory is requested and access
 is denied, or another error occurs, a simple error
 page is returned.
+.SH EXAMPLES
+These are all examples of how to use
+.BR httpd.rewrite .
+.PP
+A local redirection:
+.RS
+.EX
+/netlib/c++/idioms/index.html.Z /netlib/c++/idioms/index.html
+.EE
+.RE
+.PP
+Redirection to another site:
+.RS
+.EX
+/netlib/lapack/lawns		http://netlib.org/lapack/lawns
+http://inferno.bell-labs.com	http://www.vitanuova.com
+.EE
+.RE
+.PP
+Root directory for virtual host:
+.RS
+.EX
+http://www.ampl.com		/cm/cs/what/ampl
+.EE
+.RE
 .SH FILES
 .TF /sys/lib/httpd.rewrite
 .TP

+ 19 - 7
sys/src/cmd/ip/httpd/httpd.c

@@ -284,17 +284,19 @@ doreq(HConnect *c)
 	Strings ss;
 	char *magic, *uri, *newuri, *origuri, *newpath, *hb;
 	char virtualhost[100], logfd0[10], logfd1[10], vers[16];
-	int n, nredirect;
+	int n, nredirect, permmove;
 
 	/*
 	 * munge uri for magic
 	 */
 	uri = c->req.uri;
 	nredirect = 0;
+	permmove = 0;
 top:
 	if(++nredirect > 10){
 		if(hparseheaders(c, 15*60*1000) < 0)
 			exits("failed");
+		werrstr("redirection loop");
 		return hfail(c, HNotFound, uri);
 	}
 	ss = stripmagic(c, uri);
@@ -315,20 +317,30 @@ top:
 		c->req.uri = newpath;
 		newuri = newpath;
 	}else if(origuri[0]=='/' && origuri[1]==0){
-		/* can't redirect / until we read the headers */
+		/* can't redirect / until we read the headers below */
 		newuri = nil;
 	}else
 		newuri = redirect(c, origuri);
 	
 	if(newuri != nil){
-		if(newuri[0] == '@'){
-			c->req.uri = newuri+1;
-			uri = newuri+1;
+		if(isdecorated(newuri)){
+			if(newuri[0] == Modperm)
+				permmove = 1;
+			c->req.uri = uri = undecorated(newuri);
 			goto top;
 		}
 		if(hparseheaders(c, 15*60*1000) < 0)
 			exits("failed");
-		return hmoved(c, newuri);
+		/*
+		 * try temporary redirect instead of permanent,
+		 * unless explicitly overridden.
+		 */
+		if (permmove)
+			return hmoved(c, newuri);
+		if (http11(c))
+			return hredirected(c, "307 Temporary Redirect", newuri);
+		else
+			return hredirected(c, "302 Temporary Redirect", newuri);
 	}
 
 	/*
@@ -524,7 +536,7 @@ static int
 notfound(HConnect *c, char *url)
 {
 	c->xferbuf[0] = 0;
-	errstr(c->xferbuf, sizeof c->xferbuf);
+	rerrstr(c->xferbuf, sizeof c->xferbuf);
 	if(strstr(c->xferbuf, "file does not exist") != nil)
 		return hfail(c, HNotFound, url);
 	if(strstr(c->xferbuf, "permission denied") != nil)

+ 7 - 1
sys/src/cmd/ip/httpd/httpsrv.h

@@ -2,7 +2,11 @@ typedef struct HSPriv	HSPriv;
 
 enum
 {
-	HSTIMEOUT	= 15 * 60 * 1000
+	HSTIMEOUT	= 15 * 60 * 1000,
+
+	/* rewrite replacement field modifiers */
+	Modsilent	= '@',
+	Modperm		= '=',
 };
 
 struct HSPriv
@@ -54,6 +58,8 @@ void			redirectinit(void);
 char*			redirect(HConnect *hc, char*);
 char*			masquerade(char*);
 char*			authrealm(HConnect *hc, char *path);
+int			isdecorated(char *repl);
+char			*undecorated(char *repl);
 
 /* log.c */
 void			logit(HConnect*, char*, ...);

+ 38 - 16
sys/src/cmd/ip/httpd/redirect.c

@@ -21,6 +21,22 @@ static Redir *redirtab[HASHSIZE];
 static Redir *vhosttab[HASHSIZE];
 static char emptystring[1];
 
+/* replacement field decorated with redirection modifiers? */
+int
+isdecorated(char *repl)
+{
+	return repl[0] == Modsilent || repl[0] == Modperm;
+}
+
+/* return replacement without redirection modifiers */
+char *
+undecorated(char *repl)
+{
+	while (isdecorated(repl))
+		repl++;
+	return repl;
+}
+
 static int
 hashasu(char *key, int n)
 {
@@ -69,7 +85,8 @@ redirectinit(void)
 {
 	static Biobuf *b = nil;
 	static Qid qid;
-	char *file, *line, *s, *host, *field[3];
+	char *file, *line, *s, *host, *repl, *field[3];
+	static char pfx[] = "http://";
 
 	file = "/sys/lib/httpd.rewrite";
 	if(b != nil){
@@ -88,13 +105,15 @@ redirectinit(void)
 	while((line = Brdline(b, '\n')) != nil){
 		line[Blinelen(b)-1] = 0;
 		s = strchr(line, '#');
-		if(s != nil)
-			*s = '\0'; 	/* chop comment */
+		if(s != nil && (s == line || s[-1] == ' ' || s[-1] == '\t'))
+			*s = '\0'; 	/* chop comment iff after whitespace */
 		if(tokenize(line, field, nelem(field)) == 2){
-			if(strncmp(field[0], "http://", STRLEN("http://")) == 0 &&
-					strncmp(field[1], "http://", STRLEN("http://")) != 0){
-				host = field[0]+STRLEN("http://");
-				s = strpbrk(host, "/");
+			repl = undecorated(field[1]);
+			if(strncmp(field[0], pfx, STRLEN(pfx)) == 0 &&
+			   strncmp(repl, pfx, STRLEN(pfx)) != 0){
+				/* url -> filename */
+				host = field[0] + STRLEN(pfx);
+				s = strrchr(host, '/');
 				if(s)
 					*s = 0;  /* chop trailing slash */
 
@@ -133,7 +152,7 @@ char*
 redirect(HConnect *hc, char *path)
 {
 	Redir *redir;
-	char *s, *newpath;
+	char *s, *newpath, *repl;
 	int c, n;
 
 	for(s = strchr(path, '\0'); s > path; s = prevslash(path, s)){
@@ -142,25 +161,28 @@ redirect(HConnect *hc, char *path)
 		redir = lookup(redirtab, path);
 		*s = c;
 		if(redir != nil){
-			n = strlen(redir->repl) + strlen(s) + 2 + UTFmax;
+			repl = undecorated(redir->repl);
+			n = strlen(repl) + strlen(s) + 2 + UTFmax;
 			newpath = halloc(hc, n);
-			snprint(newpath, n, "%s%s", redir->repl, s);
+			snprint(newpath, n, "%s%s", repl, s);
 			return newpath;
 		}
 	}
 	return nil;
 }
 
-// if host is virtual, return implicit prefix for URI within webroot.
-// if not, return empty string
-// return value should not be freed by caller
+/*
+ * if host is virtual, return implicit prefix for URI within webroot.
+ * if not, return empty string.
+ * return value should not be freed by caller.
+ */
 char*
 masquerade(char *host)
 {
 	Redir *redir;
 
 	redir = lookup(vhosttab, host);
-	if(redir != nil)
-		return redir->repl;
-	return emptystring;
+	if(redir == nil)
+		return emptystring;
+	return undecorated(redir->repl);
 }