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/xlatmap - 664 sys sys 1137469677 1750
 sys/lib/ghostscript/zeroline.ps - 664 sys sys 1137463375 2467
 sys/lib/ghostscript/zeroline.ps - 664 sys sys 1137463375 2467
 sys/lib/grap.defines - 664 sys sys 944956052 375
 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 - 20000000775 sys sys 1140447136 0
 sys/lib/kbmap/ascii - 664 sys sys 1130763837 5181
 sys/lib/kbmap/ascii - 664 sys sys 1130763837 5181
 sys/lib/kbmap/azerty - 664 sys sys 1130763837 619
 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/fshalt - 664 sys sys 1196638947 862
 sys/man/8/getflags - 664 sys sys 1196638947 1713
 sys/man/8/getflags - 664 sys sys 1196638947 1713
 sys/man/8/gpsfs - 664 sys sys 1223562059 5097
 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/init - 664 sys sys 1196638947 1430
 sys/man/8/ipconfig - 664 sys sys 1205960389 8284
 sys/man/8/ipconfig - 664 sys sys 1205960389 8284
 sys/man/8/ipserv - 664 sys sys 1208190062 3272
 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/content.c - 664 sys sys 1015090170 3140
 sys/src/cmd/ip/httpd/emem.c - 664 sys sys 984773807 278
 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/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/imagemap.c - 664 sys sys 984773808 5229
 sys/src/cmd/ip/httpd/init.c - 664 sys sys 1015090171 2182
 sys/src/cmd/ip/httpd/init.c - 664 sys sys 1015090171 2182
 sys/src/cmd/ip/httpd/log.c - 664 sys sys 1214400897 3075
 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/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_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/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/save.c - 664 sys sys 1015090172 3175
 sys/src/cmd/ip/httpd/sendfd.c - 664 sys sys 1129202621 12264
 sys/src/cmd/ip/httpd/sendfd.c - 664 sys sys 1129202621 12264
 sys/src/cmd/ip/httpd/webls.c - 664 sys sys 1120737502 7658
 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/xlatmap - 664 sys sys 1137469677 1750
 sys/lib/ghostscript/zeroline.ps - 664 sys sys 1137463375 2467
 sys/lib/ghostscript/zeroline.ps - 664 sys sys 1137463375 2467
 sys/lib/grap.defines - 664 sys sys 944956052 375
 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 - 20000000775 sys sys 1140447136 0
 sys/lib/kbmap/ascii - 664 sys sys 1130763837 5181
 sys/lib/kbmap/ascii - 664 sys sys 1130763837 5181
 sys/lib/kbmap/azerty - 664 sys sys 1130763837 619
 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/fshalt - 664 sys sys 1196638947 862
 sys/man/8/getflags - 664 sys sys 1196638947 1713
 sys/man/8/getflags - 664 sys sys 1196638947 1713
 sys/man/8/gpsfs - 664 sys sys 1223562059 5097
 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/init - 664 sys sys 1196638947 1430
 sys/man/8/ipconfig - 664 sys sys 1205960389 8284
 sys/man/8/ipconfig - 664 sys sys 1205960389 8284
 sys/man/8/ipserv - 664 sys sys 1208190062 3272
 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/content.c - 664 sys sys 1015090170 3140
 sys/src/cmd/ip/httpd/emem.c - 664 sys sys 984773807 278
 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/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/imagemap.c - 664 sys sys 984773808 5229
 sys/src/cmd/ip/httpd/init.c - 664 sys sys 1015090171 2182
 sys/src/cmd/ip/httpd/init.c - 664 sys sys 1015090171 2182
 sys/src/cmd/ip/httpd/log.c - 664 sys sys 1214400897 3075
 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/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_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/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/save.c - 664 sys sys 1015090172 3175
 sys/src/cmd/ip/httpd/sendfd.c - 664 sys sys 1129202621 12264
 sys/src/cmd/ip/httpd/sendfd.c - 664 sys sys 1129202621 12264
 sys/src/cmd/ip/httpd/webls.c - 664 sys sys 1120737502 7658
 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
 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
 1225139404 0 c sys/man/2/sechash - 664 sys sys 1225138636 3584
 1225218609 0 c sys/games/lib/fortunes - 664 sys sys 1225218126 271031
 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
 # An example of a local redirect
 #/netlib/c++/idioms/index.html.Z /netlib/c++/idioms/index.html
 #/netlib/c++/idioms/index.html.Z /netlib/c++/idioms/index.html
-#
+
 # Redirection to another site
 # Redirection to another site
 #/netlib/lapack/lawns http://netlib.org/lapack/lawns
 #/netlib/lapack/lawns http://netlib.org/lapack/lawns
-#
+
 # Home page for virtual host
 # Home page for virtual host
 #http://www.ampl.com/		/cm/cs/what/ampl/index.html
 #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;
 Persistent connections are supported for HTTP/1.1 or later clients;
 all connections close after a magic command is executed.
 all connections close after a magic command is executed.
 The Content-type
 The Content-type
-(default application/octet-stream)
+(default
+.BR application/octet-stream )
 and Content-encoding
 and Content-encoding
-(default binary)
+(default
+.BR binary )
 of a file are determined by looking for suffixes of the file name in
 of a file are determined by looking for suffixes of the file name in
 .BR /sys/lib/mimetype .
 .BR /sys/lib/mimetype .
+.SS Redirection
 .PP
 .PP
 Each requested URI is looked up in a redirection table, read from
 Each requested URI is looked up in a redirection table, read from
 .BR /sys/lib/httpd.rewrite .
 .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 first field of each line is a URI;
 the second a replacement path.
 the second a replacement path.
 If a prefix of the URI matches a redirection path,
 If a prefix of the URI matches a redirection path,
 the URI is rewritten using the corresponding replacement 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,
 If the replacement path does not specify a server name,
 and the request has no explicit host,
 and the request has no explicit host,
 then
 then
@@ -138,14 +145,35 @@ the requested server),
 but not both:
 but not both:
 .B http://system/who/rob
 .B http://system/who/rob
 will never match a request.
 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
 .I Httpd
 handles replacements prefixed with 
 handles replacements prefixed with 
-.B @ 
+.L @ 
 internally,
 internally,
 treating the request as if it were for the replacement
 treating the request as if it were for the replacement
 (without the
 (without the
 .BR @ )
 .BR @ )
 but not informing the client of the rewritten name.
 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
 .PP
 Before opening any file,
 Before opening any file,
 .I httpd
 .I httpd
@@ -161,6 +189,9 @@ is a domain name presented to the HTTP client.
 The rest are pairs of user name and password.
 The rest are pairs of user name and password.
 Thus, there can be many user name/password pairs
 Thus, there can be many user name/password pairs
 valid for a directory.
 valid for a directory.
+.br
+.ne 3
+.SS "Auxiliaries (magic)"
 .PP
 .PP
 If the requested URI begins with
 If the requested URI begins with
 .BI  /magic/ server /\f1,
 .BI  /magic/ server /\f1,
@@ -283,6 +314,31 @@ overrides
 If a listing for a directory is requested and access
 If a listing for a directory is requested and access
 is denied, or another error occurs, a simple error
 is denied, or another error occurs, a simple error
 page is returned.
 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
 .SH FILES
 .TF /sys/lib/httpd.rewrite
 .TF /sys/lib/httpd.rewrite
 .TP
 .TP

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

@@ -284,17 +284,19 @@ doreq(HConnect *c)
 	Strings ss;
 	Strings ss;
 	char *magic, *uri, *newuri, *origuri, *newpath, *hb;
 	char *magic, *uri, *newuri, *origuri, *newpath, *hb;
 	char virtualhost[100], logfd0[10], logfd1[10], vers[16];
 	char virtualhost[100], logfd0[10], logfd1[10], vers[16];
-	int n, nredirect;
+	int n, nredirect, permmove;
 
 
 	/*
 	/*
 	 * munge uri for magic
 	 * munge uri for magic
 	 */
 	 */
 	uri = c->req.uri;
 	uri = c->req.uri;
 	nredirect = 0;
 	nredirect = 0;
+	permmove = 0;
 top:
 top:
 	if(++nredirect > 10){
 	if(++nredirect > 10){
 		if(hparseheaders(c, 15*60*1000) < 0)
 		if(hparseheaders(c, 15*60*1000) < 0)
 			exits("failed");
 			exits("failed");
+		werrstr("redirection loop");
 		return hfail(c, HNotFound, uri);
 		return hfail(c, HNotFound, uri);
 	}
 	}
 	ss = stripmagic(c, uri);
 	ss = stripmagic(c, uri);
@@ -315,20 +317,30 @@ top:
 		c->req.uri = newpath;
 		c->req.uri = newpath;
 		newuri = newpath;
 		newuri = newpath;
 	}else if(origuri[0]=='/' && origuri[1]==0){
 	}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;
 		newuri = nil;
 	}else
 	}else
 		newuri = redirect(c, origuri);
 		newuri = redirect(c, origuri);
 	
 	
 	if(newuri != nil){
 	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;
 			goto top;
 		}
 		}
 		if(hparseheaders(c, 15*60*1000) < 0)
 		if(hparseheaders(c, 15*60*1000) < 0)
 			exits("failed");
 			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)
 notfound(HConnect *c, char *url)
 {
 {
 	c->xferbuf[0] = 0;
 	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)
 	if(strstr(c->xferbuf, "file does not exist") != nil)
 		return hfail(c, HNotFound, url);
 		return hfail(c, HNotFound, url);
 	if(strstr(c->xferbuf, "permission denied") != nil)
 	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
 enum
 {
 {
-	HSTIMEOUT	= 15 * 60 * 1000
+	HSTIMEOUT	= 15 * 60 * 1000,
+
+	/* rewrite replacement field modifiers */
+	Modsilent	= '@',
+	Modperm		= '=',
 };
 };
 
 
 struct HSPriv
 struct HSPriv
@@ -54,6 +58,8 @@ void			redirectinit(void);
 char*			redirect(HConnect *hc, char*);
 char*			redirect(HConnect *hc, char*);
 char*			masquerade(char*);
 char*			masquerade(char*);
 char*			authrealm(HConnect *hc, char *path);
 char*			authrealm(HConnect *hc, char *path);
+int			isdecorated(char *repl);
+char			*undecorated(char *repl);
 
 
 /* log.c */
 /* log.c */
 void			logit(HConnect*, char*, ...);
 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 Redir *vhosttab[HASHSIZE];
 static char emptystring[1];
 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
 static int
 hashasu(char *key, int n)
 hashasu(char *key, int n)
 {
 {
@@ -69,7 +85,8 @@ redirectinit(void)
 {
 {
 	static Biobuf *b = nil;
 	static Biobuf *b = nil;
 	static Qid qid;
 	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";
 	file = "/sys/lib/httpd.rewrite";
 	if(b != nil){
 	if(b != nil){
@@ -88,13 +105,15 @@ redirectinit(void)
 	while((line = Brdline(b, '\n')) != nil){
 	while((line = Brdline(b, '\n')) != nil){
 		line[Blinelen(b)-1] = 0;
 		line[Blinelen(b)-1] = 0;
 		s = strchr(line, '#');
 		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(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)
 				if(s)
 					*s = 0;  /* chop trailing slash */
 					*s = 0;  /* chop trailing slash */
 
 
@@ -133,7 +152,7 @@ char*
 redirect(HConnect *hc, char *path)
 redirect(HConnect *hc, char *path)
 {
 {
 	Redir *redir;
 	Redir *redir;
-	char *s, *newpath;
+	char *s, *newpath, *repl;
 	int c, n;
 	int c, n;
 
 
 	for(s = strchr(path, '\0'); s > path; s = prevslash(path, s)){
 	for(s = strchr(path, '\0'); s > path; s = prevslash(path, s)){
@@ -142,25 +161,28 @@ redirect(HConnect *hc, char *path)
 		redir = lookup(redirtab, path);
 		redir = lookup(redirtab, path);
 		*s = c;
 		*s = c;
 		if(redir != nil){
 		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);
 			newpath = halloc(hc, n);
-			snprint(newpath, n, "%s%s", redir->repl, s);
+			snprint(newpath, n, "%s%s", repl, s);
 			return newpath;
 			return newpath;
 		}
 		}
 	}
 	}
 	return nil;
 	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*
 char*
 masquerade(char *host)
 masquerade(char *host)
 {
 {
 	Redir *redir;
 	Redir *redir;
 
 
 	redir = lookup(vhosttab, host);
 	redir = lookup(vhosttab, host);
-	if(redir != nil)
-		return redir->repl;
-	return emptystring;
+	if(redir == nil)
+		return emptystring;
+	return undecorated(redir->repl);
 }
 }