aboutsummaryrefslogtreecommitdiff
path: root/src/lib/http/server.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-04-15 18:40:55 -0700
committerRuss Cox <rsc@golang.org>2009-04-15 18:40:55 -0700
commitcff99ba167a9eb6f134a576f0438390ddacba38d (patch)
treee335678a7c56ef773c15a7b3103a0a4a71917b82 /src/lib/http/server.go
parent17c290ffb9a14061321eb570a8d3e3a93d8ca2c9 (diff)
downloadgo-cff99ba167a9eb6f134a576f0438390ddacba38d.tar.xz
make Location translate relative path to absolute
(HTTP requires absolute in protocol). add URL tests R=r DELTA=243 (242 added, 0 deleted, 1 changed) OCL=27472 CL=27523
Diffstat (limited to 'src/lib/http/server.go')
-rw-r--r--src/lib/http/server.go43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/lib/http/server.go b/src/lib/http/server.go
index a8aef01f0e..267e9e41e4 100644
--- a/src/lib/http/server.go
+++ b/src/lib/http/server.go
@@ -269,6 +269,49 @@ func NotFoundHandler() Handler {
// Redirect replies to the request with a redirect to url,
// which may be a path relative to the request path.
func Redirect(c *Conn, url string) {
+ u, err := ParseURL(url);
+ if err != nil {
+ // TODO report internal error instead?
+ c.SetHeader("Location", url);
+ c.WriteHeader(StatusMovedPermanently);
+ }
+
+ // If url was relative, make absolute by
+ // combining with request path.
+ // The browser would probably do this for us,
+ // but doing it ourselves is more reliable.
+
+ // NOTE(rsc): RFC 2616 says that the Location
+ // line must be an absolute URI, like
+ // "http://www.google.com/redirect/",
+ // not a path like "/redirect/".
+ // Unfortunately, we don't know what to
+ // put in the host name section to get the
+ // client to connect to us again, so we can't
+ // know the right absolute URI to send back.
+ // Because of this problem, no one pays attention
+ // to the RFC; they all send back just a new path.
+ // So do we.
+ oldpath := c.Req.Url.Path;
+ if oldpath == "" { // should not happen, but avoid a crash if it does
+ oldpath = "/"
+ }
+ if u.Scheme == "" {
+ // no leading http://server
+ if url == "" || url[0] != '/' {
+ // make relative path absolute
+ olddir, oldfile := path.Split(oldpath);
+ url = olddir + url;
+ }
+
+ // clean up but preserve trailing slash
+ trailing := url[len(url) - 1] == '/';
+ url = path.Clean(url);
+ if trailing && url[len(url) - 1] != '/' {
+ url += "/";
+ }
+ }
+
c.SetHeader("Location", url);
c.WriteHeader(StatusMovedPermanently);
}