Skip to content

net/http: add more flexible Redirect #25166

Closed
@SamWhited

Description

@SamWhited

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions