You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='* REMOVED TO PREVENT LOCAL PATHS FROM BEING LEAKED */go-build'
GOENV='* REMOVED TO PREVENT LOCAL PATHS FROM BEING LEAKED */go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='* REMOVED TO PREVENT LOCAL PATHS FROM BEING LEAKED */pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='* REMOVED TO PREVENT LOCAL PATHS FROM BEING LEAKED *'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='* REMOVED TO PREVENT LOCAL PATHS FROM BEING LEAKED *'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='* REMOVED TO PREVENT LOCAL PATHS FROM BEING LEAKED */pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.23.0'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='* REMOVED TO PREVENT LOCAL PATHS FROM BEING LEAKED *'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='servemuxpoc/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build618692677=/tmp/go-build -gno-record-gcc-switches'
In the above Go Playground example, I'm registering a single http.HandleFunc with a http.ServeMux and leveraging
the new pattern format to require both the path, /hello, and method, HTTP GET to match for the request to be handled.
Once registered, I create an http.Server and run it in a goroutine. Afterward, I begin sending 2 requests to the server.
The first request contains // at the beginning of it's path and the second request does not. Note, both requests are sent
with the HTTP POST method.
What did you see happen?
with duplicated slash in url path
request POST http://[::]:29142//hello
received request POST //hello
writing response 301
received request GET /hello
writing response 500
response 500 GET
without duplicated slash in url path
request POST http://[::]:29142/hello
received request POST /hello
writing response 405
response 405 Method Not Allowed
The first request actually executes the HTTP GET pattern handler which results in a HTTP 500 status code being returned.
The second request did not execute the HTTP GET pattern handler and received a HTTP 405 status code.
What did you expect to see?
For the both requests, I expected to receive a HTTP 405 Method Not Allowed to be returned since each request method is HTTP POST.
which along with the logs seen in the output of the Go Playground example all lead to the first request being matched to http.RedirectHandler.
Now, I understand that http.RedirectHandler is expected behaviour but I believe this scenario to be a particular edge case
that leads to 2 expectations to collide. That being the request method matching of http.ServeMux and the http.RedirectHandler
behviour. As a user, I was geniunely surprised to not receive a 405 for POST //hello since cleaning //hello makes it /hello.
I think in this situation the HTTP method should be validated before http.RedirectHandler is returned but I'd love to hear others
thoughts on this behaviour.
NOTE: this is an edge case that only happens for patterns whose method for matching happens to be HTTP GET since http.RedirectHandler redirects via HTTP GET i.e. incoming HTTP POST //hello -> redirect to HTTP GET /hello
The text was updated successfully, but these errors were encountered:
The behavior you're experiencing is the one described in issue #60769. The current behavior is correct. Returning a 308 status instead of 301 would be more desirable, however, as discussed in issue #60769, there is a compatibility issue with older clients that do not recognize the 308 status.
Go version
go version go1.23.0 linux/amd64
Output of
go env
in your module/workspace:What did you do?
https://go.dev/play/p/_3usVyrcn1V
In the above Go Playground example, I'm registering a single
http.HandleFunc
with ahttp.ServeMux
and leveragingthe new pattern format to require both the path,
/hello
, and method,HTTP GET
to match for the request to be handled.Once registered, I create an
http.Server
and run it in a goroutine. Afterward, I begin sending 2 requests to the server.The first request contains
//
at the beginning of it's path and the second request does not. Note, both requests are sentwith the
HTTP POST
method.What did you see happen?
The first request actually executes the
HTTP GET
pattern handler which results in aHTTP 500
status code being returned.The second request did not execute the
HTTP GET
pattern handler and received aHTTP 405
status code.What did you expect to see?
For the both requests, I expected to receive a
HTTP 405 Method Not Allowed
to be returned since each request method isHTTP POST
.After investigating, I came across the following:
which along with the logs seen in the output of the Go Playground example all lead to the first request being matched to
http.RedirectHandler
.Now, I understand that
http.RedirectHandler
is expected behaviour but I believe this scenario to be a particular edge casethat leads to 2 expectations to collide. That being the request method matching of
http.ServeMux
and thehttp.RedirectHandler
behviour. As a user, I was geniunely surprised to not receive a
405
forPOST //hello
since cleaning//hello
makes it/hello
.I think in this situation the HTTP method should be validated before
http.RedirectHandler
is returned but I'd love to hear othersthoughts on this behaviour.
NOTE: this is an edge case that only happens for patterns whose method for matching happens to be
HTTP GET
sincehttp.RedirectHandler
redirects viaHTTP GET
i.e. incomingHTTP POST //hello
-> redirect toHTTP GET /hello
The text was updated successfully, but these errors were encountered: