Re: [go-nuts] HTTP Server is too clean with its URLs

1,612 views
Skip to first unread message

Brad Fitzpatrick

unread,
May 8, 2013, 4:44:36 PM5/8/13
to buet...@google.com, golang-nuts
Don't use ServeMux.



On Wed, May 8, 2013 at 12:31 PM, <buet...@google.com> wrote:
I am working on a forward proxy built using Go. I noticed that URLs of the form 'http://foo.com//bar' get normalized to 'http://foo.com/bar', before they hit our ServeHTTP function. This happens in func (mux *ServeMux) ServeHTTP(...) (net/http/server.go), which returns a 301 redirect to the single-slash version. I believe Apache makes this behavior optional. The problem for us is that (AFAICT) a double-slash in the URL is still standards compliant. Origin sites may in fact have URLs with a double slash, and if so we should be fetching those URLs without cleaning them. We haven't found an example of a site that breaks with the clean URL, yet. But, if we do, is there a way we can bypass the cleaning step?

 michael

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Keith Rarick

unread,
May 8, 2013, 4:44:47 PM5/8/13
to buet...@google.com, golang-nuts
You don't have to use the http package's ServeMux.
For example, you can put your handler directly into a
call to http.ListenAndServe.
Message has been deleted

Joe Wass

unread,
Oct 10, 2013, 1:13:04 PM10/10/13
to golan...@googlegroups.com, buet...@google.com
And this means re-implementing ServeMux, right? 

I also have the same problem, and I would expect this to be configurable rather than all-or-nothing. I have my app working, except for this annoying redirect for certain URLs where there are consecutive slashes (which are meaningful: it's a hard requirement that the slashes have to be preserved in the URL). I don't much like the idea of writing my own URL router this just for the sake of a few slashes. Unless I've misunderstood?

Are the library maintainers open to patches of this kind? If so, I think adding a method to alter the configuration of this behaviour would be useful, especially if the current behaviour breaks standards as michael suggests.

Andy Balholm

unread,
Oct 10, 2013, 2:51:58 PM10/10/13
to golan...@googlegroups.com, buet...@google.com
On Thursday, October 10, 2013 10:13:04 AM UTC-7, Joe Wass wrote:
And this means re-implementing ServeMux, right? 

Unless one of the third-party routers like pat or gorilla/mux does what you need. 

Kevin Gillette

unread,
Oct 10, 2013, 4:05:40 PM10/10/13
to golan...@googlegroups.com, buet...@google.com
For implementing a reverse proxy, it's not like you would have to reimplement ServeMux, since you want to have as much transparency as possible, and mainly would be serving out of a flat prefix per internal destination. If the web-service is providing its own additional paths that aren't proxied anywhere, then as clean as possible is likely ideal. The way this can be done is to do as Keith suggested, by providing your own http.Handler to ListenAndServe, and after checking to see if the path matches any of the configured proxies, fallback to a new mux created with http.NewServeMux.

Joe Wass

unread,
Oct 11, 2013, 6:19:43 AM10/11/13
to golan...@googlegroups.com, buet...@google.com
Thanks for your help Andy and Kevin.

I'm not actually implementing a reverse proxy, I just want to do some 'normal' URL routing where the URLs may contain consecutive slashes which I want to capture. I'm using the Gorilla mux, and assume the net/http package would do the same given the original message.

If anyone else passes along this way and is interested, this is what I've ended up doing. I want to handle urls like "/route/to/things/http://thing-uri". (This re-direct behaviour was happening with URL-encoded components).

const ROUTE_THINGS = "/route/to/things/"

func HandleThing(writer http.ResponseWriter, request *http.Request, string thingUri) { ... }

type InterceptHandler struct { router *mux.Router }

func (handler *InterceptHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
    if strings.HasPrefix(request.URL.Path, ROUTE_THINGS) {
        thingUri := request.URL.Path[len(ROUTE_THINGS):]

        HandleThing(writer, request, thingUri)
        return
    }

    handler.router.ServeHTTP(writer, request)
}

// in main:

r := mux.NewRouter()
r.StrictSlash(false)

r.HandleFunc(OTHER_ROUTE, OtherHandleFunc)

http.ListenAndServe(serveUrl.Host, &InterceptHandler{r})

Cenk Altı

unread,
Nov 25, 2014, 2:03:15 PM11/25/14
to golan...@googlegroups.com, buet...@google.com
Hello,

Old thread but http.ServeMux still cannot be used for a problem like this. In a project I had to process URL like this:

A url is embedded in another URL:

Pattern here is: "/track/click/{id}/{url}/title"

 I have tried gorilla/mux and bmizerany/pat but they did not help either. Then I wrote https://github.com/cenkalti/remux

I guess it may be useful for someone who need this.

Cenk Altı

unread,
Nov 25, 2014, 2:04:35 PM11/25/14
to golan...@googlegroups.com, buet...@google.com
Correction: Pattern should be "/track/click/{id}/{url}/{title}"

Stephen Day

unread,
Nov 26, 2014, 4:12:11 PM11/26/14
to golan...@googlegroups.com, buet...@google.com
I'm not sure if this will helps, but having the url embedded as a path component is asking for trouble. Detecting the end of the url should be as simple as finding the first unencoded slash. However, passing that url through several, non-standard systems that don't handle encoding carefully may lead to very surprising results.
Reply all
Reply to author
Forward
0 new messages