| // 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" | |
| "path" | |
| "runtime/debug" | |
| "strconv" | |
| "strings" | |
| "sync" | |
| "time" | |
| "url" | |
| ) | |
| // 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( | |
| "&", "&", | |
| "<", "<", | |
| ">", ">", | |
| `"`, """, | |
| "'", "'", | |
| ) | |
| 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) | |
| } |