URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [http/] [server.go] - Rev 747
Compare with Previous | Blame | View Log
// 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):// loggingpackage httpimport ("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 sideserver *Server // the Server on which the connection arrivedrwc net.Conn // i/o connectionlr *io.LimitedReader // io.LimitReader(rwc)buf *bufio.ReadWriter // buffered(lr,rwc), reading from bufio->limitReader->rwchijacked bool // connection has been hijacked by handlertlsState *tls.ConnectionState // or nil when not using TLSbody []byte}// A response represents the server side of an HTTP response.type response struct {conn *connreq *Request // request for this responsechunking bool // using chunked transfer encoding for reply bodywroteHeader bool // reply header has been writtenwroteContinue bool // 100 Continue response was writtenheader Header // reply header parameterswritten int64 // number of bytes written in bodycontentLength int64 // explicitly-declared Content-Length; or -1status int // status code passed to WriteHeaderneedSniff 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 = truew.requestBodyLimitHit = trueif !w.wroteHeader {w.Header().Set("Connection", "close")}}type writerOnly struct {io.Writer}func (w *response) ReadFrom(src io.Reader) (n int64, err error) {// Call WriteHeader before checking w.chunking if it hasn't// been called yet, since WriteHeader is what sets w.chunking.if !w.wroteHeader {w.WriteHeader(StatusOK)}if !w.chunking && w.bodyAllowed() && !w.needSniff {w.Flush()if rf, ok := w.conn.rwc.(io.ReaderFrom); ok {n, err = rf.ReadFrom(src)w.written += nreturn}}// 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.LimitedReaderconst 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 = srvc.rwc = rwcc.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 MBfunc (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 headertype expectContinueReader struct {resp *responsereadCloser io.ReadCloserclosed 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 = trueio.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 = truereturn 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 *Requestif req, err = ReadRequest(c.buf.Reader); err != nil {if c.lr.N == 0 {return nil, errTooLarge}return nil, err}c.lr.N = noLimitreq.RemoteAddr = c.remoteAddrreq.TLS = c.tlsStatew = new(response)w.conn = cw.req = reqw.header = make(Header)w.contentLength = -1c.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 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 << 10func (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 = truew.status = code// Check for a explicit (and valid) Content-Length header.var hasCL boolvar contentLength int64if clenStr := w.header.Get("Content-Length"); clenStr != "" {var err errorcontentLength, err = strconv.ParseInt(clenStr, 10, 64)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.req.Method != "HEAD" {w.needSniff = true}}if _, ok := w.header["Date"]; !ok {w.Header().Set("Date", time.Now().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 = contentLengthw.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 = truew.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 = truew.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 = falsedata := w.conn.bodyfmt.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 errorKludgeif w.contentLength != -1 && w.written > w.contentLength {return 0, ErrContentLength}var m intif 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 lineio.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}var buf bytes.Bufferfmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)buf.Write(debug.Stack())log.Print(buf.String())if c.rwc != nil { // may be nil if connection hijackedc.rwc.Close()}}()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 supportreq := w.reqif req.expectsContinue() {if req.ProtoAtLeast(1, 1) {// Wrap the Body reader with one that replies on the connectionreq.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.Handlerif 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 = truerwc = w.conn.rwcbuf = w.conn.bufw.conn.rwc = nilw.conn.buf = nilreturn}// 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.Pathif oldpath == "" { // should not happen, but avoid a crash if it doesoldpath = "/"}if u.Scheme == "" {// no leading http://serverif urlStr == "" || urlStr[0] != '/' {// make relative path absoluteolddir, _ := path.Split(oldpath)urlStr = olddir + urlStr}var query stringif i := strings.Index(urlStr, "?"); i != -1 {urlStr, query = urlStr[:i], urlStr[i:]}// clean up but preserve trailing slashtrailing := 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 URLtype redirectHandler struct {url stringcode 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 happenreturn 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 winsfunc (mux *ServeMux) match(path string) Handler {var h Handlervar n = 0for 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 onesh := 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 emptyHandler Handler // handler to invoke, http.DefaultServeMux if nilReadTimeout time.Duration // maximum duration before timing out read of the requestWriteTimeout time.Duration // maximum duration before timing out write of the responseMaxHeaderBytes 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.Addrif 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.SetReadDeadline(time.Now().Add(srv.ReadTimeout))}if srv.WriteTimeout != 0 {rw.SetWriteDeadline(time.Now().Add(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 (// "io"// "net/http"// "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)// }// }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 (// "log"// "net/http"// )//// 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 (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {addr := srv.Addrif addr == "" {addr = ":https"}config := &tls.Config{Rand: rand.Reader,NextProtos: []string{"http/1.1"},}var err errorconfig.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 srv.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, dt time.Duration, msg string) Handler {f := func() <-chan time.Time {return time.After(dt)}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 Handlertimeout func() <-chan time.Time // returns channel producing a timeoutbody 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:returncase <-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 ResponseWritermu sync.MutextimedOut boolwroteHeader bool}func (tw *timeoutWriter) Header() Header {return tw.w.Header()}func (tw *timeoutWriter) Write(p []byte) (int, error) {tw.mu.Lock()timedOut := tw.timedOuttw.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 = truetw.mu.Unlock()tw.w.WriteHeader(code)}
