Commit 865d5767 authored by Jose Luis Vázquez González's avatar Jose Luis Vázquez González Committed by Russ Cox

http: add host patterns

R=bradfitzgo, rsc
CC=golang-dev
https://golang.org/cl/4070043
parent 9557103e
...@@ -136,6 +136,71 @@ func TestConsumingBodyOnNextConn(t *testing.T) { ...@@ -136,6 +136,71 @@ func TestConsumingBodyOnNextConn(t *testing.T) {
} }
} }
type stringHandler string
func (s stringHandler) ServeHTTP(w ResponseWriter, r *Request) {
w.SetHeader("Result", string(s))
}
var handlers = []struct {
pattern string
msg string
}{
{"/", "Default"},
{"/someDir/", "someDir"},
{"someHost.com/someDir/", "someHost.com/someDir"},
}
var vtests = []struct {
url string
expected string
}{
{"http://localhost/someDir/apage", "someDir"},
{"http://localhost/otherDir/apage", "Default"},
{"http://someHost.com/someDir/apage", "someHost.com/someDir"},
{"http://otherHost.com/someDir/apage", "someDir"},
{"http://otherHost.com/aDir/apage", "Default"},
}
func TestHostHandlers(t *testing.T) {
for _, h := range handlers {
Handle(h.pattern, stringHandler(h.msg))
}
l, err := net.Listen("tcp", "127.0.0.1:0") // any port
if err != nil {
t.Fatal(err)
}
defer l.Close()
go Serve(l, nil)
conn, err := net.Dial("tcp", "", l.Addr().String())
if err != nil {
t.Fatal(err)
}
defer conn.Close()
cc := NewClientConn(conn, nil)
for _, vt := range vtests {
var r *Response
var req Request
if req.URL, err = ParseURL(vt.url); err != nil {
t.Errorf("cannot parse url: %v", err)
continue
}
if err := cc.Write(&req); err != nil {
t.Errorf("writing request: %v", err)
continue
}
r, err := cc.Read()
if err != nil {
t.Errorf("reading response: %v", err)
continue
}
s := r.Header["Result"]
if s != vt.expected {
t.Errorf("Get(%q) = %q, want %q", vt.url, s, vt.expected)
}
}
}
type responseWriterMethodCall struct { type responseWriterMethodCall struct {
method string method string
headerKey, headerValue string // if method == "SetHeader" headerKey, headerValue string // if method == "SetHeader"
......
...@@ -539,9 +539,8 @@ func RedirectHandler(url string, code int) Handler { ...@@ -539,9 +539,8 @@ func RedirectHandler(url string, code int) Handler {
// patterns and calls the handler for the pattern that // patterns and calls the handler for the pattern that
// most closely matches the URL. // most closely matches the URL.
// //
// Patterns named fixed paths, like "/favicon.ico", // Patterns named fixed, rooted paths, like "/favicon.ico",
// or subtrees, like "/images/" (note the trailing slash). // or rooted subtrees, like "/images/" (note the trailing slash).
// Patterns must begin with /.
// Longer patterns take precedence over shorter ones, so that // Longer patterns take precedence over shorter ones, so that
// if there are handlers registered for both "/images/" // if there are handlers registered for both "/images/"
// and "/images/thumbnails/", the latter handler will be // and "/images/thumbnails/", the latter handler will be
...@@ -549,11 +548,11 @@ func RedirectHandler(url string, code int) Handler { ...@@ -549,11 +548,11 @@ func RedirectHandler(url string, code int) Handler {
// former will receiver requests for any other paths in the // former will receiver requests for any other paths in the
// "/images/" subtree. // "/images/" subtree.
// //
// In the future, the pattern syntax may be relaxed to allow // Patterns may optionally begin with a host name, restricting matches to
// an optional host-name at the beginning of the pattern, // URLs on that host only. Host-specific patterns take precedence over
// so that a handler might register for the two patterns // general patterns, so that a handler might register for the two patterns
// "/codesearch" and "codesearch.google.com/" // "/codesearch" and "codesearch.google.com/" without also taking over
// without taking over requests for http://www.google.com/. // requests for "http://www.google.com/".
// //
// ServeMux also takes care of sanitizing the URL request path, // ServeMux also takes care of sanitizing the URL request path,
// redirecting any request containing . or .. elements to an // redirecting any request containing . or .. elements to an
...@@ -598,21 +597,13 @@ func cleanPath(p string) string { ...@@ -598,21 +597,13 @@ func cleanPath(p string) string {
return np return np
} }
// ServeHTTP dispatches the request to the handler whose // Find a handler on a handler map given a path string
// pattern most closely matches the request URL. // Most-specific (longest) pattern wins
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { func (mux *ServeMux) match(path string) Handler {
// Clean path to canonical form and redirect.
if p := cleanPath(r.URL.Path); p != r.URL.Path {
w.SetHeader("Location", p)
w.WriteHeader(StatusMovedPermanently)
return
}
// Most-specific (longest) pattern wins.
var h Handler var h Handler
var n = 0 var n = 0
for k, v := range mux.m { for k, v := range mux.m {
if !pathMatch(k, r.URL.Path) { if !pathMatch(k, path) {
continue continue
} }
if h == nil || len(k) > n { if h == nil || len(k) > n {
...@@ -620,6 +611,23 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { ...@@ -620,6 +611,23 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
h = v h = v
} }
} }
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) {
// Clean path to canonical form and redirect.
if p := cleanPath(r.URL.Path); p != r.URL.Path {
w.SetHeader("Location", p)
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 { if h == nil {
h = NotFoundHandler() h = NotFoundHandler()
} }
...@@ -628,7 +636,7 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { ...@@ -628,7 +636,7 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
// Handle registers the handler for the given pattern. // Handle registers the handler for the given pattern.
func (mux *ServeMux) Handle(pattern string, handler Handler) { func (mux *ServeMux) Handle(pattern string, handler Handler) {
if pattern == "" || pattern[0] != '/' { if pattern == "" {
panic("http: invalid pattern " + pattern) panic("http: invalid pattern " + pattern)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment