diff options
| author | Russ Cox <rsc@golang.org> | 2009-04-15 18:40:55 -0700 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2009-04-15 18:40:55 -0700 |
| commit | cff99ba167a9eb6f134a576f0438390ddacba38d (patch) | |
| tree | e335678a7c56ef773c15a7b3103a0a4a71917b82 /src/lib/http/server.go | |
| parent | 17c290ffb9a14061321eb570a8d3e3a93d8ca2c9 (diff) | |
| download | go-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.go | 43 |
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); } |
