Description
The http.Redirect
function sets the content header to text/html
and writes a simple link. Since the body is normally not seen anyways except by legacy clients with one of the newer redirect status codes, this is generally fine if you're using HTML. However, being a general HTTP package, redirects are often useful in places that don't use HTML, such as web APIs, HTTP based instant messengers, etc.
Since an HTTP redirect is performed by setting the Location
header and a status code, it seems easy enough to do on your own. However, the built in Redirect handler has several branches that cover for a variety of edge cases, and uses a special cased form of URL escaping that is not exported, so it actually requires copying a lot of code to get it right.
Since this is non-trivial, and potentially a security problem (if you don't escape your URLs properly you may wind up with header injection or similar), I would like to see the net/http
package include a more general form of redirect that does not try to write the body itself. I am using a middleware-esq approach in some of my projects:
// RedirectHandlerFunc replies to the request with a redirect to url,
// which may be a path relative to the request path.
//
// The handler should write a status code in the 3xx range, usually
// http.StatusMovedPermanently, http.StatusFound or http.StatusSeeOther.
func RedirectHandlerFunc(w http.ResponseWriter, r *http.Request, url string, h http.HandlerFunc) { /* … */ }
An alternative might be to create a function similar to the existing redirect that is meant to be called from within handlers:
// RedirectHeader replies to the request with a redirect to url,
// by writing the Location header which may be a path relative
// to the request path.
//
// RedirectHeader does not write a status code or body.
// The user should write a status code in the 3xx range, usually
// http.StatusMovedPermanently, http.StatusFound or http.StatusSeeOther.
func RedirectHeader(w http.ResponseWriter, r *http.Request, url string) { /* … */ }
The usual litmus test of "would this be useful elsewhere in the standard library" doesn't seem to apply here since this is more an application specific concern, but this would potentially be useful in all web APIs, and that seems like a rather large number of projects.