diff options
Diffstat (limited to 'src/pkg/http/server.go')
-rw-r--r-- | src/pkg/http/server.go | 72 |
1 files changed, 43 insertions, 29 deletions
diff --git a/src/pkg/http/server.go b/src/pkg/http/server.go index b8783da28..6672c494b 100644 --- a/src/pkg/http/server.go +++ b/src/pkg/http/server.go @@ -181,7 +181,9 @@ func (c *conn) readRequest() (w *response, err os.Error) { w.SetHeader("Content-Type", "text/html; charset=utf-8") w.SetHeader("Date", time.UTC().Format(TimeFormat)) - if req.ProtoAtLeast(1, 1) { + if req.Method == "HEAD" { + // do nothing + } else if req.ProtoAtLeast(1, 1) { // HTTP/1.1 or greater: use chunked transfer encoding // to avoid closing the connection at EOF. w.chunking = true @@ -227,6 +229,10 @@ func (w *response) WriteHeader(code int) { w.header["Transfer-Encoding"] = "", false w.chunking = false } + // Cannot use Content-Length with non-identity Transfer-Encoding. + if w.chunking { + w.header["Content-Length"] = "", false + } if !w.req.ProtoAtLeast(1, 0) { return } @@ -268,7 +274,7 @@ func (w *response) Write(data []byte) (n int, err os.Error) { return 0, nil } - if w.status == StatusNotModified { + if w.status == StatusNotModified || w.req.Method == "HEAD" { // Must not have body. return 0, ErrBodyNotAllowed } @@ -495,11 +501,11 @@ func Redirect(w ResponseWriter, r *Request, url string, code int) { // RFC2616 recommends that a short note "SHOULD" be included in the // response because older user agents may not understand 301/307. - note := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n" - if r.Method == "POST" { - note = "" + // Shouldn't send the response for POST or HEAD; that leaves GET. + if r.Method == "GET" { + note := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n" + fmt.Fprintln(w, note) } - fmt.Fprintln(w, note) } func htmlEscape(s string) string { @@ -533,9 +539,8 @@ func RedirectHandler(url string, code int) Handler { // patterns and calls the handler for the pattern that // most closely matches the URL. // -// Patterns named fixed paths, like "/favicon.ico", -// or subtrees, like "/images/" (note the trailing slash). -// Patterns must begin with /. +// Patterns named fixed, rooted paths, like "/favicon.ico", +// or rooted subtrees, like "/images/" (note the trailing slash). // Longer patterns take precedence over shorter ones, so that // if there are handlers registered for both "/images/" // and "/images/thumbnails/", the latter handler will be @@ -543,11 +548,11 @@ func RedirectHandler(url string, code int) Handler { // former will receiver requests for any other paths in the // "/images/" subtree. // -// In the future, the pattern syntax may be relaxed to allow -// an optional host-name at the beginning of the pattern, -// so that a handler might register for the two patterns -// "/codesearch" and "codesearch.google.com/" -// without taking over requests for http://www.google.com/. +// Patterns may optionally begin with a host name, restricting matches to +// URLs on that host only. Host-specific patterns take precedence over +// general patterns, so that a handler might register for the two patterns +// "/codesearch" and "codesearch.google.com/" without also taking over +// requests for "http://www.google.com/". // // ServeMux also takes care of sanitizing the URL request path, // redirecting any request containing . or .. elements to an @@ -592,21 +597,13 @@ func cleanPath(p string) string { return np } -// 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 - } - - // Most-specific (longest) pattern wins. +// Find a handler on a handler map given a path string +// Most-specific (longest) pattern wins +func (mux *ServeMux) match(path string) Handler { var h Handler var n = 0 for k, v := range mux.m { - if !pathMatch(k, r.URL.Path) { + if !pathMatch(k, path) { continue } if h == nil || len(k) > n { @@ -614,6 +611,23 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { 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 { h = NotFoundHandler() } @@ -622,7 +636,7 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { // Handle registers the handler for the given pattern. func (mux *ServeMux) Handle(pattern string, handler Handler) { - if pattern == "" || pattern[0] != '/' { + if pattern == "" { panic("http: invalid pattern " + pattern) } @@ -697,7 +711,7 @@ func Serve(l net.Listener, handler Handler) os.Error { // http.HandleFunc("/hello", HelloServer) // err := http.ListenAndServe(":12345", nil) // if err != nil { -// log.Exit("ListenAndServe: ", err.String()) +// log.Fatal("ListenAndServe: ", err.String()) // } // } func ListenAndServe(addr string, handler Handler) os.Error { @@ -731,7 +745,7 @@ func ListenAndServe(addr string, handler Handler) os.Error { // log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/") // err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil) // if err != nil { -// log.Exit(err) +// log.Fatal(err) // } // } // |