Skip to content

net/http: StripPrefix does not preserve url path #24366

Closed
@cjellick

Description

@cjellick

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.10 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"

What did you do?

The http.StripPrefix handler doesnt preserve the original path of the request. Specifically, it completely unescapes it, replacing %2F with /, for example.
It also causes url.Path, url.RawPath, and url.EncodedPath() to become inconsistent with each other.

You can reproduce with the following program:

package main

import (
	"fmt"
	"net/http"
)

type exampleHandler struct {}

func (h *exampleHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "url.Path: %v\n", req.URL.Path)
	fmt.Fprintf(w, "url.RawPath: %v\n", req.URL.RawPath)
	fmt.Fprintf(w, "url.EscapedPath(): %v\n", req.URL.EscapedPath())
}

func main() {
	sp := http.StripPrefix("/foo/", &exampleHandler{})

	// server on port 8888 uses StripPrefix
	server := &http.Server{
		Addr: ":8888",
		Handler: sp,
	}
	go server.ListenAndServe()

	// server on port 9999 does not use StripPrefix
	server2 := &http.Server{
		Addr: ":9999",
		Handler: &exampleHandler{},
	}
	server2.ListenAndServe()
}

What did you expect to see?

I expected to see

curl 'http://localhost:8888/foo/%2Fgoogle.com'
url.Path: %2Fgoogle.com
url.RawPath: %2Fgoogle.com
url.EscapedPath(): %2Fgoogle.com

What did you see instead?

This is the actual output:

curl 'http://localhost:8888/foo/%2Fgoogle.com'
url.Path: /google.com
url.RawPath: /foo/%2Fgoogle.com
url.EscapedPath(): /google.com

So to reiterate, I think EscapePath() should return a version of the path with all the original escaping and I think RawPath should be insync with Path and EscapedPath()

For a comparison, this is what the endpoint that doesnt use StripPrefix outputs:

curl 'http://localhost:9999/foo/%2Fgoogle.com'
url.Path: /foo//google.com
url.RawPath: /foo/%2Fgoogle.com
url.EscapedPath(): /foo/%2Fgoogle.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions