2008-09-24 16:26:55 -06:00
|
|
|
// 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.
|
|
|
|
|
2009-02-02 19:01:32 -07:00
|
|
|
// HTTP server. See RFC 2616.
|
2008-09-24 16:26:55 -06:00
|
|
|
|
2009-02-02 19:01:32 -07:00
|
|
|
// TODO(rsc):
|
|
|
|
// logging
|
|
|
|
// cgi support
|
|
|
|
// post support
|
2008-09-24 16:26:55 -06:00
|
|
|
|
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
2009-12-15 16:35:38 -07:00
|
|
|
"bufio"
|
2010-07-02 11:00:18 -06:00
|
|
|
"crypto/rand"
|
|
|
|
"crypto/tls"
|
2009-12-15 16:35:38 -07:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2010-07-02 11:00:18 -06:00
|
|
|
"time"
|
2008-09-24 16:26:55 -06:00
|
|
|
)
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// Errors introduced by the HTTP server.
|
|
|
|
var (
|
2009-12-15 16:35:38 -07:00
|
|
|
ErrWriteAfterFlush = os.NewError("Conn.Write called after Flush")
|
2010-06-03 17:09:37 -06:00
|
|
|
ErrBodyNotAllowed = os.NewError("http: response status code does not allow body")
|
2009-12-15 16:35:38 -07:00
|
|
|
ErrHijacked = os.NewError("Conn has been hijacked")
|
2009-03-11 13:51:10 -06:00
|
|
|
)
|
2009-02-02 19:01:32 -07:00
|
|
|
|
2009-10-15 01:27:40 -06:00
|
|
|
// Objects implementing the Handler interface can be
|
2009-03-11 13:51:10 -06:00
|
|
|
// registered to serve a particular path or subtree
|
|
|
|
// in the HTTP server.
|
2010-02-12 15:27:44 -07:00
|
|
|
//
|
2010-09-28 22:30:12 -06:00
|
|
|
// ServeHTTP should write reply headers and data to the ResponseWriter
|
2010-02-12 15:27:44 -07:00
|
|
|
// 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.
|
2009-02-02 19:01:32 -07:00
|
|
|
type Handler interface {
|
2010-09-28 22:30:12 -06:00
|
|
|
ServeHTTP(ResponseWriter, *Request)
|
|
|
|
}
|
|
|
|
|
|
|
|
// A ResponseWriter interface is used by an HTTP handler to
|
|
|
|
// construct an HTTP response.
|
|
|
|
type ResponseWriter interface {
|
|
|
|
// RemoteAddr returns the address of the client that sent the current request
|
|
|
|
RemoteAddr() string
|
|
|
|
|
|
|
|
// UsingTLS returns true if the client is connected using TLS
|
|
|
|
UsingTLS() bool
|
|
|
|
|
|
|
|
// SetHeader sets a header line in the eventual response.
|
|
|
|
// For example, SetHeader("Content-Type", "text/html; charset=utf-8")
|
|
|
|
// will result in the header line
|
|
|
|
//
|
|
|
|
// Content-Type: text/html; charset=utf-8
|
|
|
|
//
|
|
|
|
// being sent. UTF-8 encoded HTML is the default setting for
|
|
|
|
// Content-Type in this library, so users need not make that
|
|
|
|
// particular call. Calls to SetHeader after WriteHeader (or Write)
|
|
|
|
// are ignored.
|
|
|
|
SetHeader(string, string)
|
|
|
|
|
|
|
|
// 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, os.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)
|
|
|
|
|
|
|
|
// Flush sends any buffered data to the client.
|
|
|
|
Flush()
|
|
|
|
|
|
|
|
// 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() (io.ReadWriteCloser, *bufio.ReadWriter, os.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// A conn represents the server side of an HTTP connection.
|
|
|
|
type conn struct {
|
|
|
|
remoteAddr string // network address of remote side
|
|
|
|
handler Handler // request handler
|
|
|
|
rwc io.ReadWriteCloser // i/o connection
|
|
|
|
buf *bufio.ReadWriter // buffered rwc
|
|
|
|
hijacked bool // connection has been hijacked by handler
|
|
|
|
usingTLS bool // a flag indicating connection over TLS
|
|
|
|
}
|
|
|
|
|
|
|
|
// A response represents the server side of an HTTP response.
|
|
|
|
type response struct {
|
|
|
|
conn *conn
|
|
|
|
req *Request // request for this response
|
2010-09-27 19:55:04 -06:00
|
|
|
chunking bool // using chunked transfer encoding for reply body
|
|
|
|
wroteHeader bool // reply header has been written
|
|
|
|
wroteContinue bool // 100 Continue response was written
|
|
|
|
header map[string]string // reply header parameters
|
|
|
|
written int64 // number of bytes written in body
|
|
|
|
status int // status code passed to WriteHeader
|
|
|
|
|
|
|
|
// 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
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create new connection from rwc.
|
2010-09-28 22:30:12 -06:00
|
|
|
func newConn(rwc net.Conn, handler Handler) (c *conn, err os.Error) {
|
|
|
|
c = new(conn)
|
|
|
|
c.remoteAddr = rwc.RemoteAddr().String()
|
2009-12-15 16:35:38 -07:00
|
|
|
c.handler = handler
|
|
|
|
c.rwc = rwc
|
2010-09-10 22:27:16 -06:00
|
|
|
_, c.usingTLS = rwc.(*tls.Conn)
|
2009-12-15 16:35:38 -07:00
|
|
|
br := bufio.NewReader(rwc)
|
|
|
|
bw := bufio.NewWriter(rwc)
|
|
|
|
c.buf = bufio.NewReadWriter(br, bw)
|
|
|
|
return c, nil
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2010-06-16 11:15:39 -06:00
|
|
|
// wrapper around io.ReaderCloser which on first read, sends an
|
|
|
|
// HTTP/1.1 100 Continue header
|
|
|
|
type expectContinueReader struct {
|
2010-09-28 22:30:12 -06:00
|
|
|
resp *response
|
2010-06-16 11:15:39 -06:00
|
|
|
readCloser io.ReadCloser
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ecr *expectContinueReader) Read(p []byte) (n int, err os.Error) {
|
2010-09-28 22:30:12 -06:00
|
|
|
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()
|
2010-06-16 11:15:39 -06:00
|
|
|
}
|
|
|
|
return ecr.readCloser.Read(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ecr *expectContinueReader) Close() os.Error {
|
|
|
|
return ecr.readCloser.Close()
|
|
|
|
}
|
|
|
|
|
2010-09-02 12:21:11 -06:00
|
|
|
// 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"
|
|
|
|
|
2009-02-02 19:01:32 -07:00
|
|
|
// Read next request from connection.
|
2010-09-28 22:30:12 -06:00
|
|
|
func (c *conn) readRequest() (w *response, err os.Error) {
|
2009-02-03 15:16:22 -07:00
|
|
|
if c.hijacked {
|
2009-11-09 13:07:39 -07:00
|
|
|
return nil, ErrHijacked
|
2009-02-03 15:16:22 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
var req *Request
|
2009-05-08 12:52:39 -06:00
|
|
|
if req, err = ReadRequest(c.buf.Reader); err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
return nil, err
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
w = new(response)
|
|
|
|
w.conn = c
|
|
|
|
w.req = req
|
|
|
|
w.header = make(map[string]string)
|
2009-02-02 19:01:32 -07:00
|
|
|
|
2010-06-16 11:15:39 -06:00
|
|
|
// Expect 100 Continue support
|
2010-09-28 22:30:12 -06:00
|
|
|
if req.expectsContinue() && req.ProtoAtLeast(1, 1) {
|
2010-06-16 11:15:39 -06:00
|
|
|
// Wrap the Body reader with one that replies on the connection
|
2010-09-28 22:30:12 -06:00
|
|
|
req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
|
2010-06-16 11:15:39 -06:00
|
|
|
}
|
|
|
|
|
2009-02-02 19:01:32 -07:00
|
|
|
// Default output is HTML encoded in UTF-8.
|
2010-09-28 22:30:12 -06:00
|
|
|
w.SetHeader("Content-Type", "text/html; charset=utf-8")
|
|
|
|
w.SetHeader("Date", time.UTC().Format(TimeFormat))
|
2009-02-02 19:01:32 -07:00
|
|
|
|
2011-01-13 12:34:31 -07:00
|
|
|
if req.Method == "HEAD" {
|
|
|
|
// do nothing
|
|
|
|
} else if req.ProtoAtLeast(1, 1) {
|
2009-02-02 19:01:32 -07:00
|
|
|
// HTTP/1.1 or greater: use chunked transfer encoding
|
|
|
|
// to avoid closing the connection at EOF.
|
2010-09-28 22:30:12 -06:00
|
|
|
w.chunking = true
|
|
|
|
w.SetHeader("Transfer-Encoding", "chunked")
|
2009-02-02 19:01:32 -07:00
|
|
|
} else {
|
|
|
|
// HTTP version < 1.1: cannot do chunked transfer
|
|
|
|
// encoding, so signal EOF by closing connection.
|
2010-09-27 19:55:04 -06:00
|
|
|
// Will be overridden if the HTTP handler ends up
|
|
|
|
// writing a Content-Length and the client requested
|
|
|
|
// "Connection: keep-alive"
|
2010-09-28 22:30:12 -06:00
|
|
|
w.closeAfterReply = true
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
return w, nil
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
// UsingTLS implements the ResponseWriter.UsingTLS
|
|
|
|
func (w *response) UsingTLS() bool {
|
|
|
|
return w.conn.usingTLS
|
2010-09-10 22:27:16 -06:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
// RemoteAddr implements the ResponseWriter.RemoteAddr method
|
|
|
|
func (w *response) RemoteAddr() string { return w.conn.remoteAddr }
|
|
|
|
|
|
|
|
// SetHeader implements the ResponseWriter.SetHeader method
|
|
|
|
func (w *response) SetHeader(hdr, val string) { w.header[CanonicalHeaderKey(hdr)] = val }
|
|
|
|
|
|
|
|
// WriteHeader implements the ResponseWriter.WriteHeader method
|
|
|
|
func (w *response) WriteHeader(code int) {
|
|
|
|
if w.conn.hijacked {
|
log: new interface
New logging interface simplifies and generalizes.
1) Loggers now have only one output.
2) log.Stdout, Stderr, Crash and friends are gone.
Logging is now always to standard error by default.
3) log.Panic* replaces log.Crash*.
4) Exiting and panicking are not part of the logger's state; instead
the functions Exit* and Panic* simply call Exit or panic after
printing.
5) There is now one 'standard logger'. Instead of calling Stderr,
use Print etc. There are now triples, by analogy with fmt:
Print, Println, Printf
What was log.Stderr is now best represented by log.Println,
since there are now separate Print and Println functions
(and methods).
6) New functions SetOutput, SetFlags, and SetPrefix allow global
editing of the standard logger's properties. This is new
functionality. For instance, one can call
log.SetFlags(log.Lshortfile|log.Ltime|log.Lmicroseconds)
to get all logging output to show file name, line number, and
time stamp.
In short, for most purposes
log.Stderr -> log.Println or log.Print
log.Stderrf -> log.Printf
log.Crash -> log.Panicln or log.Panic
log.Crashf -> log.Panicf
log.Exit -> log.Exitln or log.Exit
log.Exitf -> log.Exitf (no change)
This has a slight breakage: since loggers now write only to one
output, existing calls to log.New() need to delete the second argument.
Also, custom loggers with exit or panic properties will need to be
reworked.
All package code updated to new interface.
The test has been reworked somewhat.
The old interface will be removed after the new release.
For now, its elements are marked 'deprecated' in their comments.
Fixes #1184.
R=rsc
CC=golang-dev
https://golang.org/cl/2419042
2010-10-12 13:59:18 -06:00
|
|
|
log.Print("http: response.WriteHeader on hijacked connection")
|
2009-12-15 16:35:38 -07:00
|
|
|
return
|
2009-02-03 15:16:22 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
if w.wroteHeader {
|
log: new interface
New logging interface simplifies and generalizes.
1) Loggers now have only one output.
2) log.Stdout, Stderr, Crash and friends are gone.
Logging is now always to standard error by default.
3) log.Panic* replaces log.Crash*.
4) Exiting and panicking are not part of the logger's state; instead
the functions Exit* and Panic* simply call Exit or panic after
printing.
5) There is now one 'standard logger'. Instead of calling Stderr,
use Print etc. There are now triples, by analogy with fmt:
Print, Println, Printf
What was log.Stderr is now best represented by log.Println,
since there are now separate Print and Println functions
(and methods).
6) New functions SetOutput, SetFlags, and SetPrefix allow global
editing of the standard logger's properties. This is new
functionality. For instance, one can call
log.SetFlags(log.Lshortfile|log.Ltime|log.Lmicroseconds)
to get all logging output to show file name, line number, and
time stamp.
In short, for most purposes
log.Stderr -> log.Println or log.Print
log.Stderrf -> log.Printf
log.Crash -> log.Panicln or log.Panic
log.Crashf -> log.Panicf
log.Exit -> log.Exitln or log.Exit
log.Exitf -> log.Exitf (no change)
This has a slight breakage: since loggers now write only to one
output, existing calls to log.New() need to delete the second argument.
Also, custom loggers with exit or panic properties will need to be
reworked.
All package code updated to new interface.
The test has been reworked somewhat.
The old interface will be removed after the new release.
For now, its elements are marked 'deprecated' in their comments.
Fixes #1184.
R=rsc
CC=golang-dev
https://golang.org/cl/2419042
2010-10-12 13:59:18 -06:00
|
|
|
log.Print("http: multiple response.WriteHeader calls")
|
2009-12-15 16:35:38 -07:00
|
|
|
return
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
w.wroteHeader = true
|
|
|
|
w.status = code
|
2010-06-03 17:09:37 -06:00
|
|
|
if code == StatusNotModified {
|
|
|
|
// Must not have body.
|
2010-09-28 22:30:12 -06:00
|
|
|
w.header["Content-Type"] = "", false
|
|
|
|
w.header["Transfer-Encoding"] = "", false
|
2010-11-01 14:15:03 -06:00
|
|
|
w.chunking = false
|
2010-06-03 17:09:37 -06:00
|
|
|
}
|
2011-01-19 08:05:48 -07:00
|
|
|
// Cannot use Content-Length with non-identity Transfer-Encoding.
|
|
|
|
if w.chunking {
|
|
|
|
w.header["Content-Length"] = "", false
|
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
if !w.req.ProtoAtLeast(1, 0) {
|
2009-11-09 13:07:39 -07:00
|
|
|
return
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
proto := "HTTP/1.0"
|
2010-09-28 22:30:12 -06:00
|
|
|
if w.req.ProtoAtLeast(1, 1) {
|
2009-11-09 13:07:39 -07:00
|
|
|
proto = "HTTP/1.1"
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
codestring := strconv.Itoa(code)
|
|
|
|
text, ok := statusText[code]
|
2009-02-02 19:01:32 -07:00
|
|
|
if !ok {
|
2009-11-09 13:07:39 -07:00
|
|
|
text = "status code " + codestring
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
io.WriteString(w.conn.buf, proto+" "+codestring+" "+text+"\r\n")
|
|
|
|
for k, v := range w.header {
|
|
|
|
io.WriteString(w.conn.buf, k+": "+v+"\r\n")
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
io.WriteString(w.conn.buf, "\r\n")
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
// Write implements the ResponseWriter.Write method
|
|
|
|
func (w *response) Write(data []byte) (n int, err os.Error) {
|
|
|
|
if w.conn.hijacked {
|
log: new interface
New logging interface simplifies and generalizes.
1) Loggers now have only one output.
2) log.Stdout, Stderr, Crash and friends are gone.
Logging is now always to standard error by default.
3) log.Panic* replaces log.Crash*.
4) Exiting and panicking are not part of the logger's state; instead
the functions Exit* and Panic* simply call Exit or panic after
printing.
5) There is now one 'standard logger'. Instead of calling Stderr,
use Print etc. There are now triples, by analogy with fmt:
Print, Println, Printf
What was log.Stderr is now best represented by log.Println,
since there are now separate Print and Println functions
(and methods).
6) New functions SetOutput, SetFlags, and SetPrefix allow global
editing of the standard logger's properties. This is new
functionality. For instance, one can call
log.SetFlags(log.Lshortfile|log.Ltime|log.Lmicroseconds)
to get all logging output to show file name, line number, and
time stamp.
In short, for most purposes
log.Stderr -> log.Println or log.Print
log.Stderrf -> log.Printf
log.Crash -> log.Panicln or log.Panic
log.Crashf -> log.Panicf
log.Exit -> log.Exitln or log.Exit
log.Exitf -> log.Exitf (no change)
This has a slight breakage: since loggers now write only to one
output, existing calls to log.New() need to delete the second argument.
Also, custom loggers with exit or panic properties will need to be
reworked.
All package code updated to new interface.
The test has been reworked somewhat.
The old interface will be removed after the new release.
For now, its elements are marked 'deprecated' in their comments.
Fixes #1184.
R=rsc
CC=golang-dev
https://golang.org/cl/2419042
2010-10-12 13:59:18 -06:00
|
|
|
log.Print("http: response.Write on hijacked connection")
|
2009-12-15 16:35:38 -07:00
|
|
|
return 0, ErrHijacked
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
if !w.wroteHeader {
|
|
|
|
if w.req.wantsHttp10KeepAlive() {
|
|
|
|
_, hasLength := w.header["Content-Length"]
|
2010-09-27 19:55:04 -06:00
|
|
|
if hasLength {
|
2010-09-28 22:30:12 -06:00
|
|
|
_, connectionHeaderSet := w.header["Connection"]
|
2010-09-27 19:55:04 -06:00
|
|
|
if !connectionHeaderSet {
|
2010-09-28 22:30:12 -06:00
|
|
|
w.header["Connection"] = "keep-alive"
|
2010-09-27 19:55:04 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
w.WriteHeader(StatusOK)
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
if len(data) == 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
return 0, nil
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2011-01-13 12:34:31 -07:00
|
|
|
if w.status == StatusNotModified || w.req.Method == "HEAD" {
|
2010-06-03 17:09:37 -06:00
|
|
|
// Must not have body.
|
|
|
|
return 0, ErrBodyNotAllowed
|
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
w.written += int64(len(data)) // ignoring errors, for errorKludge
|
2009-06-08 15:15:13 -06:00
|
|
|
|
2009-02-02 19:01:32 -07:00
|
|
|
// TODO(rsc): if chunking happened after the buffering,
|
2009-02-03 15:16:22 -07:00
|
|
|
// then there would be fewer chunk headers.
|
|
|
|
// On the other hand, it would make hijacking more difficult.
|
2010-09-28 22:30:12 -06:00
|
|
|
if w.chunking {
|
|
|
|
fmt.Fprintf(w.conn.buf, "%x\r\n", len(data)) // TODO(rsc): use strconv not fmt
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
n, err = w.conn.buf.Write(data)
|
|
|
|
if err == nil && w.chunking {
|
2009-04-27 01:38:04 -06:00
|
|
|
if n != len(data) {
|
2009-11-09 13:07:39 -07:00
|
|
|
err = io.ErrShortWrite
|
2009-04-27 01:38:04 -06:00
|
|
|
}
|
|
|
|
if err == nil {
|
2010-09-28 22:30:12 -06:00
|
|
|
io.WriteString(w.conn.buf, "\r\n")
|
2009-04-27 01:38:04 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-15 16:35:38 -07:00
|
|
|
return n, err
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2009-06-08 15:15:13 -06:00
|
|
|
// If this is an error reply (4xx or 5xx)
|
|
|
|
// and the handler wrote some data explaining the error,
|
|
|
|
// some browsers (i.e., Chrome, Internet Explorer)
|
|
|
|
// will show their own error instead unless the error is
|
|
|
|
// long enough. The minimum lengths used in those
|
|
|
|
// browsers are in the 256-512 range.
|
|
|
|
// Pad to 1024 bytes.
|
2010-09-28 22:30:12 -06:00
|
|
|
func errorKludge(w *response) {
|
2009-12-15 16:35:38 -07:00
|
|
|
const min = 1024
|
2009-06-08 15:15:13 -06:00
|
|
|
|
|
|
|
// Is this an error?
|
2010-09-28 22:30:12 -06:00
|
|
|
if kind := w.status / 100; kind != 4 && kind != 5 {
|
2009-11-09 13:07:39 -07:00
|
|
|
return
|
2009-06-08 15:15:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Did the handler supply any info? Enough?
|
2010-09-28 22:30:12 -06:00
|
|
|
if w.written == 0 || w.written >= min {
|
2009-11-09 13:07:39 -07:00
|
|
|
return
|
2009-06-08 15:15:13 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Is it a broken browser?
|
2009-12-15 16:35:38 -07:00
|
|
|
var msg string
|
2010-09-28 22:30:12 -06:00
|
|
|
switch agent := w.req.UserAgent; {
|
2010-11-01 15:32:48 -06:00
|
|
|
case strings.Contains(agent, "MSIE"):
|
2009-11-09 13:07:39 -07:00
|
|
|
msg = "Internet Explorer"
|
2010-11-01 15:32:48 -06:00
|
|
|
case strings.Contains(agent, "Chrome/"):
|
2009-11-09 13:07:39 -07:00
|
|
|
msg = "Chrome"
|
2009-06-08 15:15:13 -06:00
|
|
|
default:
|
2009-11-09 13:07:39 -07:00
|
|
|
return
|
2009-06-08 15:15:13 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
msg += " would ignore this error page if this text weren't here.\n"
|
2009-08-24 18:31:35 -06:00
|
|
|
|
|
|
|
// Is it text? ("Content-Type" is always in the map)
|
2010-09-28 22:30:12 -06:00
|
|
|
baseType := strings.Split(w.header["Content-Type"], ";", 2)[0]
|
2009-08-24 18:31:35 -06:00
|
|
|
switch baseType {
|
|
|
|
case "text/html":
|
2010-09-28 22:30:12 -06:00
|
|
|
io.WriteString(w, "<!-- ")
|
|
|
|
for w.written < min {
|
|
|
|
io.WriteString(w, msg)
|
2009-08-24 18:31:35 -06:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
io.WriteString(w, " -->")
|
2009-08-24 18:31:35 -06:00
|
|
|
case "text/plain":
|
2010-09-28 22:30:12 -06:00
|
|
|
io.WriteString(w, "\n")
|
|
|
|
for w.written < min {
|
|
|
|
io.WriteString(w, msg)
|
2009-08-24 18:31:35 -06:00
|
|
|
}
|
2009-06-08 15:15:13 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
func (w *response) finishRequest() {
|
2010-09-27 19:55:04 -06:00
|
|
|
// 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 ...
|
2010-09-28 22:30:12 -06:00
|
|
|
if w.req.wantsHttp10KeepAlive() {
|
|
|
|
_, sentLength := w.header["Content-Length"]
|
|
|
|
if sentLength && w.header["Connection"] == "keep-alive" {
|
|
|
|
w.closeAfterReply = false
|
2010-09-27 19:55:04 -06:00
|
|
|
}
|
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
if !w.wroteHeader {
|
|
|
|
w.WriteHeader(StatusOK)
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
errorKludge(w)
|
|
|
|
if w.chunking {
|
|
|
|
io.WriteString(w.conn.buf, "0\r\n")
|
2009-02-02 19:01:32 -07:00
|
|
|
// trailer key/value pairs, followed by blank line
|
2010-09-28 22:30:12 -06:00
|
|
|
io.WriteString(w.conn.buf, "\r\n")
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
w.conn.buf.Flush()
|
2010-12-01 21:00:19 -07:00
|
|
|
w.req.Body.Close()
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
// Flush implements the ResponseWriter.Flush method.
|
|
|
|
func (w *response) Flush() {
|
|
|
|
if !w.wroteHeader {
|
|
|
|
w.WriteHeader(StatusOK)
|
2009-11-13 19:06:47 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
w.conn.buf.Flush()
|
2009-11-13 19:06:47 -07:00
|
|
|
}
|
|
|
|
|
2009-02-02 19:01:32 -07:00
|
|
|
// Close the connection.
|
2010-09-28 22:30:12 -06:00
|
|
|
func (c *conn) close() {
|
2009-02-03 15:16:22 -07:00
|
|
|
if c.buf != nil {
|
2009-12-15 16:35:38 -07:00
|
|
|
c.buf.Flush()
|
|
|
|
c.buf = nil
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2009-03-11 13:51:10 -06:00
|
|
|
if c.rwc != nil {
|
2009-12-15 16:35:38 -07:00
|
|
|
c.rwc.Close()
|
|
|
|
c.rwc = nil
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Serve a new connection.
|
2010-09-28 22:30:12 -06:00
|
|
|
func (c *conn) serve() {
|
2008-09-24 16:26:55 -06:00
|
|
|
for {
|
2010-09-28 22:30:12 -06:00
|
|
|
w, err := c.readRequest()
|
2008-09-24 16:26:55 -06:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
2010-09-27 19:55:04 -06:00
|
|
|
// HTTP cannot have multiple simultaneous active requests.[*]
|
2009-02-02 19:01:32 -07:00
|
|
|
// Until the server replies to this request, it can't read another,
|
2009-04-07 01:40:07 -06:00
|
|
|
// so we might as well run the handler in this goroutine.
|
2010-09-27 19:55:04 -06:00
|
|
|
// [*] Not strictly true: HTTP pipelining. We could let them all process
|
|
|
|
// in parallel even if their responses need to be serialized.
|
2010-09-28 22:30:12 -06:00
|
|
|
c.handler.ServeHTTP(w, w.req)
|
2009-02-03 15:16:22 -07:00
|
|
|
if c.hijacked {
|
2009-11-09 13:07:39 -07:00
|
|
|
return
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
w.finishRequest()
|
|
|
|
if w.closeAfterReply {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
c.close()
|
2009-02-03 15:16:22 -07:00
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
// Hijack impements the ResponseWriter.Hijack method.
|
|
|
|
func (w *response) Hijack() (rwc io.ReadWriteCloser, buf *bufio.ReadWriter, err os.Error) {
|
|
|
|
if w.conn.hijacked {
|
2009-11-09 13:07:39 -07:00
|
|
|
return nil, nil, ErrHijacked
|
2009-02-03 15:16:22 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
w.conn.hijacked = true
|
|
|
|
rwc = w.conn.rwc
|
|
|
|
buf = w.conn.buf
|
|
|
|
w.conn.rwc = nil
|
|
|
|
w.conn.buf = nil
|
2009-12-15 16:35:38 -07:00
|
|
|
return
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// 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.
|
2010-09-28 22:30:12 -06:00
|
|
|
type HandlerFunc func(ResponseWriter, *Request)
|
2009-03-11 13:51:10 -06:00
|
|
|
|
2010-09-29 21:22:28 -06:00
|
|
|
// ServeHTTP calls f(w, req).
|
2010-09-28 22:30:12 -06:00
|
|
|
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
|
|
|
|
f(w, r)
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Helper handlers
|
|
|
|
|
2010-03-19 17:22:09 -06:00
|
|
|
// Error replies to the request with the specified error message and HTTP code.
|
2010-09-28 22:30:12 -06:00
|
|
|
func Error(w ResponseWriter, error string, code int) {
|
|
|
|
w.SetHeader("Content-Type", "text/plain; charset=utf-8")
|
|
|
|
w.WriteHeader(code)
|
|
|
|
fmt.Fprintln(w, error)
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2010-03-19 17:22:09 -06:00
|
|
|
// NotFound replies to the request with an HTTP 404 not found error.
|
2010-09-28 22:30:12 -06:00
|
|
|
func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
|
2010-03-19 17:22:09 -06:00
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// NotFoundHandler returns a simple request handler
|
|
|
|
// that replies to each request with a ``404 page not found'' reply.
|
2009-12-15 16:35:38 -07:00
|
|
|
func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
|
2009-02-02 19:01:32 -07:00
|
|
|
|
2009-04-14 21:31:31 -06:00
|
|
|
// Redirect replies to the request with a redirect to url,
|
|
|
|
// which may be a path relative to the request path.
|
2010-09-28 22:30:12 -06:00
|
|
|
func Redirect(w ResponseWriter, r *Request, url string, code int) {
|
2011-01-11 15:15:28 -07:00
|
|
|
if u, err := ParseURL(url); 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 = "/"
|
2009-04-15 19:40:55 -06:00
|
|
|
}
|
2011-01-11 15:15:28 -07:00
|
|
|
if u.Scheme == "" {
|
|
|
|
// no leading http://server
|
|
|
|
if url == "" || url[0] != '/' {
|
|
|
|
// make relative path absolute
|
|
|
|
olddir, _ := path.Split(oldpath)
|
|
|
|
url = olddir + url
|
|
|
|
}
|
2009-04-15 19:40:55 -06:00
|
|
|
|
2011-01-11 15:15:28 -07:00
|
|
|
// clean up but preserve trailing slash
|
|
|
|
trailing := url[len(url)-1] == '/'
|
|
|
|
url = path.Clean(url)
|
|
|
|
if trailing && url[len(url)-1] != '/' {
|
|
|
|
url += "/"
|
|
|
|
}
|
2009-04-15 19:40:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
w.SetHeader("Location", url)
|
|
|
|
w.WriteHeader(code)
|
2011-01-11 15:15:28 -07:00
|
|
|
|
|
|
|
// RFC2616 recommends that a short note "SHOULD" be included in the
|
|
|
|
// response because older user agents may not understand 301/307.
|
2011-01-13 12:34:31 -07:00
|
|
|
// Shouldn't send the response for POST or HEAD; that leaves GET.
|
|
|
|
if r.Method == "GET" {
|
|
|
|
note := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n"
|
|
|
|
fmt.Fprintln(w, note)
|
2011-01-11 15:15:28 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func htmlEscape(s string) string {
|
|
|
|
s = strings.Replace(s, "&", "&", -1)
|
|
|
|
s = strings.Replace(s, "<", "<", -1)
|
|
|
|
s = strings.Replace(s, ">", ">", -1)
|
|
|
|
s = strings.Replace(s, "\"", """, -1)
|
|
|
|
s = strings.Replace(s, "'", "'", -1)
|
|
|
|
return s
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2009-04-14 21:31:31 -06:00
|
|
|
// Redirect to a fixed URL
|
2009-05-12 16:41:19 -06:00
|
|
|
type redirectHandler struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
url string
|
|
|
|
code int
|
2009-05-12 16:41:19 -06:00
|
|
|
}
|
2009-10-06 20:41:51 -06:00
|
|
|
|
2010-09-28 22:30:12 -06:00
|
|
|
func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
|
|
|
|
Redirect(w, r, rh.url, rh.code)
|
2009-04-14 21:31:31 -06:00
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// RedirectHandler returns a request handler that redirects
|
2009-05-12 16:41:19 -06:00
|
|
|
// each request it receives to the given url using the given
|
|
|
|
// status code.
|
|
|
|
func RedirectHandler(url string, code int) Handler {
|
2009-11-09 13:07:39 -07:00
|
|
|
return &redirectHandler{url, code}
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// 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 paths, like "/favicon.ico",
|
|
|
|
// or subtrees, like "/images/" (note the trailing slash).
|
|
|
|
// Patterns must begin with /.
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// In the future, the pattern syntax may be relaxed to allow
|
|
|
|
// an optional host-name at the beginning of the pattern,
|
|
|
|
// so that a handler might register for the two patterns
|
|
|
|
// "/codesearch" and "codesearch.google.com/"
|
|
|
|
// without taking over requests for http://www.google.com/.
|
2009-04-07 01:40:07 -06:00
|
|
|
//
|
|
|
|
// ServeMux also takes care of sanitizing the URL request path,
|
|
|
|
// redirecting any request containing . or .. elements to an
|
|
|
|
// equivalent .- and ..-free URL.
|
2009-02-02 19:01:32 -07:00
|
|
|
type ServeMux struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
m map[string]Handler
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// NewServeMux allocates and returns a new ServeMux.
|
2009-12-15 16:35:38 -07:00
|
|
|
func NewServeMux() *ServeMux { return &ServeMux{make(map[string]Handler)} }
|
2009-02-02 19:01:32 -07:00
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// DefaultServeMux is the default ServeMux used by Serve.
|
2009-10-06 20:41:51 -06:00
|
|
|
var DefaultServeMux = NewServeMux()
|
2009-02-02 19:01:32 -07:00
|
|
|
|
|
|
|
// Does path match pattern?
|
|
|
|
func pathMatch(pattern, path string) bool {
|
|
|
|
if len(pattern) == 0 {
|
|
|
|
// should not happen
|
2009-11-09 13:07:39 -07:00
|
|
|
return false
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
n := len(pattern)
|
2009-02-02 19:01:32 -07:00
|
|
|
if pattern[n-1] != '/' {
|
2009-11-09 13:07:39 -07:00
|
|
|
return pattern == path
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return len(path) >= n && path[0:n] == pattern
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2009-04-07 01:40:07 -06:00
|
|
|
// Return the canonical path for p, eliminating . and .. elements.
|
|
|
|
func cleanPath(p string) string {
|
|
|
|
if p == "" {
|
2009-11-09 13:07:39 -07:00
|
|
|
return "/"
|
2009-04-07 01:40:07 -06:00
|
|
|
}
|
|
|
|
if p[0] != '/' {
|
2009-11-09 22:23:52 -07:00
|
|
|
p = "/" + p
|
2009-04-07 01:40:07 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
np := path.Clean(p)
|
2009-04-07 01:40:07 -06:00
|
|
|
// path.Clean removes trailing slash except for root;
|
|
|
|
// put the trailing slash back if necessary.
|
|
|
|
if p[len(p)-1] == '/' && np != "/" {
|
2009-11-09 13:07:39 -07:00
|
|
|
np += "/"
|
2009-04-07 01:40:07 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return np
|
2009-04-07 01:40:07 -06:00
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// ServeHTTP dispatches the request to the handler whose
|
|
|
|
// pattern most closely matches the request URL.
|
2010-09-28 22:30:12 -06:00
|
|
|
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
2009-04-07 01:40:07 -06:00
|
|
|
// Clean path to canonical form and redirect.
|
2010-09-28 22:30:12 -06:00
|
|
|
if p := cleanPath(r.URL.Path); p != r.URL.Path {
|
|
|
|
w.SetHeader("Location", p)
|
|
|
|
w.WriteHeader(StatusMovedPermanently)
|
2009-12-15 16:35:38 -07:00
|
|
|
return
|
2009-04-07 01:40:07 -06:00
|
|
|
}
|
|
|
|
|
2009-02-02 19:01:32 -07:00
|
|
|
// Most-specific (longest) pattern wins.
|
2009-12-15 16:35:38 -07:00
|
|
|
var h Handler
|
|
|
|
var n = 0
|
2009-02-02 19:01:32 -07:00
|
|
|
for k, v := range mux.m {
|
2010-09-28 22:30:12 -06:00
|
|
|
if !pathMatch(k, r.URL.Path) {
|
2009-11-09 13:07:39 -07:00
|
|
|
continue
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
if h == nil || len(k) > n {
|
2009-12-15 16:35:38 -07:00
|
|
|
n = len(k)
|
|
|
|
h = v
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if h == nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
h = NotFoundHandler()
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2010-09-28 22:30:12 -06:00
|
|
|
h.ServeHTTP(w, r)
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2008-09-24 16:26:55 -06:00
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// Handle registers the handler for the given pattern.
|
2009-02-02 19:01:32 -07:00
|
|
|
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
|
|
|
if pattern == "" || pattern[0] != '/' {
|
2010-03-24 17:46:53 -06:00
|
|
|
panic("http: invalid pattern " + pattern)
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
|
2009-12-15 16:35:38 -07:00
|
|
|
mux.m[pattern] = handler
|
2009-02-02 19:01:32 -07:00
|
|
|
|
|
|
|
// Helpful behavior:
|
2009-05-12 16:41:19 -06:00
|
|
|
// If pattern is /tree/, insert permanent redirect for /tree.
|
2009-12-15 16:35:38 -07:00
|
|
|
n := len(pattern)
|
2009-02-02 19:01:32 -07:00
|
|
|
if n > 0 && pattern[n-1] == '/' {
|
2009-11-09 22:23:52 -07:00
|
|
|
mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently)
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-28 17:02:37 -06:00
|
|
|
// HandleFunc registers the handler function for the given pattern.
|
2010-09-28 22:30:12 -06:00
|
|
|
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
|
2010-03-28 17:02:37 -06:00
|
|
|
mux.Handle(pattern, HandlerFunc(handler))
|
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// Handle registers the handler for the given pattern
|
|
|
|
// in the DefaultServeMux.
|
2009-12-15 16:35:38 -07:00
|
|
|
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
|
2009-02-02 19:01:32 -07:00
|
|
|
|
2010-03-28 17:02:37 -06:00
|
|
|
// HandleFunc registers the handler function for the given pattern
|
|
|
|
// in the DefaultServeMux.
|
2010-09-28 22:30:12 -06:00
|
|
|
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
|
2010-03-28 17:02:37 -06:00
|
|
|
DefaultServeMux.HandleFunc(pattern, handler)
|
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// 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.
|
2009-04-17 01:08:24 -06:00
|
|
|
func Serve(l net.Listener, handler Handler) os.Error {
|
2009-02-02 19:01:32 -07:00
|
|
|
if handler == nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
handler = DefaultServeMux
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2008-09-24 16:26:55 -06:00
|
|
|
for {
|
2009-12-15 16:35:38 -07:00
|
|
|
rw, e := l.Accept()
|
2008-09-24 16:26:55 -06:00
|
|
|
if e != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
return e
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
c, err := newConn(rw, handler)
|
2009-02-02 19:01:32 -07:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
continue
|
2009-02-02 19:01:32 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
go c.serve()
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
panic("not reached")
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
|
|
|
|
2009-03-11 13:51:10 -06:00
|
|
|
// 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 (
|
2010-04-05 23:55:05 -06:00
|
|
|
// "http"
|
|
|
|
// "io"
|
|
|
|
// "log"
|
2009-03-11 13:51:10 -06:00
|
|
|
// )
|
|
|
|
//
|
|
|
|
// // hello world, the web server
|
2010-09-28 22:30:12 -06:00
|
|
|
// func HelloServer(w http.ResponseWriter, req *http.Request) {
|
|
|
|
// io.WriteString(w, "hello, world!\n")
|
2009-03-11 13:51:10 -06:00
|
|
|
// }
|
|
|
|
//
|
|
|
|
// func main() {
|
2010-04-05 23:55:05 -06:00
|
|
|
// http.HandleFunc("/hello", HelloServer)
|
|
|
|
// err := http.ListenAndServe(":12345", nil)
|
2009-03-11 13:51:10 -06:00
|
|
|
// if err != nil {
|
2010-04-05 23:55:05 -06:00
|
|
|
// log.Exit("ListenAndServe: ", err.String())
|
2009-03-11 13:51:10 -06:00
|
|
|
// }
|
|
|
|
// }
|
2009-04-17 01:08:24 -06:00
|
|
|
func ListenAndServe(addr string, handler Handler) os.Error {
|
2009-12-15 16:35:38 -07:00
|
|
|
l, e := net.Listen("tcp", addr)
|
2008-09-24 16:26:55 -06:00
|
|
|
if e != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
return e
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
e = Serve(l, handler)
|
|
|
|
l.Close()
|
|
|
|
return e
|
2008-09-24 16:26:55 -06:00
|
|
|
}
|
2010-07-02 11:00:18 -06:00
|
|
|
|
2010-07-02 14:43:48 -06:00
|
|
|
// ListenAndServeTLS acts identically to ListenAndServe, except that it
|
|
|
|
// expects HTTPS connections. Additionally, files containing a certificate and
|
2010-07-02 11:00:18 -06:00
|
|
|
// matching private key for the server must be provided.
|
|
|
|
//
|
|
|
|
// A trivial example server is:
|
|
|
|
//
|
|
|
|
// import (
|
|
|
|
// "http"
|
|
|
|
// "log"
|
|
|
|
// )
|
|
|
|
//
|
2010-09-28 22:30:12 -06:00
|
|
|
// func handler(w http.ResponseWriter, req *http.Request) {
|
|
|
|
// w.SetHeader("Content-Type", "text/plain")
|
|
|
|
// w.Write([]byte("This is an example server.\n"))
|
2010-07-02 11:00:18 -06:00
|
|
|
// }
|
|
|
|
//
|
|
|
|
// func main() {
|
|
|
|
// http.HandleFunc("/", handler)
|
log: new interface
New logging interface simplifies and generalizes.
1) Loggers now have only one output.
2) log.Stdout, Stderr, Crash and friends are gone.
Logging is now always to standard error by default.
3) log.Panic* replaces log.Crash*.
4) Exiting and panicking are not part of the logger's state; instead
the functions Exit* and Panic* simply call Exit or panic after
printing.
5) There is now one 'standard logger'. Instead of calling Stderr,
use Print etc. There are now triples, by analogy with fmt:
Print, Println, Printf
What was log.Stderr is now best represented by log.Println,
since there are now separate Print and Println functions
(and methods).
6) New functions SetOutput, SetFlags, and SetPrefix allow global
editing of the standard logger's properties. This is new
functionality. For instance, one can call
log.SetFlags(log.Lshortfile|log.Ltime|log.Lmicroseconds)
to get all logging output to show file name, line number, and
time stamp.
In short, for most purposes
log.Stderr -> log.Println or log.Print
log.Stderrf -> log.Printf
log.Crash -> log.Panicln or log.Panic
log.Crashf -> log.Panicf
log.Exit -> log.Exitln or log.Exit
log.Exitf -> log.Exitf (no change)
This has a slight breakage: since loggers now write only to one
output, existing calls to log.New() need to delete the second argument.
Also, custom loggers with exit or panic properties will need to be
reworked.
All package code updated to new interface.
The test has been reworked somewhat.
The old interface will be removed after the new release.
For now, its elements are marked 'deprecated' in their comments.
Fixes #1184.
R=rsc
CC=golang-dev
https://golang.org/cl/2419042
2010-10-12 13:59:18 -06:00
|
|
|
// log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
|
2010-08-16 09:22:22 -06:00
|
|
|
// err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
|
2010-07-02 11:00:18 -06:00
|
|
|
// if err != nil {
|
|
|
|
// log.Exit(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) os.Error {
|
|
|
|
config := &tls.Config{
|
|
|
|
Rand: rand.Reader,
|
|
|
|
Time: time.Seconds,
|
|
|
|
NextProtos: []string{"http/1.1"},
|
|
|
|
}
|
|
|
|
|
|
|
|
var err os.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 Serve(tlsListener, handler)
|
|
|
|
}
|