mirror of
https://github.com/golang/go
synced 2024-11-24 17:10:03 -07:00
net/http: panic on duplicate registrations
Otherwise, the registration semantics are init-order-dependent, which I was trying very hard to avoid in the API. This may break broken programs. Fixes #2900. R=golang-dev, r, bradfitz, dsymonds, balasanjay, kevlar CC=golang-dev https://golang.org/cl/5644051
This commit is contained in:
parent
49110eaa22
commit
d0dc68901a
@ -1146,10 +1146,16 @@ The affected items are:
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Also, the <code>Request.RawURL</code> field has been removed; it was a
|
||||
The <code>Request.RawURL</code> field has been removed; it was a
|
||||
historical artifact.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>Handle</code> and <code>HandleFunc</code>
|
||||
functions, and the similarly-named methods of <code>ServeMux</code>,
|
||||
now panic if an attempt is made to register the same pattern twice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<em>Updating</em>:
|
||||
Running <code>go fix</code> will update the few programs that are affected except for
|
||||
|
@ -1049,10 +1049,16 @@ The affected items are:
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Also, the <code>Request.RawURL</code> field has been removed; it was a
|
||||
The <code>Request.RawURL</code> field has been removed; it was a
|
||||
historical artifact.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>Handle</code> and <code>HandleFunc</code>
|
||||
functions, and the similarly-named methods of <code>ServeMux</code>,
|
||||
now panic if an attempt is made to register the same pattern twice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<em>Updating</em>:
|
||||
Running <code>go fix</code> will update the few programs that are affected except for
|
||||
|
@ -833,11 +833,17 @@ func RedirectHandler(url string, code int) Handler {
|
||||
// redirecting any request containing . or .. elements to an
|
||||
// equivalent .- and ..-free URL.
|
||||
type ServeMux struct {
|
||||
m map[string]Handler
|
||||
mu sync.RWMutex
|
||||
m map[string]muxEntry
|
||||
}
|
||||
|
||||
type muxEntry struct {
|
||||
explicit bool
|
||||
h Handler
|
||||
}
|
||||
|
||||
// NewServeMux allocates and returns a new ServeMux.
|
||||
func NewServeMux() *ServeMux { return &ServeMux{make(map[string]Handler)} }
|
||||
func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} }
|
||||
|
||||
// DefaultServeMux is the default ServeMux used by Serve.
|
||||
var DefaultServeMux = NewServeMux()
|
||||
@ -883,12 +889,28 @@ func (mux *ServeMux) match(path string) Handler {
|
||||
}
|
||||
if h == nil || len(k) > n {
|
||||
n = len(k)
|
||||
h = v
|
||||
h = v.h
|
||||
}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// handler returns the handler to use for the request r.
|
||||
func (mux *ServeMux) handler(r *Request) Handler {
|
||||
mux.mu.RLock()
|
||||
defer mux.mu.RUnlock()
|
||||
|
||||
// Host-specific pattern takes precedence over generic ones
|
||||
h := mux.match(r.Host + r.URL.Path)
|
||||
if h == nil {
|
||||
h = mux.match(r.URL.Path)
|
||||
}
|
||||
if h == nil {
|
||||
h = NotFoundHandler()
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
// ServeHTTP dispatches the request to the handler whose
|
||||
// pattern most closely matches the request URL.
|
||||
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
||||
@ -898,30 +920,33 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
||||
w.WriteHeader(StatusMovedPermanently)
|
||||
return
|
||||
}
|
||||
// Host-specific pattern takes precedence over generic ones
|
||||
h := mux.match(r.Host + r.URL.Path)
|
||||
if h == nil {
|
||||
h = mux.match(r.URL.Path)
|
||||
}
|
||||
if h == nil {
|
||||
h = NotFoundHandler()
|
||||
}
|
||||
h.ServeHTTP(w, r)
|
||||
mux.handler(r).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// Handle registers the handler for the given pattern.
|
||||
// If a handler already exists for pattern, Handle panics.
|
||||
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||
mux.mu.Lock()
|
||||
defer mux.mu.Unlock()
|
||||
|
||||
if pattern == "" {
|
||||
panic("http: invalid pattern " + pattern)
|
||||
}
|
||||
if handler == nil {
|
||||
panic("http: nil handler")
|
||||
}
|
||||
if mux.m[pattern].explicit {
|
||||
panic("http: multiple registrations for " + pattern)
|
||||
}
|
||||
|
||||
mux.m[pattern] = handler
|
||||
mux.m[pattern] = muxEntry{explicit: true, h: handler}
|
||||
|
||||
// Helpful behavior:
|
||||
// If pattern is /tree/, insert permanent redirect for /tree.
|
||||
// If pattern is /tree/, insert an implicit permanent redirect for /tree.
|
||||
// It can be overridden by an explicit registration.
|
||||
n := len(pattern)
|
||||
if n > 0 && pattern[n-1] == '/' {
|
||||
mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently)
|
||||
if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
|
||||
mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(pattern, StatusMovedPermanently)}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user