mirror of
https://github.com/golang/go
synced 2024-11-24 19:30:42 -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>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<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.
|
historical artifact.
|
||||||
</p>
|
</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>
|
<p>
|
||||||
<em>Updating</em>:
|
<em>Updating</em>:
|
||||||
Running <code>go fix</code> will update the few programs that are affected except for
|
Running <code>go fix</code> will update the few programs that are affected except for
|
||||||
|
@ -1049,10 +1049,16 @@ The affected items are:
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<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.
|
historical artifact.
|
||||||
</p>
|
</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>
|
<p>
|
||||||
<em>Updating</em>:
|
<em>Updating</em>:
|
||||||
Running <code>go fix</code> will update the few programs that are affected except for
|
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
|
// redirecting any request containing . or .. elements to an
|
||||||
// equivalent .- and ..-free URL.
|
// equivalent .- and ..-free URL.
|
||||||
type ServeMux struct {
|
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.
|
// 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.
|
// DefaultServeMux is the default ServeMux used by Serve.
|
||||||
var DefaultServeMux = NewServeMux()
|
var DefaultServeMux = NewServeMux()
|
||||||
@ -883,12 +889,28 @@ func (mux *ServeMux) match(path string) Handler {
|
|||||||
}
|
}
|
||||||
if h == nil || len(k) > n {
|
if h == nil || len(k) > n {
|
||||||
n = len(k)
|
n = len(k)
|
||||||
h = v
|
h = v.h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 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
|
// ServeHTTP dispatches the request to the handler whose
|
||||||
// pattern most closely matches the request URL.
|
// pattern most closely matches the request URL.
|
||||||
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
||||||
@ -898,30 +920,33 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
|||||||
w.WriteHeader(StatusMovedPermanently)
|
w.WriteHeader(StatusMovedPermanently)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Host-specific pattern takes precedence over generic ones
|
mux.handler(r).ServeHTTP(w, r)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle registers the handler for the given pattern.
|
// 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) {
|
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||||
|
mux.mu.Lock()
|
||||||
|
defer mux.mu.Unlock()
|
||||||
|
|
||||||
if pattern == "" {
|
if pattern == "" {
|
||||||
panic("http: invalid pattern " + 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:
|
// 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)
|
n := len(pattern)
|
||||||
if n > 0 && pattern[n-1] == '/' {
|
if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
|
||||||
mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently)
|
mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(pattern, StatusMovedPermanently)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user