Skip to content

net/http: Conflicts with pattern when using NewServeMux #68838

Closed as not planned
@bentcoder

Description

@bentcoder

Go version

go version go1.22.0 darwin/amd64

Output of go env in your module/workspace:

GO111MODULE='on'
GOARCH='amd64'
GOBIN=''
GOCACHE='/Users/me/Library/Caches/go-build'
GOENV='/Users/me/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/me/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/me/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/Cellar/go/1.22.0/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/Cellar/go/1.22.0/libexec/pkg/tool/darwin_amd64'
GOVCS=''
GOVERSION='go1.22.0'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/dev/null'
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 -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/4d/gcwrbh1s0nz1xhvb6mbfsv840000gn/T/go-build3252772856=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

package main

import (
	"net/http"
)

func main() {
	rtr := http.NewServeMux()
	rtr.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`GET /users/{id}`)) })
	rtr.HandleFunc("GET /{ver}/users", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`GET /{ver}/users`)) })

	http.ListenAndServe(":1234", rtr)
}

What did you see happen?

panic: pattern "GET /{ver}/users" (registered at /Users/me/dev/golang/mix/rest/main.go:10) conflicts with pattern "GET /users/{id}" (registered at /Users/me/dev/golang/mix/rest/main.go:9):
GET /{ver}/users and GET /users/{id} both match some paths, like "/users/users".
But neither is more specific than the other.
GET /{ver}/users matches "/ver/users", but GET /users/{id} doesn't.
GET /users/{id} matches "/users/id", but GET /{ver}/users doesn't.

goroutine 1 [running]:
net/http.(*ServeMux).register(...)
        /usr/local/Cellar/go/1.22.0/libexec/src/net/http/server.go:2733
net/http.(*ServeMux).HandleFunc(0xc00011ab60, {0x35d1977, 0x10}, 0x36cf208)
        /usr/local/Cellar/go/1.22.0/libexec/src/net/http/server.go:2707 +0xb2
main.main()
        /Users/me/dev/golang/mix/rest/main.go:10 +0xad
exit status 2

What did you expect to see?

I expected this routing setup to work because routes below are not same. The {ver} is a dynamic hence adjustable by client.

GET /users/111
GET /users/222

GET /aaa/users
GET /bbb/users
GET /ccc/users

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions