aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/http/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/http/server.go')
-rw-r--r--libgo/go/net/http/server.go1189
1 files changed, 1189 insertions, 0 deletions
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
new file mode 100644
index 0000000..8c48894
--- /dev/null
+++ b/libgo/go/net/http/server.go
@@ -0,0 +1,1189 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// HTTP server. See RFC 2616.
+
+// TODO(rsc):
+// logging
+
+package http
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/rand"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/url"
+ "path"
+ "runtime/debug"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+// Errors introduced by the HTTP server.
+var (
+ ErrWriteAfterFlush = errors.New("Conn.Write called after Flush")
+ ErrBodyNotAllowed = errors.New("http: response status code does not allow body")
+ ErrHijacked = errors.New("Conn has been hijacked")
+ ErrContentLength = errors.New("Conn.Write wrote more than the declared Content-Length")
+)
+
+// Objects implementing the Handler interface can be
+// registered to serve a particular path or subtree
+// in the HTTP server.
+//
+// ServeHTTP should write reply headers and data to the ResponseWriter
+// and then return. Returning signals that the request is finished
+// and that the HTTP server can move on to the next request on
+// the connection.
+type Handler interface {
+ ServeHTTP(ResponseWriter, *Request)
+}
+
+// A ResponseWriter interface is used by an HTTP handler to
+// construct an HTTP response.
+type ResponseWriter interface {
+ // Header returns the header map that will be sent by WriteHeader.
+ // Changing the header after a call to WriteHeader (or Write) has
+ // no effect.
+ Header() Header
+
+ // Write writes the data to the connection as part of an HTTP reply.
+ // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
+ // before writing the data.
+ Write([]byte) (int, error)
+
+ // WriteHeader sends an HTTP response header with status code.
+ // If WriteHeader is not called explicitly, the first call to Write
+ // will trigger an implicit WriteHeader(http.StatusOK).
+ // Thus explicit calls to WriteHeader are mainly used to
+ // send error codes.
+ WriteHeader(int)
+}
+
+// The Flusher interface is implemented by ResponseWriters that allow
+// an HTTP handler to flush buffered data to the client.
+//
+// Note that even for ResponseWriters that support Flush,
+// if the client is connected through an HTTP proxy,
+// the buffered data may not reach the client until the response
+// completes.
+type Flusher interface {
+ // Flush sends any buffered data to the client.
+ Flush()
+}
+
+// The Hijacker interface is implemented by ResponseWriters that allow
+// an HTTP handler to take over the connection.
+type Hijacker interface {
+ // Hijack lets the caller take over the connection.
+ // After a call to Hijack(), the HTTP server library
+ // will not do anything else with the connection.
+ // It becomes the caller's responsibility to manage
+ // and close the connection.
+ Hijack() (net.Conn, *bufio.ReadWriter, error)
+}
+
+// A conn represents the server side of an HTTP connection.
+type conn struct {
+ remoteAddr string // network address of remote side
+ server *Server // the Server on which the connection arrived
+ rwc net.Conn // i/o connection
+ lr *io.LimitedReader // io.LimitReader(rwc)
+ buf *bufio.ReadWriter // buffered(lr,rwc), reading from bufio->limitReader->rwc
+ hijacked bool // connection has been hijacked by handler
+ tlsState *tls.ConnectionState // or nil when not using TLS
+ body []byte
+}
+
+// A response represents the server side of an HTTP response.
+type response struct {
+ conn *conn
+ req *Request // request for this response
+ chunking bool // using chunked transfer encoding for reply body
+ wroteHeader bool // reply header has been written
+ wroteContinue bool // 100 Continue response was written
+ header Header // reply header parameters
+ written int64 // number of bytes written in body
+ contentLength int64 // explicitly-declared Content-Length; or -1
+ status int // status code passed to WriteHeader
+ needSniff bool // need to sniff to find Content-Type
+
+ // close connection after this reply. set on request and
+ // updated after response from handler if there's a
+ // "Connection: keep-alive" response header and a
+ // Content-Length.
+ closeAfterReply bool
+
+ // requestBodyLimitHit is set by requestTooLarge when
+ // maxBytesReader hits its max size. It is checked in
+ // WriteHeader, to make sure we don't consume the the
+ // remaining request body to try to advance to the next HTTP
+ // request. Instead, when this is set, we stop doing
+ // subsequent requests on this connection and stop reading
+ // input from it.
+ requestBodyLimitHit bool
+}
+
+// requestTooLarge is called by maxBytesReader when too much input has
+// been read from the client.
+func (w *response) requestTooLarge() {
+ w.closeAfterReply = true
+ w.requestBodyLimitHit = true
+ if !w.wroteHeader {
+ w.Header().Set("Connection", "close")
+ }
+}
+
+type writerOnly struct {
+ io.Writer
+}
+
+func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
+ // Flush before checking w.chunking, as Flush will call
+ // WriteHeader if it hasn't been called yet, and WriteHeader
+ // is what sets w.chunking.
+ w.Flush()
+ if !w.chunking && w.bodyAllowed() && !w.needSniff {
+ if rf, ok := w.conn.rwc.(io.ReaderFrom); ok {
+ n, err = rf.ReadFrom(src)
+ w.written += n
+ return
+ }
+ }
+ // Fall back to default io.Copy implementation.
+ // Use wrapper to hide w.ReadFrom from io.Copy.
+ return io.Copy(writerOnly{w}, src)
+}
+
+// noLimit is an effective infinite upper bound for io.LimitedReader
+const noLimit int64 = (1 << 63) - 1
+
+// Create new connection from rwc.
+func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
+ c = new(conn)
+ c.remoteAddr = rwc.RemoteAddr().String()
+ c.server = srv
+ c.rwc = rwc
+ c.body = make([]byte, sniffLen)
+ c.lr = io.LimitReader(rwc, noLimit).(*io.LimitedReader)
+ br := bufio.NewReader(c.lr)
+ bw := bufio.NewWriter(rwc)
+ c.buf = bufio.NewReadWriter(br, bw)
+ return c, nil
+}
+
+// DefaultMaxHeaderBytes is the maximum permitted size of the headers
+// in an HTTP request.
+// This can be overridden by setting Server.MaxHeaderBytes.
+const DefaultMaxHeaderBytes = 1 << 20 // 1 MB
+
+func (srv *Server) maxHeaderBytes() int {
+ if srv.MaxHeaderBytes > 0 {
+ return srv.MaxHeaderBytes
+ }
+ return DefaultMaxHeaderBytes
+}
+
+// wrapper around io.ReaderCloser which on first read, sends an
+// HTTP/1.1 100 Continue header
+type expectContinueReader struct {
+ resp *response
+ readCloser io.ReadCloser
+ closed bool
+}
+
+func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
+ if ecr.closed {
+ return 0, errors.New("http: Read after Close on request Body")
+ }
+ if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked {
+ ecr.resp.wroteContinue = true
+ io.WriteString(ecr.resp.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n")
+ ecr.resp.conn.buf.Flush()
+ }
+ return ecr.readCloser.Read(p)
+}
+
+func (ecr *expectContinueReader) Close() error {
+ ecr.closed = true
+ return ecr.readCloser.Close()
+}
+
+// TimeFormat is the time format to use with
+// time.Parse and time.Time.Format when parsing
+// or generating times in HTTP headers.
+// It is like time.RFC1123 but hard codes GMT as the time zone.
+const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
+
+var errTooLarge = errors.New("http: request too large")
+
+// Read next request from connection.
+func (c *conn) readRequest() (w *response, err error) {
+ if c.hijacked {
+ return nil, ErrHijacked
+ }
+ c.lr.N = int64(c.server.maxHeaderBytes()) + 4096 /* bufio slop */
+ var req *Request
+ if req, err = ReadRequest(c.buf.Reader); err != nil {
+ if c.lr.N == 0 {
+ return nil, errTooLarge
+ }
+ return nil, err
+ }
+ c.lr.N = noLimit
+
+ req.RemoteAddr = c.remoteAddr
+ req.TLS = c.tlsState
+
+ w = new(response)
+ w.conn = c
+ w.req = req
+ w.header = make(Header)
+ w.contentLength = -1
+ c.body = c.body[:0]
+ return w, nil
+}
+
+func (w *response) Header() Header {
+ return w.header
+}
+
+// maxPostHandlerReadBytes is the max number of Request.Body bytes not
+// consumed by a handler that the server will read from the a client
+// in order to keep a connection alive. If there are more bytes than
+// this then the server to be paranoid instead sends a "Connection:
+// close" response.
+//
+// This number is approximately what a typical machine's TCP buffer
+// size is anyway. (if we have the bytes on the machine, we might as
+// well read them)
+const maxPostHandlerReadBytes = 256 << 10
+
+func (w *response) WriteHeader(code int) {
+ if w.conn.hijacked {
+ log.Print("http: response.WriteHeader on hijacked connection")
+ return
+ }
+ if w.wroteHeader {
+ log.Print("http: multiple response.WriteHeader calls")
+ return
+ }
+ w.wroteHeader = true
+ w.status = code
+
+ // Check for a explicit (and valid) Content-Length header.
+ var hasCL bool
+ var contentLength int64
+ if clenStr := w.header.Get("Content-Length"); clenStr != "" {
+ var err error
+ contentLength, err = strconv.Atoi64(clenStr)
+ if err == nil {
+ hasCL = true
+ } else {
+ log.Printf("http: invalid Content-Length of %q sent", clenStr)
+ w.header.Del("Content-Length")
+ }
+ }
+
+ if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
+ _, connectionHeaderSet := w.header["Connection"]
+ if !connectionHeaderSet {
+ w.header.Set("Connection", "keep-alive")
+ }
+ } else if !w.req.ProtoAtLeast(1, 1) {
+ // Client did not ask to keep connection alive.
+ w.closeAfterReply = true
+ }
+
+ if w.header.Get("Connection") == "close" {
+ w.closeAfterReply = true
+ }
+
+ // Per RFC 2616, we should consume the request body before
+ // replying, if the handler hasn't already done so. But we
+ // don't want to do an unbounded amount of reading here for
+ // DoS reasons, so we only try up to a threshold.
+ if w.req.ContentLength != 0 && !w.closeAfterReply {
+ ecr, isExpecter := w.req.Body.(*expectContinueReader)
+ if !isExpecter || ecr.resp.wroteContinue {
+ n, _ := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
+ if n >= maxPostHandlerReadBytes {
+ w.requestTooLarge()
+ w.header.Set("Connection", "close")
+ } else {
+ w.req.Body.Close()
+ }
+ }
+ }
+
+ if code == StatusNotModified {
+ // Must not have body.
+ for _, header := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
+ if w.header.Get(header) != "" {
+ // TODO: return an error if WriteHeader gets a return parameter
+ // or set a flag on w to make future Writes() write an error page?
+ // for now just log and drop the header.
+ log.Printf("http: StatusNotModified response with header %q defined", header)
+ w.header.Del(header)
+ }
+ }
+ } else {
+ // If no content type, apply sniffing algorithm to body.
+ if w.header.Get("Content-Type") == "" {
+ w.needSniff = true
+ }
+ }
+
+ if _, ok := w.header["Date"]; !ok {
+ w.Header().Set("Date", time.UTC().Format(TimeFormat))
+ }
+
+ te := w.header.Get("Transfer-Encoding")
+ hasTE := te != ""
+ if hasCL && hasTE && te != "identity" {
+ // TODO: return an error if WriteHeader gets a return parameter
+ // For now just ignore the Content-Length.
+ log.Printf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
+ te, contentLength)
+ w.header.Del("Content-Length")
+ hasCL = false
+ }
+
+ if w.req.Method == "HEAD" || code == StatusNotModified {
+ // do nothing
+ } else if hasCL {
+ w.contentLength = contentLength
+ w.header.Del("Transfer-Encoding")
+ } else if w.req.ProtoAtLeast(1, 1) {
+ // HTTP/1.1 or greater: use chunked transfer encoding
+ // to avoid closing the connection at EOF.
+ // TODO: this blows away any custom or stacked Transfer-Encoding they
+ // might have set. Deal with that as need arises once we have a valid
+ // use case.
+ w.chunking = true
+ w.header.Set("Transfer-Encoding", "chunked")
+ } else {
+ // HTTP version < 1.1: cannot do chunked transfer
+ // encoding and we don't know the Content-Length so
+ // signal EOF by closing connection.
+ w.closeAfterReply = true
+ w.header.Del("Transfer-Encoding") // in case already set
+ }
+
+ // Cannot use Content-Length with non-identity Transfer-Encoding.
+ if w.chunking {
+ w.header.Del("Content-Length")
+ }
+ if !w.req.ProtoAtLeast(1, 0) {
+ return
+ }
+ proto := "HTTP/1.0"
+ if w.req.ProtoAtLeast(1, 1) {
+ proto = "HTTP/1.1"
+ }
+ codestring := strconv.Itoa(code)
+ text, ok := statusText[code]
+ if !ok {
+ text = "status code " + codestring
+ }
+ io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
+ w.header.Write(w.conn.buf)
+
+ // If we need to sniff the body, leave the header open.
+ // Otherwise, end it here.
+ if !w.needSniff {
+ io.WriteString(w.conn.buf, "\r\n")
+ }
+}
+
+// sniff uses the first block of written data,
+// stored in w.conn.body, to decide the Content-Type
+// for the HTTP body.
+func (w *response) sniff() {
+ if !w.needSniff {
+ return
+ }
+ w.needSniff = false
+
+ data := w.conn.body
+ fmt.Fprintf(w.conn.buf, "Content-Type: %s\r\n\r\n", DetectContentType(data))
+
+ if len(data) == 0 {
+ return
+ }
+ if w.chunking {
+ fmt.Fprintf(w.conn.buf, "%x\r\n", len(data))
+ }
+ _, err := w.conn.buf.Write(data)
+ if w.chunking && err == nil {
+ io.WriteString(w.conn.buf, "\r\n")
+ }
+}
+
+// bodyAllowed returns true if a Write is allowed for this response type.
+// It's illegal to call this before the header has been flushed.
+func (w *response) bodyAllowed() bool {
+ if !w.wroteHeader {
+ panic("")
+ }
+ return w.status != StatusNotModified && w.req.Method != "HEAD"
+}
+
+func (w *response) Write(data []byte) (n int, err error) {
+ if w.conn.hijacked {
+ log.Print("http: response.Write on hijacked connection")
+ return 0, ErrHijacked
+ }
+ if !w.wroteHeader {
+ w.WriteHeader(StatusOK)
+ }
+ if len(data) == 0 {
+ return 0, nil
+ }
+ if !w.bodyAllowed() {
+ return 0, ErrBodyNotAllowed
+ }
+
+ w.written += int64(len(data)) // ignoring errors, for errorKludge
+ if w.contentLength != -1 && w.written > w.contentLength {
+ return 0, ErrContentLength
+ }
+
+ var m int
+ if w.needSniff {
+ // We need to sniff the beginning of the output to
+ // determine the content type. Accumulate the
+ // initial writes in w.conn.body.
+ // Cap m so that append won't allocate.
+ m := cap(w.conn.body) - len(w.conn.body)
+ if m > len(data) {
+ m = len(data)
+ }
+ w.conn.body = append(w.conn.body, data[:m]...)
+ data = data[m:]
+ if len(data) == 0 {
+ // Copied everything into the buffer.
+ // Wait for next write.
+ return m, nil
+ }
+
+ // Filled the buffer; more data remains.
+ // Sniff the content (flushes the buffer)
+ // and then proceed with the remainder
+ // of the data as a normal Write.
+ // Calling sniff clears needSniff.
+ w.sniff()
+ }
+
+ // TODO(rsc): if chunking happened after the buffering,
+ // then there would be fewer chunk headers.
+ // On the other hand, it would make hijacking more difficult.
+ if w.chunking {
+ fmt.Fprintf(w.conn.buf, "%x\r\n", len(data)) // TODO(rsc): use strconv not fmt
+ }
+ n, err = w.conn.buf.Write(data)
+ if err == nil && w.chunking {
+ if n != len(data) {
+ err = io.ErrShortWrite
+ }
+ if err == nil {
+ io.WriteString(w.conn.buf, "\r\n")
+ }
+ }
+
+ return m + n, err
+}
+
+func (w *response) finishRequest() {
+ // If this was an HTTP/1.0 request with keep-alive and we sent a Content-Length
+ // back, we can make this a keep-alive response ...
+ if w.req.wantsHttp10KeepAlive() {
+ sentLength := w.header.Get("Content-Length") != ""
+ if sentLength && w.header.Get("Connection") == "keep-alive" {
+ w.closeAfterReply = false
+ }
+ }
+ if !w.wroteHeader {
+ w.WriteHeader(StatusOK)
+ }
+ if w.needSniff {
+ w.sniff()
+ }
+ if w.chunking {
+ io.WriteString(w.conn.buf, "0\r\n")
+ // trailer key/value pairs, followed by blank line
+ io.WriteString(w.conn.buf, "\r\n")
+ }
+ w.conn.buf.Flush()
+ // Close the body, unless we're about to close the whole TCP connection
+ // anyway.
+ if !w.closeAfterReply {
+ w.req.Body.Close()
+ }
+ if w.req.MultipartForm != nil {
+ w.req.MultipartForm.RemoveAll()
+ }
+
+ if w.contentLength != -1 && w.contentLength != w.written {
+ // Did not write enough. Avoid getting out of sync.
+ w.closeAfterReply = true
+ }
+}
+
+func (w *response) Flush() {
+ if !w.wroteHeader {
+ w.WriteHeader(StatusOK)
+ }
+ w.sniff()
+ w.conn.buf.Flush()
+}
+
+// Close the connection.
+func (c *conn) close() {
+ if c.buf != nil {
+ c.buf.Flush()
+ c.buf = nil
+ }
+ if c.rwc != nil {
+ c.rwc.Close()
+ c.rwc = nil
+ }
+}
+
+// Serve a new connection.
+func (c *conn) serve() {
+ defer func() {
+ err := recover()
+ if err == nil {
+ return
+ }
+ if c.rwc != nil { // may be nil if connection hijacked
+ c.rwc.Close()
+ }
+
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
+ buf.Write(debug.Stack())
+ log.Print(buf.String())
+ }()
+
+ if tlsConn, ok := c.rwc.(*tls.Conn); ok {
+ if err := tlsConn.Handshake(); err != nil {
+ c.close()
+ return
+ }
+ c.tlsState = new(tls.ConnectionState)
+ *c.tlsState = tlsConn.ConnectionState()
+ }
+
+ for {
+ w, err := c.readRequest()
+ if err != nil {
+ msg := "400 Bad Request"
+ if err == errTooLarge {
+ // Their HTTP client may or may not be
+ // able to read this if we're
+ // responding to them and hanging up
+ // while they're still writing their
+ // request. Undefined behavior.
+ msg = "413 Request Entity Too Large"
+ } else if err == io.ErrUnexpectedEOF {
+ break // Don't reply
+ } else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
+ break // Don't reply
+ }
+ fmt.Fprintf(c.rwc, "HTTP/1.1 %s\r\n\r\n", msg)
+ break
+ }
+
+ // Expect 100 Continue support
+ req := w.req
+ if req.expectsContinue() {
+ if req.ProtoAtLeast(1, 1) {
+ // Wrap the Body reader with one that replies on the connection
+ req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
+ }
+ if req.ContentLength == 0 {
+ w.Header().Set("Connection", "close")
+ w.WriteHeader(StatusBadRequest)
+ w.finishRequest()
+ break
+ }
+ req.Header.Del("Expect")
+ } else if req.Header.Get("Expect") != "" {
+ // TODO(bradfitz): let ServeHTTP handlers handle
+ // requests with non-standard expectation[s]? Seems
+ // theoretical at best, and doesn't fit into the
+ // current ServeHTTP model anyway. We'd need to
+ // make the ResponseWriter an optional
+ // "ExpectReplier" interface or something.
+ //
+ // For now we'll just obey RFC 2616 14.20 which says
+ // "If a server receives a request containing an
+ // Expect field that includes an expectation-
+ // extension that it does not support, it MUST
+ // respond with a 417 (Expectation Failed) status."
+ w.Header().Set("Connection", "close")
+ w.WriteHeader(StatusExpectationFailed)
+ w.finishRequest()
+ break
+ }
+
+ handler := c.server.Handler
+ if handler == nil {
+ handler = DefaultServeMux
+ }
+
+ // HTTP cannot have multiple simultaneous active requests.[*]
+ // Until the server replies to this request, it can't read another,
+ // so we might as well run the handler in this goroutine.
+ // [*] Not strictly true: HTTP pipelining. We could let them all process
+ // in parallel even if their responses need to be serialized.
+ handler.ServeHTTP(w, w.req)
+ if c.hijacked {
+ return
+ }
+ w.finishRequest()
+ if w.closeAfterReply {
+ break
+ }
+ }
+ c.close()
+}
+
+// Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
+// and a Hijacker.
+func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
+ if w.conn.hijacked {
+ return nil, nil, ErrHijacked
+ }
+ w.conn.hijacked = true
+ rwc = w.conn.rwc
+ buf = w.conn.buf
+ w.conn.rwc = nil
+ w.conn.buf = nil
+ return
+}
+
+// The HandlerFunc type is an adapter to allow the use of
+// ordinary functions as HTTP handlers. If f is a function
+// with the appropriate signature, HandlerFunc(f) is a
+// Handler object that calls f.
+type HandlerFunc func(ResponseWriter, *Request)
+
+// ServeHTTP calls f(w, r).
+func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
+ f(w, r)
+}
+
+// Helper handlers
+
+// Error replies to the request with the specified error message and HTTP code.
+func Error(w ResponseWriter, error string, code int) {
+ w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ w.WriteHeader(code)
+ fmt.Fprintln(w, error)
+}
+
+// NotFound replies to the request with an HTTP 404 not found error.
+func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
+
+// NotFoundHandler returns a simple request handler
+// that replies to each request with a ``404 page not found'' reply.
+func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
+
+// StripPrefix returns a handler that serves HTTP requests
+// by removing the given prefix from the request URL's Path
+// and invoking the handler h. StripPrefix handles a
+// request for a path that doesn't begin with prefix by
+// replying with an HTTP 404 not found error.
+func StripPrefix(prefix string, h Handler) Handler {
+ return HandlerFunc(func(w ResponseWriter, r *Request) {
+ if !strings.HasPrefix(r.URL.Path, prefix) {
+ NotFound(w, r)
+ return
+ }
+ r.URL.Path = r.URL.Path[len(prefix):]
+ h.ServeHTTP(w, r)
+ })
+}
+
+// Redirect replies to the request with a redirect to url,
+// which may be a path relative to the request path.
+func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
+ if u, err := url.Parse(urlStr); err == nil {
+ // If url was relative, make absolute by
+ // combining with request path.
+ // The browser would probably do this for us,
+ // but doing it ourselves is more reliable.
+
+ // NOTE(rsc): RFC 2616 says that the Location
+ // line must be an absolute URI, like
+ // "http://www.google.com/redirect/",
+ // not a path like "/redirect/".
+ // Unfortunately, we don't know what to
+ // put in the host name section to get the
+ // client to connect to us again, so we can't
+ // know the right absolute URI to send back.
+ // Because of this problem, no one pays attention
+ // to the RFC; they all send back just a new path.
+ // So do we.
+ oldpath := r.URL.Path
+ if oldpath == "" { // should not happen, but avoid a crash if it does
+ oldpath = "/"
+ }
+ if u.Scheme == "" {
+ // no leading http://server
+ if urlStr == "" || urlStr[0] != '/' {
+ // make relative path absolute
+ olddir, _ := path.Split(oldpath)
+ urlStr = olddir + urlStr
+ }
+
+ var query string
+ if i := strings.Index(urlStr, "?"); i != -1 {
+ urlStr, query = urlStr[:i], urlStr[i:]
+ }
+
+ // clean up but preserve trailing slash
+ trailing := urlStr[len(urlStr)-1] == '/'
+ urlStr = path.Clean(urlStr)
+ if trailing && urlStr[len(urlStr)-1] != '/' {
+ urlStr += "/"
+ }
+ urlStr += query
+ }
+ }
+
+ w.Header().Set("Location", urlStr)
+ w.WriteHeader(code)
+
+ // RFC2616 recommends that a short note "SHOULD" be included in the
+ // response because older user agents may not understand 301/307.
+ // Shouldn't send the response for POST or HEAD; that leaves GET.
+ if r.Method == "GET" {
+ note := "<a href=\"" + htmlEscape(urlStr) + "\">" + statusText[code] + "</a>.\n"
+ fmt.Fprintln(w, note)
+ }
+}
+
+var htmlReplacer = strings.NewReplacer(
+ "&", "&amp;",
+ "<", "&lt;",
+ ">", "&gt;",
+ `"`, "&quot;",
+ "'", "&apos;",
+)
+
+func htmlEscape(s string) string {
+ return htmlReplacer.Replace(s)
+}
+
+// Redirect to a fixed URL
+type redirectHandler struct {
+ url string
+ code int
+}
+
+func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
+ Redirect(w, r, rh.url, rh.code)
+}
+
+// RedirectHandler returns a request handler that redirects
+// each request it receives to the given url using the given
+// status code.
+func RedirectHandler(url string, code int) Handler {
+ return &redirectHandler{url, code}
+}
+
+// ServeMux is an HTTP request multiplexer.
+// It matches the URL of each incoming request against a list of registered
+// patterns and calls the handler for the pattern that
+// most closely matches the URL.
+//
+// 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
+// called for paths beginning "/images/thumbnails/" and the
+// former will receiver requests for any other paths in the
+// "/images/" subtree.
+//
+// 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
+// equivalent .- and ..-free URL.
+type ServeMux struct {
+ m map[string]Handler
+}
+
+// NewServeMux allocates and returns a new ServeMux.
+func NewServeMux() *ServeMux { return &ServeMux{make(map[string]Handler)} }
+
+// DefaultServeMux is the default ServeMux used by Serve.
+var DefaultServeMux = NewServeMux()
+
+// Does path match pattern?
+func pathMatch(pattern, path string) bool {
+ if len(pattern) == 0 {
+ // should not happen
+ return false
+ }
+ n := len(pattern)
+ if pattern[n-1] != '/' {
+ return pattern == path
+ }
+ return len(path) >= n && path[0:n] == pattern
+}
+
+// Return the canonical path for p, eliminating . and .. elements.
+func cleanPath(p string) string {
+ if p == "" {
+ return "/"
+ }
+ if p[0] != '/' {
+ p = "/" + p
+ }
+ np := path.Clean(p)
+ // path.Clean removes trailing slash except for root;
+ // put the trailing slash back if necessary.
+ if p[len(p)-1] == '/' && np != "/" {
+ np += "/"
+ }
+ return np
+}
+
+// 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, path) {
+ continue
+ }
+ if h == nil || len(k) > n {
+ n = len(k)
+ 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.Header().Set("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()
+ }
+ h.ServeHTTP(w, r)
+}
+
+// Handle registers the handler for the given pattern.
+func (mux *ServeMux) Handle(pattern string, handler Handler) {
+ if pattern == "" {
+ panic("http: invalid pattern " + pattern)
+ }
+
+ mux.m[pattern] = handler
+
+ // Helpful behavior:
+ // If pattern is /tree/, insert permanent redirect for /tree.
+ n := len(pattern)
+ if n > 0 && pattern[n-1] == '/' {
+ mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently)
+ }
+}
+
+// HandleFunc registers the handler function for the given pattern.
+func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+ mux.Handle(pattern, HandlerFunc(handler))
+}
+
+// Handle registers the handler for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
+
+// HandleFunc registers the handler function for the given pattern
+// in the DefaultServeMux.
+// The documentation for ServeMux explains how patterns are matched.
+func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
+ DefaultServeMux.HandleFunc(pattern, handler)
+}
+
+// Serve accepts incoming HTTP connections on the listener l,
+// creating a new service thread for each. The service threads
+// read requests and then call handler to reply to them.
+// Handler is typically nil, in which case the DefaultServeMux is used.
+func Serve(l net.Listener, handler Handler) error {
+ srv := &Server{Handler: handler}
+ return srv.Serve(l)
+}
+
+// A Server defines parameters for running an HTTP server.
+type Server struct {
+ Addr string // TCP address to listen on, ":http" if empty
+ Handler Handler // handler to invoke, http.DefaultServeMux if nil
+ ReadTimeout int64 // the net.Conn.SetReadTimeout value for new connections
+ WriteTimeout int64 // the net.Conn.SetWriteTimeout value for new connections
+ MaxHeaderBytes int // maximum size of request headers, DefaultMaxHeaderBytes if 0
+}
+
+// ListenAndServe listens on the TCP network address srv.Addr and then
+// calls Serve to handle requests on incoming connections. If
+// srv.Addr is blank, ":http" is used.
+func (srv *Server) ListenAndServe() error {
+ addr := srv.Addr
+ if addr == "" {
+ addr = ":http"
+ }
+ l, e := net.Listen("tcp", addr)
+ if e != nil {
+ return e
+ }
+ return srv.Serve(l)
+}
+
+// Serve accepts incoming connections on the Listener l, creating a
+// new service thread for each. The service threads read requests and
+// then call srv.Handler to reply to them.
+func (srv *Server) Serve(l net.Listener) error {
+ defer l.Close()
+ for {
+ rw, e := l.Accept()
+ if e != nil {
+ if ne, ok := e.(net.Error); ok && ne.Temporary() {
+ log.Printf("http: Accept error: %v", e)
+ continue
+ }
+ return e
+ }
+ if srv.ReadTimeout != 0 {
+ rw.SetReadTimeout(srv.ReadTimeout)
+ }
+ if srv.WriteTimeout != 0 {
+ rw.SetWriteTimeout(srv.WriteTimeout)
+ }
+ c, err := srv.newConn(rw)
+ if err != nil {
+ continue
+ }
+ go c.serve()
+ }
+ panic("not reached")
+}
+
+// ListenAndServe listens on the TCP network address addr
+// and then calls Serve with handler to handle requests
+// on incoming connections. Handler is typically nil,
+// in which case the DefaultServeMux is used.
+//
+// A trivial example server is:
+//
+// package main
+//
+// import (
+// "http"
+// "io"
+// "log"
+// )
+//
+// // hello world, the web server
+// func HelloServer(w http.ResponseWriter, req *http.Request) {
+// io.WriteString(w, "hello, world!\n")
+// }
+//
+// func main() {
+// http.HandleFunc("/hello", HelloServer)
+// err := http.ListenAndServe(":12345", nil)
+// if err != nil {
+// log.Fatal("ListenAndServe: ", err.String())
+// }
+// }
+func ListenAndServe(addr string, handler Handler) error {
+ server := &Server{Addr: addr, Handler: handler}
+ return server.ListenAndServe()
+}
+
+// ListenAndServeTLS acts identically to ListenAndServe, except that it
+// expects HTTPS connections. Additionally, files containing a certificate and
+// matching private key for the server must be provided. If the certificate
+// is signed by a certificate authority, the certFile should be the concatenation
+// of the server's certificate followed by the CA's certificate.
+//
+// A trivial example server is:
+//
+// import (
+// "http"
+// "log"
+// )
+//
+// func handler(w http.ResponseWriter, req *http.Request) {
+// w.Header().Set("Content-Type", "text/plain")
+// w.Write([]byte("This is an example server.\n"))
+// }
+//
+// func main() {
+// http.HandleFunc("/", handler)
+// 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.Fatal(err)
+// }
+// }
+//
+// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
+func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error {
+ server := &Server{Addr: addr, Handler: handler}
+ return server.ListenAndServeTLS(certFile, keyFile)
+}
+
+// ListenAndServeTLS listens on the TCP network address srv.Addr and
+// then calls Serve to handle requests on incoming TLS connections.
+//
+// Filenames containing a certificate and matching private key for
+// the server must be provided. If the certificate is signed by a
+// certificate authority, the certFile should be the concatenation
+// of the server's certificate followed by the CA's certificate.
+//
+// If srv.Addr is blank, ":https" is used.
+func (s *Server) ListenAndServeTLS(certFile, keyFile string) error {
+ addr := s.Addr
+ if addr == "" {
+ addr = ":https"
+ }
+ config := &tls.Config{
+ Rand: rand.Reader,
+ Time: time.Seconds,
+ NextProtos: []string{"http/1.1"},
+ }
+
+ var err error
+ config.Certificates = make([]tls.Certificate, 1)
+ config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return err
+ }
+
+ conn, err := net.Listen("tcp", addr)
+ if err != nil {
+ return err
+ }
+
+ tlsListener := tls.NewListener(conn, config)
+ return s.Serve(tlsListener)
+}
+
+// TimeoutHandler returns a Handler that runs h with the given time limit.
+//
+// The new Handler calls h.ServeHTTP to handle each request, but if a
+// call runs for more than ns nanoseconds, the handler responds with
+// a 503 Service Unavailable error and the given message in its body.
+// (If msg is empty, a suitable default message will be sent.)
+// After such a timeout, writes by h to its ResponseWriter will return
+// ErrHandlerTimeout.
+func TimeoutHandler(h Handler, ns int64, msg string) Handler {
+ f := func() <-chan int64 {
+ return time.After(ns)
+ }
+ return &timeoutHandler{h, f, msg}
+}
+
+// ErrHandlerTimeout is returned on ResponseWriter Write calls
+// in handlers which have timed out.
+var ErrHandlerTimeout = errors.New("http: Handler timeout")
+
+type timeoutHandler struct {
+ handler Handler
+ timeout func() <-chan int64 // returns channel producing a timeout
+ body string
+}
+
+func (h *timeoutHandler) errorBody() string {
+ if h.body != "" {
+ return h.body
+ }
+ return "<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>"
+}
+
+func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
+ done := make(chan bool)
+ tw := &timeoutWriter{w: w}
+ go func() {
+ h.handler.ServeHTTP(tw, r)
+ done <- true
+ }()
+ select {
+ case <-done:
+ return
+ case <-h.timeout():
+ tw.mu.Lock()
+ defer tw.mu.Unlock()
+ if !tw.wroteHeader {
+ tw.w.WriteHeader(StatusServiceUnavailable)
+ tw.w.Write([]byte(h.errorBody()))
+ }
+ tw.timedOut = true
+ }
+}
+
+type timeoutWriter struct {
+ w ResponseWriter
+
+ mu sync.Mutex
+ timedOut bool
+ wroteHeader bool
+}
+
+func (tw *timeoutWriter) Header() Header {
+ return tw.w.Header()
+}
+
+func (tw *timeoutWriter) Write(p []byte) (int, error) {
+ tw.mu.Lock()
+ timedOut := tw.timedOut
+ tw.mu.Unlock()
+ if timedOut {
+ return 0, ErrHandlerTimeout
+ }
+ return tw.w.Write(p)
+}
+
+func (tw *timeoutWriter) WriteHeader(code int) {
+ tw.mu.Lock()
+ if tw.timedOut || tw.wroteHeader {
+ tw.mu.Unlock()
+ return
+ }
+ tw.wroteHeader = true
+ tw.mu.Unlock()
+ tw.w.WriteHeader(code)
+}