2008-09-24 15:26:55 -07: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 18:01:32 -08:00
|
|
|
// HTTP server. See RFC 2616.
|
2008-09-24 15:26:55 -07:00
|
|
|
|
|
|
|
|
package http
|
|
|
|
|
|
|
|
|
|
import (
|
2009-12-15 15:35:38 -08:00
|
|
|
"bufio"
|
2010-07-02 13:00:18 -04:00
|
|
|
"crypto/tls"
|
2011-11-01 22:04:37 -04:00
|
|
|
"errors"
|
2009-12-15 15:35:38 -08:00
|
|
|
"fmt"
|
|
|
|
|
"io"
|
2011-10-14 17:34:07 -07:00
|
|
|
"io/ioutil"
|
2009-12-15 15:35:38 -08:00
|
|
|
"log"
|
|
|
|
|
"net"
|
2011-11-08 15:41:54 -08:00
|
|
|
"net/url"
|
2013-08-08 14:02:54 -07:00
|
|
|
"os"
|
2009-12-15 15:35:38 -08:00
|
|
|
"path"
|
2012-11-22 08:18:45 +11:00
|
|
|
"runtime"
|
2009-12-15 15:35:38 -08:00
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
2011-04-15 12:53:32 -07:00
|
|
|
"sync"
|
2014-02-28 07:40:25 -08:00
|
|
|
"sync/atomic"
|
2010-07-02 13:00:18 -04:00
|
|
|
"time"
|
2008-09-24 15:26:55 -07:00
|
|
|
)
|
|
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// Errors introduced by the HTTP server.
|
|
|
|
|
var (
|
2011-11-01 22:04:37 -04:00
|
|
|
ErrWriteAfterFlush = errors.New("Conn.Write called after Flush")
|
2012-05-23 09:31:24 -07:00
|
|
|
ErrBodyNotAllowed = errors.New("http: request method or response status code does not allow body")
|
2011-11-01 22:04:37 -04:00
|
|
|
ErrHijacked = errors.New("Conn has been hijacked")
|
|
|
|
|
ErrContentLength = errors.New("Conn.Write wrote more than the declared Content-Length")
|
2009-03-11 12:51:10 -07:00
|
|
|
)
|
2009-02-02 18:01:32 -08:00
|
|
|
|
2009-10-15 00:27:40 -07:00
|
|
|
// Objects implementing the Handler interface can be
|
2009-03-11 12:51:10 -07:00
|
|
|
// registered to serve a particular path or subtree
|
|
|
|
|
// in the HTTP server.
|
2010-02-12 14:27:44 -08:00
|
|
|
//
|
2010-09-29 14:30:12 +10:00
|
|
|
// ServeHTTP should write reply headers and data to the ResponseWriter
|
2010-02-12 14:27:44 -08: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 18:01:32 -08:00
|
|
|
type Handler interface {
|
2010-09-29 14:30:12 +10:00
|
|
|
ServeHTTP(ResponseWriter, *Request)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A ResponseWriter interface is used by an HTTP handler to
|
|
|
|
|
// construct an HTTP response.
|
|
|
|
|
type ResponseWriter interface {
|
2011-03-09 09:41:01 -08:00
|
|
|
// 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
|
2010-09-29 14:30:12 +10:00
|
|
|
|
|
|
|
|
// 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)
|
2012-02-12 23:14:48 -05:00
|
|
|
// before writing the data. If the Header does not contain a
|
|
|
|
|
// Content-Type line, Write adds a Content-Type set to the result of passing
|
|
|
|
|
// the initial 512 bytes of written data to DetectContentType.
|
2011-11-01 22:04:37 -04:00
|
|
|
Write([]byte) (int, error)
|
2010-09-29 14:30:12 +10:00
|
|
|
|
|
|
|
|
// 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)
|
2011-03-09 10:24:50 -08:00
|
|
|
}
|
2010-09-29 14:30:12 +10:00
|
|
|
|
2011-03-09 10:24:50 -08:00
|
|
|
// 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 {
|
2010-09-29 14:30:12 +10:00
|
|
|
// Flush sends any buffered data to the client.
|
|
|
|
|
Flush()
|
2011-03-06 18:59:50 -08:00
|
|
|
}
|
2010-09-29 14:30:12 +10:00
|
|
|
|
2011-03-07 12:04:04 -08:00
|
|
|
// The Hijacker interface is implemented by ResponseWriters that allow
|
|
|
|
|
// an HTTP handler to take over the connection.
|
2011-03-06 18:59:50 -08:00
|
|
|
type Hijacker interface {
|
2010-09-29 14:30:12 +10:00
|
|
|
// 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.
|
2011-11-01 22:04:37 -04:00
|
|
|
Hijack() (net.Conn, *bufio.ReadWriter, error)
|
2010-09-29 14:30:12 +10:00
|
|
|
}
|
|
|
|
|
|
2012-12-05 19:25:43 -08:00
|
|
|
// The CloseNotifier interface is implemented by ResponseWriters which
|
|
|
|
|
// allow detecting when the underlying connection has gone away.
|
|
|
|
|
//
|
|
|
|
|
// This mechanism can be used to cancel long operations on the server
|
|
|
|
|
// if the client has disconnected before the response is ready.
|
|
|
|
|
type CloseNotifier interface {
|
|
|
|
|
// CloseNotify returns a channel that receives a single value
|
|
|
|
|
// when the client connection has gone away.
|
|
|
|
|
CloseNotify() <-chan bool
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-29 14:30:12 +10:00
|
|
|
// A conn represents the server side of an HTTP connection.
|
|
|
|
|
type conn struct {
|
2011-03-10 08:17:22 -08:00
|
|
|
remoteAddr string // network address of remote side
|
2011-08-09 10:55:14 -07:00
|
|
|
server *Server // the Server on which the connection arrived
|
2011-03-10 08:17:22 -08:00
|
|
|
rwc net.Conn // i/o connection
|
2013-03-21 20:02:01 -07:00
|
|
|
sr liveSwitchReader // where the LimitReader reads from; usually the rwc
|
2012-12-05 19:25:43 -08:00
|
|
|
lr *io.LimitedReader // io.LimitReader(sr)
|
|
|
|
|
buf *bufio.ReadWriter // buffered(lr,rwc), reading from bufio->limitReader->sr->rwc
|
2011-07-15 01:01:49 -04:00
|
|
|
tlsState *tls.ConnectionState // or nil when not using TLS
|
2012-12-05 19:25:43 -08:00
|
|
|
|
|
|
|
|
mu sync.Mutex // guards the following
|
|
|
|
|
clientGone bool // if client has disconnected mid-request
|
|
|
|
|
closeNotifyc chan bool // made lazily
|
|
|
|
|
hijackedv bool // connection has been hijacked by handler
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *conn) hijacked() bool {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
return c.hijackedv
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *conn) hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
if c.hijackedv {
|
|
|
|
|
return nil, nil, ErrHijacked
|
|
|
|
|
}
|
|
|
|
|
if c.closeNotifyc != nil {
|
|
|
|
|
return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier")
|
|
|
|
|
}
|
|
|
|
|
c.hijackedv = true
|
|
|
|
|
rwc = c.rwc
|
|
|
|
|
buf = c.buf
|
|
|
|
|
c.rwc = nil
|
|
|
|
|
c.buf = nil
|
2014-03-03 18:58:28 -08:00
|
|
|
c.setState(rwc, StateHijacked)
|
2012-12-05 19:25:43 -08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *conn) closeNotify() <-chan bool {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
if c.closeNotifyc == nil {
|
2013-04-22 10:32:10 -07:00
|
|
|
c.closeNotifyc = make(chan bool, 1)
|
2012-12-05 19:25:43 -08:00
|
|
|
if c.hijackedv {
|
|
|
|
|
// to obey the function signature, even though
|
|
|
|
|
// it'll never receive a value.
|
|
|
|
|
return c.closeNotifyc
|
|
|
|
|
}
|
|
|
|
|
pr, pw := io.Pipe()
|
|
|
|
|
|
|
|
|
|
readSource := c.sr.r
|
|
|
|
|
c.sr.Lock()
|
|
|
|
|
c.sr.r = pr
|
|
|
|
|
c.sr.Unlock()
|
|
|
|
|
go func() {
|
|
|
|
|
_, err := io.Copy(pw, readSource)
|
|
|
|
|
if err == nil {
|
|
|
|
|
err = io.EOF
|
|
|
|
|
}
|
|
|
|
|
pw.CloseWithError(err)
|
|
|
|
|
c.noteClientGone()
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
return c.closeNotifyc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *conn) noteClientGone() {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
if c.closeNotifyc != nil && !c.clientGone {
|
|
|
|
|
c.closeNotifyc <- true
|
|
|
|
|
}
|
|
|
|
|
c.clientGone = true
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-21 20:02:01 -07:00
|
|
|
// A switchReader can have its Reader changed at runtime.
|
|
|
|
|
// It's not safe for concurrent Reads and switches.
|
2012-12-05 19:25:43 -08:00
|
|
|
type switchReader struct {
|
2013-03-21 20:02:01 -07:00
|
|
|
io.Reader
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A switchWriter can have its Writer changed at runtime.
|
|
|
|
|
// It's not safe for concurrent Writes and switches.
|
|
|
|
|
type switchWriter struct {
|
|
|
|
|
io.Writer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A liveSwitchReader is a switchReader that's safe for concurrent
|
|
|
|
|
// reads and switches, if its mutex is held.
|
|
|
|
|
type liveSwitchReader struct {
|
2012-12-05 19:25:43 -08:00
|
|
|
sync.Mutex
|
|
|
|
|
r io.Reader
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-21 20:02:01 -07:00
|
|
|
func (sr *liveSwitchReader) Read(p []byte) (n int, err error) {
|
2012-12-05 19:25:43 -08:00
|
|
|
sr.Lock()
|
|
|
|
|
r := sr.r
|
|
|
|
|
sr.Unlock()
|
|
|
|
|
return r.Read(p)
|
2010-09-29 14:30:12 +10:00
|
|
|
}
|
|
|
|
|
|
2013-01-11 10:03:43 -08:00
|
|
|
// This should be >= 512 bytes for DetectContentType,
|
|
|
|
|
// but otherwise it's somewhat arbitrary.
|
|
|
|
|
const bufferBeforeChunkingSize = 2048
|
|
|
|
|
|
|
|
|
|
// chunkWriter writes to a response's conn buffer, and is the writer
|
|
|
|
|
// wrapped by the response.bufw buffered writer.
|
|
|
|
|
//
|
|
|
|
|
// chunkWriter also is responsible for finalizing the Header, including
|
|
|
|
|
// conditionally setting the Content-Type and setting a Content-Length
|
|
|
|
|
// in cases where the handler's final output is smaller than the buffer
|
|
|
|
|
// size. It also conditionally adds chunk headers, when in chunking mode.
|
|
|
|
|
//
|
|
|
|
|
// See the comment above (*response).Write for the entire write flow.
|
|
|
|
|
type chunkWriter struct {
|
2013-03-28 11:35:24 -07:00
|
|
|
res *response
|
|
|
|
|
|
2013-04-02 16:27:23 -07:00
|
|
|
// header is either nil or a deep clone of res.handlerHeader
|
|
|
|
|
// at the time of res.WriteHeader, if res.WriteHeader is
|
|
|
|
|
// called and extra buffering is being done to calculate
|
|
|
|
|
// Content-Type and/or Content-Length.
|
2013-03-28 11:35:24 -07:00
|
|
|
header Header
|
|
|
|
|
|
|
|
|
|
// wroteHeader tells whether the header's been written to "the
|
|
|
|
|
// wire" (or rather: w.conn.buf). this is unlike
|
|
|
|
|
// (*response).wroteHeader, which tells only whether it was
|
|
|
|
|
// logically written.
|
|
|
|
|
wroteHeader bool
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
// set by the writeHeader method:
|
|
|
|
|
chunking bool // using chunked transfer encoding for reply body
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-02 16:27:23 -07:00
|
|
|
var (
|
|
|
|
|
crlf = []byte("\r\n")
|
|
|
|
|
colonSpace = []byte(": ")
|
|
|
|
|
)
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
func (cw *chunkWriter) Write(p []byte) (n int, err error) {
|
|
|
|
|
if !cw.wroteHeader {
|
|
|
|
|
cw.writeHeader(p)
|
|
|
|
|
}
|
net/http: treat HEAD requests like GET requests
A response to a HEAD request is supposed to look the same as a
response to a GET request, just without a body.
HEAD requests are incredibly rare in the wild.
The Go net/http package has so far treated HEAD requests
specially: a Write on our default ResponseWriter returned
ErrBodyNotAllowed, telling handlers that something was wrong.
This was to optimize the fast path for HEAD requests, but:
1) because HEAD requests are incredibly rare, they're not
worth having a fast path for.
2) Letting the http.Handler handle but do nop Writes is still
very fast.
3) this forces ugly error handling into the application.
e.g. https://code.google.com/p/go/source/detail?r=6f596be7a31e
and related.
4) The net/http package nowadays does Content-Type sniffing,
but you don't get that for HEAD.
5) The net/http package nowadays does Content-Length counting
for small (few KB) responses, but not for HEAD.
6) ErrBodyNotAllowed was useless. By the time you received it,
you had probably already done all your heavy computation
and I/O to calculate what to write.
So, this change makes HEAD requests like GET requests.
We now count content-length and sniff content-type for HEAD
requests. If you Write, it doesn't return an error.
If you want a fast-path in your code for HEAD, you have to do
it early and set all the response headers yourself. Just like
before. If you choose not to Write in HEAD requests, be sure
to set Content-Length if you know it. We won't write
"Content-Length: 0" because you might've just chosen to not
write (or you don't know your Content-Length in advance).
Fixes #5454
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/12583043
2013-08-06 18:33:03 -07:00
|
|
|
if cw.res.req.Method == "HEAD" {
|
|
|
|
|
// Eat writes.
|
|
|
|
|
return len(p), nil
|
|
|
|
|
}
|
2013-01-11 10:03:43 -08:00
|
|
|
if cw.chunking {
|
|
|
|
|
_, err = fmt.Fprintf(cw.res.conn.buf, "%x\r\n", len(p))
|
|
|
|
|
if err != nil {
|
2013-02-04 20:26:25 -08:00
|
|
|
cw.res.conn.rwc.Close()
|
2013-01-11 10:03:43 -08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
n, err = cw.res.conn.buf.Write(p)
|
|
|
|
|
if cw.chunking && err == nil {
|
|
|
|
|
_, err = cw.res.conn.buf.Write(crlf)
|
|
|
|
|
}
|
2013-02-04 20:26:25 -08:00
|
|
|
if err != nil {
|
|
|
|
|
cw.res.conn.rwc.Close()
|
|
|
|
|
}
|
2013-01-11 10:03:43 -08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (cw *chunkWriter) flush() {
|
|
|
|
|
if !cw.wroteHeader {
|
|
|
|
|
cw.writeHeader(nil)
|
|
|
|
|
}
|
|
|
|
|
cw.res.conn.buf.Flush()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (cw *chunkWriter) close() {
|
|
|
|
|
if !cw.wroteHeader {
|
|
|
|
|
cw.writeHeader(nil)
|
|
|
|
|
}
|
|
|
|
|
if cw.chunking {
|
|
|
|
|
// zero EOF chunk, trailer key/value pairs (currently
|
|
|
|
|
// unsupported in Go's server), followed by a blank
|
|
|
|
|
// line.
|
2013-05-20 19:26:26 -07:00
|
|
|
cw.res.conn.buf.WriteString("0\r\n\r\n")
|
2013-01-11 10:03:43 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-29 14:30:12 +10:00
|
|
|
// A response represents the server side of an HTTP response.
|
|
|
|
|
type response struct {
|
|
|
|
|
conn *conn
|
2011-03-09 09:41:01 -08:00
|
|
|
req *Request // request for this response
|
2013-01-11 10:03:43 -08:00
|
|
|
wroteHeader bool // reply header has been (logically) written
|
2011-03-09 09:41:01 -08:00
|
|
|
wroteContinue bool // 100 Continue response was written
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
w *bufio.Writer // buffers output in chunks to chunkWriter
|
2013-03-28 13:13:28 -07:00
|
|
|
cw chunkWriter
|
2013-03-27 13:35:49 -07:00
|
|
|
sw *switchWriter // of the bufio.Writer, for return to putBufioWriter
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
// handlerHeader is the Header that Handlers get access to,
|
|
|
|
|
// which may be retained and mutated even after WriteHeader.
|
|
|
|
|
// handlerHeader is copied into cw.header at WriteHeader
|
|
|
|
|
// time, and privately mutated thereafter.
|
|
|
|
|
handlerHeader Header
|
2013-03-28 11:35:24 -07:00
|
|
|
calledHeader bool // handler accessed handlerHeader via Header
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
written int64 // number of bytes written in body
|
|
|
|
|
contentLength int64 // explicitly-declared Content-Length; or -1
|
|
|
|
|
status int // status code passed to WriteHeader
|
2010-09-27 21:55:04 -04:00
|
|
|
|
|
|
|
|
// 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
|
2011-08-23 12:17:21 +04:00
|
|
|
|
|
|
|
|
// requestBodyLimitHit is set by requestTooLarge when
|
|
|
|
|
// maxBytesReader hits its max size. It is checked in
|
2012-11-22 02:58:24 +08:00
|
|
|
// WriteHeader, to make sure we don't consume the
|
2011-08-23 12:17:21 +04:00
|
|
|
// remaining request body to try to advance to the next HTTP
|
2012-05-29 12:40:13 -07:00
|
|
|
// request. Instead, when this is set, we stop reading
|
2011-08-23 12:17:21 +04:00
|
|
|
// subsequent requests on this connection and stop reading
|
|
|
|
|
// input from it.
|
|
|
|
|
requestBodyLimitHit bool
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
handlerDone bool // set true when the handler exits
|
2013-05-19 20:15:40 -07:00
|
|
|
|
|
|
|
|
// Buffers for Date and Content-Length
|
|
|
|
|
dateBuf [len(TimeFormat)]byte
|
|
|
|
|
clenBuf [10]byte
|
2011-08-23 12:17:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// requestTooLarge is called by maxBytesReader when too much input has
|
|
|
|
|
// been read from the client.
|
2011-10-14 17:34:07 -07:00
|
|
|
func (w *response) requestTooLarge() {
|
|
|
|
|
w.closeAfterReply = true
|
|
|
|
|
w.requestBodyLimitHit = true
|
|
|
|
|
if !w.wroteHeader {
|
|
|
|
|
w.Header().Set("Connection", "close")
|
2011-08-23 12:17:21 +04:00
|
|
|
}
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2013-07-23 11:59:49 +10:00
|
|
|
// needsSniff reports whether a Content-Type still needs to be sniffed.
|
2013-01-11 10:03:43 -08:00
|
|
|
func (w *response) needsSniff() bool {
|
2013-10-15 08:22:04 +11:00
|
|
|
_, haveType := w.handlerHeader["Content-Type"]
|
|
|
|
|
return !w.cw.wroteHeader && !haveType && w.written < sniffLen
|
2013-01-11 10:03:43 -08:00
|
|
|
}
|
|
|
|
|
|
2013-08-08 14:02:54 -07:00
|
|
|
// writerOnly hides an io.Writer value's optional ReadFrom method
|
|
|
|
|
// from io.Copy.
|
2011-05-25 10:15:26 -07:00
|
|
|
type writerOnly struct {
|
|
|
|
|
io.Writer
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-08 14:02:54 -07:00
|
|
|
func srcIsRegularFile(src io.Reader) (isRegular bool, err error) {
|
|
|
|
|
switch v := src.(type) {
|
|
|
|
|
case *os.File:
|
|
|
|
|
fi, err := v.Stat()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
|
|
|
|
return fi.Mode().IsRegular(), nil
|
|
|
|
|
case *io.LimitedReader:
|
|
|
|
|
return srcIsRegularFile(v.R)
|
|
|
|
|
default:
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReadFrom is here to optimize copying from an *os.File regular file
|
|
|
|
|
// to a *net.TCPConn with sendfile.
|
2011-11-01 22:04:37 -04:00
|
|
|
func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
|
2013-08-08 14:02:54 -07:00
|
|
|
// Our underlying w.conn.rwc is usually a *TCPConn (with its
|
|
|
|
|
// own ReadFrom method). If not, or if our src isn't a regular
|
|
|
|
|
// file, just fall back to the normal copy method.
|
|
|
|
|
rf, ok := w.conn.rwc.(io.ReaderFrom)
|
|
|
|
|
regFile, err := srcIsRegularFile(src)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
if !ok || !regFile {
|
|
|
|
|
return io.Copy(writerOnly{w}, src)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sendfile path:
|
|
|
|
|
|
2011-11-09 15:48:05 +11:00
|
|
|
if !w.wroteHeader {
|
|
|
|
|
w.WriteHeader(StatusOK)
|
|
|
|
|
}
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
if w.needsSniff() {
|
|
|
|
|
n0, err := io.Copy(writerOnly{w}, io.LimitReader(src, sniffLen))
|
|
|
|
|
n += n0
|
|
|
|
|
if err != nil {
|
|
|
|
|
return n, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w.w.Flush() // get rid of any previous writes
|
|
|
|
|
w.cw.flush() // make sure Header is written; flush data to rwc
|
|
|
|
|
|
|
|
|
|
// Now that cw has been flushed, its chunking field is guaranteed initialized.
|
|
|
|
|
if !w.cw.chunking && w.bodyAllowed() {
|
2013-08-08 14:02:54 -07:00
|
|
|
n0, err := rf.ReadFrom(src)
|
|
|
|
|
n += n0
|
|
|
|
|
w.written += n0
|
|
|
|
|
return n, err
|
2011-05-25 10:15:26 -07:00
|
|
|
}
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
n0, err := io.Copy(writerOnly{w}, src)
|
|
|
|
|
n += n0
|
|
|
|
|
return n, err
|
2011-05-25 10:15:26 -07:00
|
|
|
}
|
|
|
|
|
|
2011-08-09 10:55:14 -07:00
|
|
|
// noLimit is an effective infinite upper bound for io.LimitedReader
|
|
|
|
|
const noLimit int64 = (1 << 63) - 1
|
|
|
|
|
|
net/http: fix Transport races & deadlocks
Thanks to Dustin Sallings for exposing the most frustrating
bug ever, and for providing repro cases (which formed the
basis of the new tests in this CL), and to Dave Cheney and
Dmitry Vyukov for help debugging and fixing.
This CL depends on submited pollster CLs ffd1e075c260 (Unix)
and 14b544194509 (Windows), as well as unsubmitted 6852085.
Some operating systems (OpenBSD, NetBSD, ?) may still require
more pollster work, fixing races (Issue 4434 and
http://goo.gl/JXB6W).
Tested on linux-amd64 and darwin-amd64, both with GOMAXPROCS 1
and 4 (all combinations of which previously failed differently)
Fixes #4191
Update #4434 (related fallout from this bug)
R=dave, bradfitz, dsallings, rsc, fullung
CC=golang-dev
https://golang.org/cl/6851061
2012-11-26 13:31:02 -08:00
|
|
|
// debugServerConnections controls whether all server connections are wrapped
|
|
|
|
|
// with a verbose logging wrapper.
|
|
|
|
|
const debugServerConnections = false
|
|
|
|
|
|
2009-02-02 18:01:32 -08:00
|
|
|
// Create new connection from rwc.
|
2011-11-01 22:04:37 -04:00
|
|
|
func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
|
2010-09-29 14:30:12 +10:00
|
|
|
c = new(conn)
|
|
|
|
|
c.remoteAddr = rwc.RemoteAddr().String()
|
2011-08-09 10:55:14 -07:00
|
|
|
c.server = srv
|
2009-12-15 15:35:38 -08:00
|
|
|
c.rwc = rwc
|
net/http: fix Transport races & deadlocks
Thanks to Dustin Sallings for exposing the most frustrating
bug ever, and for providing repro cases (which formed the
basis of the new tests in this CL), and to Dave Cheney and
Dmitry Vyukov for help debugging and fixing.
This CL depends on submited pollster CLs ffd1e075c260 (Unix)
and 14b544194509 (Windows), as well as unsubmitted 6852085.
Some operating systems (OpenBSD, NetBSD, ?) may still require
more pollster work, fixing races (Issue 4434 and
http://goo.gl/JXB6W).
Tested on linux-amd64 and darwin-amd64, both with GOMAXPROCS 1
and 4 (all combinations of which previously failed differently)
Fixes #4191
Update #4434 (related fallout from this bug)
R=dave, bradfitz, dsallings, rsc, fullung
CC=golang-dev
https://golang.org/cl/6851061
2012-11-26 13:31:02 -08:00
|
|
|
if debugServerConnections {
|
|
|
|
|
c.rwc = newLoggingConn("server", c.rwc)
|
|
|
|
|
}
|
2013-03-21 20:02:01 -07:00
|
|
|
c.sr = liveSwitchReader{r: c.rwc}
|
2012-12-05 19:25:43 -08:00
|
|
|
c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
|
2013-08-10 19:22:44 -07:00
|
|
|
br := newBufioReader(c.lr)
|
|
|
|
|
bw := newBufioWriterSize(c.rwc, 4<<10)
|
2009-12-15 15:35:38 -08:00
|
|
|
c.buf = bufio.NewReadWriter(br, bw)
|
|
|
|
|
return c, nil
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2013-03-21 20:02:01 -07:00
|
|
|
var (
|
2013-12-18 15:52:20 -08:00
|
|
|
bufioReaderPool sync.Pool
|
|
|
|
|
bufioWriter2kPool sync.Pool
|
|
|
|
|
bufioWriter4kPool sync.Pool
|
2013-03-21 20:02:01 -07:00
|
|
|
)
|
|
|
|
|
|
2013-12-18 15:52:20 -08:00
|
|
|
func bufioWriterPool(size int) *sync.Pool {
|
2013-03-27 13:35:49 -07:00
|
|
|
switch size {
|
|
|
|
|
case 2 << 10:
|
2013-12-18 15:52:20 -08:00
|
|
|
return &bufioWriter2kPool
|
2013-03-27 13:35:49 -07:00
|
|
|
case 4 << 10:
|
2013-12-18 15:52:20 -08:00
|
|
|
return &bufioWriter4kPool
|
2013-03-27 13:35:49 -07:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-10 19:22:44 -07:00
|
|
|
func newBufioReader(r io.Reader) *bufio.Reader {
|
2013-12-18 15:52:20 -08:00
|
|
|
if v := bufioReaderPool.Get(); v != nil {
|
|
|
|
|
br := v.(*bufio.Reader)
|
|
|
|
|
br.Reset(r)
|
|
|
|
|
return br
|
2013-03-21 20:02:01 -07:00
|
|
|
}
|
2013-12-18 15:52:20 -08:00
|
|
|
return bufio.NewReader(r)
|
2013-03-21 20:02:01 -07:00
|
|
|
}
|
|
|
|
|
|
2013-08-10 19:22:44 -07:00
|
|
|
func putBufioReader(br *bufio.Reader) {
|
|
|
|
|
br.Reset(nil)
|
2013-12-18 15:52:20 -08:00
|
|
|
bufioReaderPool.Put(br)
|
2013-03-21 20:02:01 -07:00
|
|
|
}
|
|
|
|
|
|
2013-08-10 19:22:44 -07:00
|
|
|
func newBufioWriterSize(w io.Writer, size int) *bufio.Writer {
|
2013-12-18 15:52:20 -08:00
|
|
|
pool := bufioWriterPool(size)
|
|
|
|
|
if pool != nil {
|
|
|
|
|
if v := pool.Get(); v != nil {
|
|
|
|
|
bw := v.(*bufio.Writer)
|
|
|
|
|
bw.Reset(w)
|
|
|
|
|
return bw
|
|
|
|
|
}
|
2013-03-21 20:02:01 -07:00
|
|
|
}
|
2013-12-18 15:52:20 -08:00
|
|
|
return bufio.NewWriterSize(w, size)
|
2013-03-21 20:02:01 -07:00
|
|
|
}
|
|
|
|
|
|
2013-08-10 19:22:44 -07:00
|
|
|
func putBufioWriter(bw *bufio.Writer) {
|
|
|
|
|
bw.Reset(nil)
|
2013-12-18 15:52:20 -08:00
|
|
|
if pool := bufioWriterPool(bw.Available()); pool != nil {
|
|
|
|
|
pool.Put(bw)
|
2013-03-21 20:02:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-09 10:55:14 -07:00
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-03 18:58:28 -08:00
|
|
|
func (srv *Server) initialLimitedReaderSize() int64 {
|
|
|
|
|
return int64(srv.maxHeaderBytes()) + 4096 // bufio slop
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-16 10:15:39 -07:00
|
|
|
// wrapper around io.ReaderCloser which on first read, sends an
|
|
|
|
|
// HTTP/1.1 100 Continue header
|
|
|
|
|
type expectContinueReader struct {
|
2010-09-29 14:30:12 +10:00
|
|
|
resp *response
|
2010-06-16 10:15:39 -07:00
|
|
|
readCloser io.ReadCloser
|
2011-04-14 10:40:23 -07:00
|
|
|
closed bool
|
2010-06-16 10:15:39 -07:00
|
|
|
}
|
|
|
|
|
|
2011-11-01 22:04:37 -04:00
|
|
|
func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
|
2011-04-14 10:40:23 -07:00
|
|
|
if ecr.closed {
|
2012-12-10 01:42:10 -05:00
|
|
|
return 0, ErrBodyReadAfterClose
|
2011-04-14 10:40:23 -07:00
|
|
|
}
|
2012-12-05 19:25:43 -08:00
|
|
|
if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() {
|
2010-09-29 14:30:12 +10:00
|
|
|
ecr.resp.wroteContinue = true
|
2013-05-20 19:26:26 -07:00
|
|
|
ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
|
2010-09-29 14:30:12 +10:00
|
|
|
ecr.resp.conn.buf.Flush()
|
2010-06-16 10:15:39 -07:00
|
|
|
}
|
|
|
|
|
return ecr.readCloser.Read(p)
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-01 22:04:37 -04:00
|
|
|
func (ecr *expectContinueReader) Close() error {
|
2011-04-14 10:40:23 -07:00
|
|
|
ecr.closed = true
|
2010-06-16 10:15:39 -07:00
|
|
|
return ecr.readCloser.Close()
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-02 14:21:11 -04: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"
|
|
|
|
|
|
2013-09-22 19:53:55 -07:00
|
|
|
// appendTime is a non-allocating version of []byte(t.UTC().Format(TimeFormat))
|
2013-05-19 20:15:40 -07:00
|
|
|
func appendTime(b []byte, t time.Time) []byte {
|
|
|
|
|
const days = "SunMonTueWedThuFriSat"
|
|
|
|
|
const months = "JanFebMarAprMayJunJulAugSepOctNovDec"
|
|
|
|
|
|
2013-09-22 19:53:55 -07:00
|
|
|
t = t.UTC()
|
2013-05-19 20:15:40 -07:00
|
|
|
yy, mm, dd := t.Date()
|
|
|
|
|
hh, mn, ss := t.Clock()
|
|
|
|
|
day := days[3*t.Weekday():]
|
|
|
|
|
mon := months[3*(mm-1):]
|
|
|
|
|
|
|
|
|
|
return append(b,
|
|
|
|
|
day[0], day[1], day[2], ',', ' ',
|
|
|
|
|
byte('0'+dd/10), byte('0'+dd%10), ' ',
|
|
|
|
|
mon[0], mon[1], mon[2], ' ',
|
|
|
|
|
byte('0'+yy/1000), byte('0'+(yy/100)%10), byte('0'+(yy/10)%10), byte('0'+yy%10), ' ',
|
|
|
|
|
byte('0'+hh/10), byte('0'+hh%10), ':',
|
|
|
|
|
byte('0'+mn/10), byte('0'+mn%10), ':',
|
|
|
|
|
byte('0'+ss/10), byte('0'+ss%10), ' ',
|
|
|
|
|
'G', 'M', 'T')
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-01 22:04:37 -04:00
|
|
|
var errTooLarge = errors.New("http: request too large")
|
2011-08-09 10:55:14 -07:00
|
|
|
|
2009-02-02 18:01:32 -08:00
|
|
|
// Read next request from connection.
|
2011-11-01 22:04:37 -04:00
|
|
|
func (c *conn) readRequest() (w *response, err error) {
|
2012-12-05 19:25:43 -08:00
|
|
|
if c.hijacked() {
|
2009-11-09 12:07:39 -08:00
|
|
|
return nil, ErrHijacked
|
2009-02-03 14:16:22 -08:00
|
|
|
}
|
2013-02-04 13:52:45 -08:00
|
|
|
|
|
|
|
|
if d := c.server.ReadTimeout; d != 0 {
|
|
|
|
|
c.rwc.SetReadDeadline(time.Now().Add(d))
|
|
|
|
|
}
|
|
|
|
|
if d := c.server.WriteTimeout; d != 0 {
|
|
|
|
|
defer func() {
|
|
|
|
|
c.rwc.SetWriteDeadline(time.Now().Add(d))
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-03 18:58:28 -08:00
|
|
|
c.lr.N = c.server.initialLimitedReaderSize()
|
2010-09-29 14:30:12 +10:00
|
|
|
var req *Request
|
2009-05-08 11:52:39 -07:00
|
|
|
if req, err = ReadRequest(c.buf.Reader); err != nil {
|
2011-08-09 10:55:14 -07:00
|
|
|
if c.lr.N == 0 {
|
|
|
|
|
return nil, errTooLarge
|
|
|
|
|
}
|
2009-11-09 12:07:39 -08:00
|
|
|
return nil, err
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2011-08-09 10:55:14 -07:00
|
|
|
c.lr.N = noLimit
|
2009-02-02 18:01:32 -08:00
|
|
|
|
2011-03-10 08:17:22 -08:00
|
|
|
req.RemoteAddr = c.remoteAddr
|
|
|
|
|
req.TLS = c.tlsState
|
|
|
|
|
|
2013-01-11 10:03:43 -08:00
|
|
|
w = &response{
|
|
|
|
|
conn: c,
|
|
|
|
|
req: req,
|
|
|
|
|
handlerHeader: make(Header),
|
|
|
|
|
contentLength: -1,
|
|
|
|
|
}
|
|
|
|
|
w.cw.res = w
|
2013-08-10 19:22:44 -07:00
|
|
|
w.w = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
|
2010-09-29 14:30:12 +10:00
|
|
|
return w, nil
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2011-03-09 09:41:01 -08:00
|
|
|
func (w *response) Header() Header {
|
2013-03-28 11:35:24 -07:00
|
|
|
if w.cw.header == nil && w.wroteHeader && !w.cw.wroteHeader {
|
|
|
|
|
// Accessing the header between logically writing it
|
|
|
|
|
// and physically writing it means we need to allocate
|
|
|
|
|
// a clone to snapshot the logically written state.
|
|
|
|
|
w.cw.header = w.handlerHeader.clone()
|
|
|
|
|
}
|
|
|
|
|
w.calledHeader = true
|
2013-01-11 10:03:43 -08:00
|
|
|
return w.handlerHeader
|
2011-03-03 12:22:13 -08:00
|
|
|
}
|
2010-09-29 14:30:12 +10:00
|
|
|
|
2011-10-14 17:34:07 -07:00
|
|
|
// maxPostHandlerReadBytes is the max number of Request.Body bytes not
|
2011-12-10 13:02:23 +11:00
|
|
|
// consumed by a handler that the server will read from the client
|
2011-10-14 17:34:07 -07:00
|
|
|
// 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
|
|
|
|
|
|
2010-09-29 14:30:12 +10:00
|
|
|
func (w *response) WriteHeader(code int) {
|
2012-12-05 19:25:43 -08:00
|
|
|
if w.conn.hijacked() {
|
2014-02-28 12:12:51 -08:00
|
|
|
w.conn.server.logf("http: response.WriteHeader on hijacked connection")
|
2009-12-15 15:35:38 -08:00
|
|
|
return
|
2009-02-03 14:16:22 -08:00
|
|
|
}
|
2010-09-29 14:30:12 +10:00
|
|
|
if w.wroteHeader {
|
2014-02-28 12:12:51 -08:00
|
|
|
w.conn.server.logf("http: multiple response.WriteHeader calls")
|
2009-12-15 15:35:38 -08:00
|
|
|
return
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2011-10-14 17:34:07 -07:00
|
|
|
w.wroteHeader = true
|
|
|
|
|
w.status = code
|
|
|
|
|
|
2013-03-28 11:35:24 -07:00
|
|
|
if w.calledHeader && w.cw.header == nil {
|
|
|
|
|
w.cw.header = w.handlerHeader.clone()
|
|
|
|
|
}
|
2013-01-11 10:03:43 -08:00
|
|
|
|
2013-03-28 11:35:24 -07:00
|
|
|
if cl := w.handlerHeader.get("Content-Length"); cl != "" {
|
2013-01-11 10:03:43 -08:00
|
|
|
v, err := strconv.ParseInt(cl, 10, 64)
|
|
|
|
|
if err == nil && v >= 0 {
|
|
|
|
|
w.contentLength = v
|
2011-10-14 17:34:07 -07:00
|
|
|
} else {
|
2014-02-28 12:12:51 -08:00
|
|
|
w.conn.server.logf("http: invalid Content-Length of %q", cl)
|
2013-03-28 11:35:24 -07:00
|
|
|
w.handlerHeader.Del("Content-Length")
|
2013-01-11 10:03:43 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-02 16:27:23 -07:00
|
|
|
// extraHeader is the set of headers sometimes added by chunkWriter.writeHeader.
|
|
|
|
|
// This type is used to avoid extra allocations from cloning and/or populating
|
|
|
|
|
// the response Header map and all its 1-element slices.
|
|
|
|
|
type extraHeader struct {
|
|
|
|
|
contentType string
|
|
|
|
|
connection string
|
|
|
|
|
transferEncoding string
|
2013-05-19 20:15:40 -07:00
|
|
|
date []byte // written if not nil
|
|
|
|
|
contentLength []byte // written if not nil
|
2013-04-02 16:27:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sorted the same as extraHeader.Write's loop.
|
|
|
|
|
var extraHeaderKeys = [][]byte{
|
2013-05-19 20:15:40 -07:00
|
|
|
[]byte("Content-Type"),
|
|
|
|
|
[]byte("Connection"),
|
|
|
|
|
[]byte("Transfer-Encoding"),
|
2013-04-02 16:27:23 -07:00
|
|
|
}
|
|
|
|
|
|
2013-05-19 20:15:40 -07:00
|
|
|
var (
|
|
|
|
|
headerContentLength = []byte("Content-Length: ")
|
|
|
|
|
headerDate = []byte("Date: ")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Write writes the headers described in h to w.
|
|
|
|
|
//
|
|
|
|
|
// This method has a value receiver, despite the somewhat large size
|
|
|
|
|
// of h, because it prevents an allocation. The escape analysis isn't
|
|
|
|
|
// smart enough to realize this function doesn't mutate h.
|
|
|
|
|
func (h extraHeader) Write(w *bufio.Writer) {
|
|
|
|
|
if h.date != nil {
|
|
|
|
|
w.Write(headerDate)
|
|
|
|
|
w.Write(h.date)
|
|
|
|
|
w.Write(crlf)
|
|
|
|
|
}
|
|
|
|
|
if h.contentLength != nil {
|
|
|
|
|
w.Write(headerContentLength)
|
|
|
|
|
w.Write(h.contentLength)
|
|
|
|
|
w.Write(crlf)
|
|
|
|
|
}
|
|
|
|
|
for i, v := range []string{h.contentType, h.connection, h.transferEncoding} {
|
2013-04-02 16:27:23 -07:00
|
|
|
if v != "" {
|
|
|
|
|
w.Write(extraHeaderKeys[i])
|
|
|
|
|
w.Write(colonSpace)
|
2013-05-19 20:15:40 -07:00
|
|
|
w.WriteString(v)
|
2013-04-02 16:27:23 -07:00
|
|
|
w.Write(crlf)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-11 10:03:43 -08:00
|
|
|
// writeHeader finalizes the header sent to the client and writes it
|
|
|
|
|
// to cw.res.conn.buf.
|
|
|
|
|
//
|
|
|
|
|
// p is not written by writeHeader, but is the first chunk of the body
|
|
|
|
|
// that will be written. It is sniffed for a Content-Type if none is
|
|
|
|
|
// set explicitly. It's also used to set the Content-Length, if the
|
|
|
|
|
// total body size was small and the handler has already finished
|
|
|
|
|
// running.
|
|
|
|
|
func (cw *chunkWriter) writeHeader(p []byte) {
|
|
|
|
|
if cw.wroteHeader {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
cw.wroteHeader = true
|
|
|
|
|
|
|
|
|
|
w := cw.res
|
2014-02-28 07:40:25 -08:00
|
|
|
keepAlivesEnabled := w.conn.server.doKeepAlives()
|
net/http: treat HEAD requests like GET requests
A response to a HEAD request is supposed to look the same as a
response to a GET request, just without a body.
HEAD requests are incredibly rare in the wild.
The Go net/http package has so far treated HEAD requests
specially: a Write on our default ResponseWriter returned
ErrBodyNotAllowed, telling handlers that something was wrong.
This was to optimize the fast path for HEAD requests, but:
1) because HEAD requests are incredibly rare, they're not
worth having a fast path for.
2) Letting the http.Handler handle but do nop Writes is still
very fast.
3) this forces ugly error handling into the application.
e.g. https://code.google.com/p/go/source/detail?r=6f596be7a31e
and related.
4) The net/http package nowadays does Content-Type sniffing,
but you don't get that for HEAD.
5) The net/http package nowadays does Content-Length counting
for small (few KB) responses, but not for HEAD.
6) ErrBodyNotAllowed was useless. By the time you received it,
you had probably already done all your heavy computation
and I/O to calculate what to write.
So, this change makes HEAD requests like GET requests.
We now count content-length and sniff content-type for HEAD
requests. If you Write, it doesn't return an error.
If you want a fast-path in your code for HEAD, you have to do
it early and set all the response headers yourself. Just like
before. If you choose not to Write in HEAD requests, be sure
to set Content-Length if you know it. We won't write
"Content-Length: 0" because you might've just chosen to not
write (or you don't know your Content-Length in advance).
Fixes #5454
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/12583043
2013-08-06 18:33:03 -07:00
|
|
|
isHEAD := w.req.Method == "HEAD"
|
2013-03-28 11:35:24 -07:00
|
|
|
|
2013-04-02 16:27:23 -07:00
|
|
|
// header is written out to w.conn.buf below. Depending on the
|
|
|
|
|
// state of the handler, we either own the map or not. If we
|
|
|
|
|
// don't own it, the exclude map is created lazily for
|
|
|
|
|
// WriteSubset to remove headers. The setHeader struct holds
|
|
|
|
|
// headers we need to add.
|
|
|
|
|
header := cw.header
|
|
|
|
|
owned := header != nil
|
|
|
|
|
if !owned {
|
|
|
|
|
header = w.handlerHeader
|
|
|
|
|
}
|
|
|
|
|
var excludeHeader map[string]bool
|
|
|
|
|
delHeader := func(key string) {
|
|
|
|
|
if owned {
|
|
|
|
|
header.Del(key)
|
|
|
|
|
return
|
2013-03-28 11:35:24 -07:00
|
|
|
}
|
2013-04-02 16:27:23 -07:00
|
|
|
if _, ok := header[key]; !ok {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if excludeHeader == nil {
|
|
|
|
|
excludeHeader = make(map[string]bool)
|
|
|
|
|
}
|
|
|
|
|
excludeHeader[key] = true
|
2013-03-28 11:35:24 -07:00
|
|
|
}
|
2013-04-02 16:27:23 -07:00
|
|
|
var setHeader extraHeader
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
// If the handler is done but never sent a Content-Length
|
|
|
|
|
// response header and this is our first (and last) write, set
|
|
|
|
|
// it, even to zero. This helps HTTP/1.0 clients keep their
|
|
|
|
|
// "keep-alive" connections alive.
|
2014-01-16 11:43:52 -08:00
|
|
|
// Exceptions: 304/204/1xx responses never get Content-Length, and if
|
2013-08-15 17:40:05 -07:00
|
|
|
// it was a HEAD request, we don't know the difference between
|
|
|
|
|
// 0 actual bytes and 0 bytes because the handler noticed it
|
|
|
|
|
// was a HEAD request and chose not to write anything. So for
|
|
|
|
|
// HEAD, the handler should either write the Content-Length or
|
|
|
|
|
// write non-zero bytes. If it's actually 0 bytes and the
|
|
|
|
|
// handler never looked at the Request.Method, we just don't
|
|
|
|
|
// send a Content-Length header.
|
2014-01-16 11:43:52 -08:00
|
|
|
if w.handlerDone && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
|
2013-01-11 10:03:43 -08:00
|
|
|
w.contentLength = int64(len(p))
|
2013-05-19 20:15:40 -07:00
|
|
|
setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10)
|
2013-01-11 10:03:43 -08: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 ...
|
2014-02-28 07:40:25 -08:00
|
|
|
if w.req.wantsHttp10KeepAlive() && keepAlivesEnabled {
|
2013-04-02 16:27:23 -07:00
|
|
|
sentLength := header.get("Content-Length") != ""
|
|
|
|
|
if sentLength && header.get("Connection") == "keep-alive" {
|
2013-01-11 10:03:43 -08:00
|
|
|
w.closeAfterReply = false
|
2011-10-14 17:34:07 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-11 10:03:43 -08:00
|
|
|
// Check for a explicit (and valid) Content-Length header.
|
|
|
|
|
hasCL := w.contentLength != -1
|
|
|
|
|
|
net/http: treat HEAD requests like GET requests
A response to a HEAD request is supposed to look the same as a
response to a GET request, just without a body.
HEAD requests are incredibly rare in the wild.
The Go net/http package has so far treated HEAD requests
specially: a Write on our default ResponseWriter returned
ErrBodyNotAllowed, telling handlers that something was wrong.
This was to optimize the fast path for HEAD requests, but:
1) because HEAD requests are incredibly rare, they're not
worth having a fast path for.
2) Letting the http.Handler handle but do nop Writes is still
very fast.
3) this forces ugly error handling into the application.
e.g. https://code.google.com/p/go/source/detail?r=6f596be7a31e
and related.
4) The net/http package nowadays does Content-Type sniffing,
but you don't get that for HEAD.
5) The net/http package nowadays does Content-Length counting
for small (few KB) responses, but not for HEAD.
6) ErrBodyNotAllowed was useless. By the time you received it,
you had probably already done all your heavy computation
and I/O to calculate what to write.
So, this change makes HEAD requests like GET requests.
We now count content-length and sniff content-type for HEAD
requests. If you Write, it doesn't return an error.
If you want a fast-path in your code for HEAD, you have to do
it early and set all the response headers yourself. Just like
before. If you choose not to Write in HEAD requests, be sure
to set Content-Length if you know it. We won't write
"Content-Length: 0" because you might've just chosen to not
write (or you don't know your Content-Length in advance).
Fixes #5454
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/12583043
2013-08-06 18:33:03 -07:00
|
|
|
if w.req.wantsHttp10KeepAlive() && (isHEAD || hasCL) {
|
2013-04-02 16:27:23 -07:00
|
|
|
_, connectionHeaderSet := header["Connection"]
|
2011-10-14 17:34:07 -07:00
|
|
|
if !connectionHeaderSet {
|
2013-04-02 16:27:23 -07:00
|
|
|
setHeader.connection = "keep-alive"
|
2011-10-14 17:34:07 -07:00
|
|
|
}
|
2012-05-22 13:56:40 -04:00
|
|
|
} else if !w.req.ProtoAtLeast(1, 1) || w.req.wantsClose() {
|
2011-10-14 17:34:07 -07:00
|
|
|
w.closeAfterReply = true
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-28 07:40:25 -08:00
|
|
|
if header.get("Connection") == "close" || !keepAlivesEnabled {
|
2011-10-14 17:34:07 -07:00
|
|
|
w.closeAfterReply = true
|
|
|
|
|
}
|
2011-04-14 10:40:23 -07:00
|
|
|
|
|
|
|
|
// Per RFC 2616, we should consume the request body before
|
2011-10-14 17:34:07 -07:00
|
|
|
// 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 {
|
2011-04-14 10:40:23 -07:00
|
|
|
ecr, isExpecter := w.req.Body.(*expectContinueReader)
|
|
|
|
|
if !isExpecter || ecr.resp.wroteContinue {
|
2011-10-14 17:34:07 -07:00
|
|
|
n, _ := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
|
|
|
|
|
if n >= maxPostHandlerReadBytes {
|
|
|
|
|
w.requestTooLarge()
|
2013-04-02 16:27:23 -07:00
|
|
|
delHeader("Connection")
|
|
|
|
|
setHeader.connection = "close"
|
2011-10-14 17:34:07 -07:00
|
|
|
} else {
|
|
|
|
|
w.req.Body.Close()
|
|
|
|
|
}
|
2011-04-14 10:40:23 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-28 11:35:24 -07:00
|
|
|
code := w.status
|
2014-01-16 11:43:52 -08:00
|
|
|
if !bodyAllowedForStatus(code) {
|
2010-06-03 16:09:37 -07:00
|
|
|
// Must not have body.
|
2013-04-02 16:27:23 -07:00
|
|
|
// RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
|
|
|
|
|
for _, k := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
|
|
|
|
|
delHeader(k)
|
2011-03-03 12:22:13 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
2011-07-15 01:01:49 -04:00
|
|
|
// If no content type, apply sniffing algorithm to body.
|
2013-07-31 23:38:32 -07:00
|
|
|
_, haveType := header["Content-Type"]
|
net/http: treat HEAD requests like GET requests
A response to a HEAD request is supposed to look the same as a
response to a GET request, just without a body.
HEAD requests are incredibly rare in the wild.
The Go net/http package has so far treated HEAD requests
specially: a Write on our default ResponseWriter returned
ErrBodyNotAllowed, telling handlers that something was wrong.
This was to optimize the fast path for HEAD requests, but:
1) because HEAD requests are incredibly rare, they're not
worth having a fast path for.
2) Letting the http.Handler handle but do nop Writes is still
very fast.
3) this forces ugly error handling into the application.
e.g. https://code.google.com/p/go/source/detail?r=6f596be7a31e
and related.
4) The net/http package nowadays does Content-Type sniffing,
but you don't get that for HEAD.
5) The net/http package nowadays does Content-Length counting
for small (few KB) responses, but not for HEAD.
6) ErrBodyNotAllowed was useless. By the time you received it,
you had probably already done all your heavy computation
and I/O to calculate what to write.
So, this change makes HEAD requests like GET requests.
We now count content-length and sniff content-type for HEAD
requests. If you Write, it doesn't return an error.
If you want a fast-path in your code for HEAD, you have to do
it early and set all the response headers yourself. Just like
before. If you choose not to Write in HEAD requests, be sure
to set Content-Length if you know it. We won't write
"Content-Length: 0" because you might've just chosen to not
write (or you don't know your Content-Length in advance).
Fixes #5454
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/12583043
2013-08-06 18:33:03 -07:00
|
|
|
if !haveType {
|
2013-04-02 16:27:23 -07:00
|
|
|
setHeader.contentType = DetectContentType(p)
|
2011-03-03 12:22:13 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-02 16:27:23 -07:00
|
|
|
if _, ok := header["Date"]; !ok {
|
2013-05-19 20:15:40 -07:00
|
|
|
setHeader.date = appendTime(cw.res.dateBuf[:0], time.Now())
|
2011-03-03 12:22:13 -08:00
|
|
|
}
|
|
|
|
|
|
2013-04-02 16:27:23 -07:00
|
|
|
te := header.get("Transfer-Encoding")
|
2011-03-09 09:41:01 -08:00
|
|
|
hasTE := te != ""
|
2011-03-03 12:22:13 -08:00
|
|
|
if hasCL && hasTE && te != "identity" {
|
|
|
|
|
// TODO: return an error if WriteHeader gets a return parameter
|
|
|
|
|
// For now just ignore the Content-Length.
|
2014-02-28 12:12:51 -08:00
|
|
|
w.conn.server.logf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
|
2013-01-11 10:03:43 -08:00
|
|
|
te, w.contentLength)
|
2013-04-02 16:27:23 -07:00
|
|
|
delHeader("Content-Length")
|
2011-03-03 12:22:13 -08:00
|
|
|
hasCL = false
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-16 11:43:52 -08:00
|
|
|
if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) {
|
2011-03-03 12:22:13 -08:00
|
|
|
// do nothing
|
2012-11-29 18:00:51 -08:00
|
|
|
} else if code == StatusNoContent {
|
2013-04-02 16:27:23 -07:00
|
|
|
delHeader("Transfer-Encoding")
|
2011-03-03 12:22:13 -08:00
|
|
|
} else if hasCL {
|
2013-04-02 16:27:23 -07:00
|
|
|
delHeader("Transfer-Encoding")
|
2011-03-03 12:22:13 -08:00
|
|
|
} 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.
|
2013-01-11 10:03:43 -08:00
|
|
|
cw.chunking = true
|
2013-04-02 16:27:23 -07:00
|
|
|
setHeader.transferEncoding = "chunked"
|
2011-03-03 12:22:13 -08:00
|
|
|
} 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
|
2013-04-02 16:27:23 -07:00
|
|
|
delHeader("Transfer-Encoding") // in case already set
|
2011-03-03 12:22:13 -08:00
|
|
|
}
|
|
|
|
|
|
2011-01-19 10:05:48 -05:00
|
|
|
// Cannot use Content-Length with non-identity Transfer-Encoding.
|
2013-01-11 10:03:43 -08:00
|
|
|
if cw.chunking {
|
2013-04-02 16:27:23 -07:00
|
|
|
delHeader("Content-Length")
|
2011-01-19 10:05:48 -05:00
|
|
|
}
|
2010-09-29 14:30:12 +10:00
|
|
|
if !w.req.ProtoAtLeast(1, 0) {
|
2009-11-09 12:07:39 -08:00
|
|
|
return
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2012-05-23 11:19:38 -07:00
|
|
|
|
2014-02-28 07:40:25 -08:00
|
|
|
if w.closeAfterReply && (!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) {
|
2013-04-02 16:27:23 -07:00
|
|
|
delHeader("Connection")
|
2013-08-06 18:37:34 -07:00
|
|
|
if w.req.ProtoAtLeast(1, 1) {
|
|
|
|
|
setHeader.connection = "close"
|
|
|
|
|
}
|
2012-05-23 11:19:38 -07:00
|
|
|
}
|
|
|
|
|
|
2013-05-20 19:26:26 -07:00
|
|
|
w.conn.buf.WriteString(statusLine(w.req, code))
|
2013-04-02 16:27:23 -07:00
|
|
|
cw.header.WriteSubset(w.conn.buf, excludeHeader)
|
2013-05-19 20:15:40 -07:00
|
|
|
setHeader.Write(w.conn.buf.Writer)
|
2013-03-28 13:07:14 -07:00
|
|
|
w.conn.buf.Write(crlf)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// statusLines is a cache of Status-Line strings, keyed by code (for
|
|
|
|
|
// HTTP/1.1) or negative code (for HTTP/1.0). This is faster than a
|
|
|
|
|
// map keyed by struct of two fields. This map's max size is bounded
|
|
|
|
|
// by 2*len(statusText), two protocol types for each known official
|
|
|
|
|
// status code in the statusText map.
|
|
|
|
|
var (
|
|
|
|
|
statusMu sync.RWMutex
|
|
|
|
|
statusLines = make(map[int]string)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// statusLine returns a response Status-Line (RFC 2616 Section 6.1)
|
|
|
|
|
// for the given request and response status code.
|
|
|
|
|
func statusLine(req *Request, code int) string {
|
|
|
|
|
// Fast path:
|
|
|
|
|
key := code
|
|
|
|
|
proto11 := req.ProtoAtLeast(1, 1)
|
|
|
|
|
if !proto11 {
|
|
|
|
|
key = -key
|
|
|
|
|
}
|
|
|
|
|
statusMu.RLock()
|
|
|
|
|
line, ok := statusLines[key]
|
|
|
|
|
statusMu.RUnlock()
|
|
|
|
|
if ok {
|
|
|
|
|
return line
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Slow path:
|
2009-12-15 15:35:38 -08:00
|
|
|
proto := "HTTP/1.0"
|
2013-03-28 13:07:14 -07:00
|
|
|
if proto11 {
|
2009-11-09 12:07:39 -08:00
|
|
|
proto = "HTTP/1.1"
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
codestring := strconv.Itoa(code)
|
|
|
|
|
text, ok := statusText[code]
|
2009-02-02 18:01:32 -08:00
|
|
|
if !ok {
|
2009-11-09 12:07:39 -08:00
|
|
|
text = "status code " + codestring
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2013-03-28 13:07:14 -07:00
|
|
|
line = proto + " " + codestring + " " + text + "\r\n"
|
|
|
|
|
if ok {
|
|
|
|
|
statusMu.Lock()
|
|
|
|
|
defer statusMu.Unlock()
|
|
|
|
|
statusLines[key] = line
|
|
|
|
|
}
|
|
|
|
|
return line
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2011-06-09 18:10:21 -07:00
|
|
|
// 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("")
|
|
|
|
|
}
|
2014-01-16 11:43:52 -08:00
|
|
|
return bodyAllowedForStatus(w.status)
|
2011-06-09 18:10:21 -07:00
|
|
|
}
|
|
|
|
|
|
2013-01-11 10:03:43 -08:00
|
|
|
// The Life Of A Write is like this:
|
|
|
|
|
//
|
|
|
|
|
// Handler starts. No header has been sent. The handler can either
|
|
|
|
|
// write a header, or just start writing. Writing before sending a header
|
2013-03-20 16:32:37 -07:00
|
|
|
// sends an implicitly empty 200 OK header.
|
2013-01-11 10:03:43 -08:00
|
|
|
//
|
|
|
|
|
// If the handler didn't declare a Content-Length up front, we either
|
|
|
|
|
// go into chunking mode or, if the handler finishes running before
|
|
|
|
|
// the chunking buffer size, we compute a Content-Length and send that
|
|
|
|
|
// in the header instead.
|
|
|
|
|
//
|
|
|
|
|
// Likewise, if the handler didn't set a Content-Type, we sniff that
|
|
|
|
|
// from the initial chunk of output.
|
|
|
|
|
//
|
|
|
|
|
// The Writers are wired together like:
|
|
|
|
|
//
|
|
|
|
|
// 1. *response (the ResponseWriter) ->
|
|
|
|
|
// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes
|
|
|
|
|
// 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type)
|
|
|
|
|
// and which writes the chunk headers, if needed.
|
|
|
|
|
// 4. conn.buf, a bufio.Writer of default (4kB) bytes
|
|
|
|
|
// 5. the rwc, the net.Conn.
|
|
|
|
|
//
|
|
|
|
|
// TODO(bradfitz): short-circuit some of the buffering when the
|
|
|
|
|
// initial header contains both a Content-Type and Content-Length.
|
|
|
|
|
// Also short-circuit in (1) when the header's been sent and not in
|
|
|
|
|
// chunking mode, writing directly to (4) instead, if (2) has no
|
|
|
|
|
// buffered data. More generally, we could short-circuit from (1) to
|
|
|
|
|
// (3) even in chunking mode if the write size from (1) is over some
|
|
|
|
|
// threshold and nothing is in (2). The answer might be mostly making
|
|
|
|
|
// bufferBeforeChunkingSize smaller and having bufio's fast-paths deal
|
|
|
|
|
// with this instead.
|
2011-11-01 22:04:37 -04:00
|
|
|
func (w *response) Write(data []byte) (n int, err error) {
|
2013-08-19 22:56:54 -07:00
|
|
|
return w.write(len(data), data, "")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *response) WriteString(data string) (n int, err error) {
|
|
|
|
|
return w.write(len(data), nil, data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// either dataB or dataS is non-zero.
|
|
|
|
|
func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
|
2012-12-05 19:25:43 -08:00
|
|
|
if w.conn.hijacked() {
|
2014-02-28 12:12:51 -08:00
|
|
|
w.conn.server.logf("http: response.Write on hijacked connection")
|
2009-12-15 15:35:38 -08:00
|
|
|
return 0, ErrHijacked
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2010-09-29 14:30:12 +10:00
|
|
|
if !w.wroteHeader {
|
|
|
|
|
w.WriteHeader(StatusOK)
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2013-08-19 22:56:54 -07:00
|
|
|
if lenData == 0 {
|
2009-11-09 12:07:39 -08:00
|
|
|
return 0, nil
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2011-06-09 18:10:21 -07:00
|
|
|
if !w.bodyAllowed() {
|
2010-06-03 16:09:37 -07:00
|
|
|
return 0, ErrBodyNotAllowed
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-19 22:56:54 -07:00
|
|
|
w.written += int64(lenData) // ignoring errors, for errorKludge
|
2011-03-03 12:22:13 -08:00
|
|
|
if w.contentLength != -1 && w.written > w.contentLength {
|
|
|
|
|
return 0, ErrContentLength
|
|
|
|
|
}
|
2013-08-19 22:56:54 -07:00
|
|
|
if dataB != nil {
|
|
|
|
|
return w.w.Write(dataB)
|
|
|
|
|
} else {
|
|
|
|
|
return w.w.WriteString(dataS)
|
|
|
|
|
}
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2010-09-29 14:30:12 +10:00
|
|
|
func (w *response) finishRequest() {
|
2013-01-11 10:03:43 -08:00
|
|
|
w.handlerDone = true
|
|
|
|
|
|
2010-09-29 14:30:12 +10:00
|
|
|
if !w.wroteHeader {
|
|
|
|
|
w.WriteHeader(StatusOK)
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2013-01-11 10:03:43 -08:00
|
|
|
|
|
|
|
|
w.w.Flush()
|
2013-08-10 19:22:44 -07:00
|
|
|
putBufioWriter(w.w)
|
2013-01-11 10:03:43 -08:00
|
|
|
w.cw.close()
|
2010-09-29 14:30:12 +10:00
|
|
|
w.conn.buf.Flush()
|
2013-01-11 10:03:43 -08:00
|
|
|
|
2014-01-14 09:46:40 -08:00
|
|
|
// Close the body (regardless of w.closeAfterReply) so we can
|
|
|
|
|
// re-use its bufio.Reader later safely.
|
|
|
|
|
w.req.Body.Close()
|
|
|
|
|
|
2011-04-28 15:21:54 +10:00
|
|
|
if w.req.MultipartForm != nil {
|
|
|
|
|
w.req.MultipartForm.RemoveAll()
|
|
|
|
|
}
|
2011-03-03 12:22:13 -08:00
|
|
|
|
net/http: treat HEAD requests like GET requests
A response to a HEAD request is supposed to look the same as a
response to a GET request, just without a body.
HEAD requests are incredibly rare in the wild.
The Go net/http package has so far treated HEAD requests
specially: a Write on our default ResponseWriter returned
ErrBodyNotAllowed, telling handlers that something was wrong.
This was to optimize the fast path for HEAD requests, but:
1) because HEAD requests are incredibly rare, they're not
worth having a fast path for.
2) Letting the http.Handler handle but do nop Writes is still
very fast.
3) this forces ugly error handling into the application.
e.g. https://code.google.com/p/go/source/detail?r=6f596be7a31e
and related.
4) The net/http package nowadays does Content-Type sniffing,
but you don't get that for HEAD.
5) The net/http package nowadays does Content-Length counting
for small (few KB) responses, but not for HEAD.
6) ErrBodyNotAllowed was useless. By the time you received it,
you had probably already done all your heavy computation
and I/O to calculate what to write.
So, this change makes HEAD requests like GET requests.
We now count content-length and sniff content-type for HEAD
requests. If you Write, it doesn't return an error.
If you want a fast-path in your code for HEAD, you have to do
it early and set all the response headers yourself. Just like
before. If you choose not to Write in HEAD requests, be sure
to set Content-Length if you know it. We won't write
"Content-Length: 0" because you might've just chosen to not
write (or you don't know your Content-Length in advance).
Fixes #5454
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/12583043
2013-08-06 18:33:03 -07:00
|
|
|
if w.req.Method != "HEAD" && w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written {
|
2011-03-03 12:22:13 -08:00
|
|
|
// Did not write enough. Avoid getting out of sync.
|
|
|
|
|
w.closeAfterReply = true
|
|
|
|
|
}
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2010-09-29 14:30:12 +10:00
|
|
|
func (w *response) Flush() {
|
|
|
|
|
if !w.wroteHeader {
|
|
|
|
|
w.WriteHeader(StatusOK)
|
2009-11-13 18:06:47 -08:00
|
|
|
}
|
2013-01-11 10:03:43 -08:00
|
|
|
w.w.Flush()
|
|
|
|
|
w.cw.flush()
|
2009-11-13 18:06:47 -08:00
|
|
|
}
|
|
|
|
|
|
2012-05-29 12:40:13 -07:00
|
|
|
func (c *conn) finalFlush() {
|
2009-02-03 14:16:22 -08:00
|
|
|
if c.buf != nil {
|
2009-12-15 15:35:38 -08:00
|
|
|
c.buf.Flush()
|
2013-03-21 20:02:01 -07:00
|
|
|
|
|
|
|
|
// Steal the bufio.Reader (~4KB worth of memory) and its associated
|
|
|
|
|
// reader for a future connection.
|
2013-08-10 19:22:44 -07:00
|
|
|
putBufioReader(c.buf.Reader)
|
2013-03-21 20:02:01 -07:00
|
|
|
|
|
|
|
|
// Steal the bufio.Writer (~4KB worth of memory) and its associated
|
|
|
|
|
// writer for a future connection.
|
2013-08-10 19:22:44 -07:00
|
|
|
putBufioWriter(c.buf.Writer)
|
2013-03-21 20:02:01 -07:00
|
|
|
|
2009-12-15 15:35:38 -08:00
|
|
|
c.buf = nil
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2012-05-29 12:40:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Close the connection.
|
|
|
|
|
func (c *conn) close() {
|
|
|
|
|
c.finalFlush()
|
2009-03-11 12:51:10 -07:00
|
|
|
if c.rwc != nil {
|
2009-12-15 15:35:38 -08:00
|
|
|
c.rwc.Close()
|
|
|
|
|
c.rwc = nil
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-12 15:20:18 -08:00
|
|
|
// rstAvoidanceDelay is the amount of time we sleep after closing the
|
|
|
|
|
// write side of a TCP connection before closing the entire socket.
|
|
|
|
|
// By sleeping, we increase the chances that the client sees our FIN
|
|
|
|
|
// and processes its final data before they process the subsequent RST
|
|
|
|
|
// from closing a connection with known unread data.
|
|
|
|
|
// This RST seems to occur mostly on BSD systems. (And Windows?)
|
|
|
|
|
// This timeout is somewhat arbitrary (~latency around the planet).
|
|
|
|
|
const rstAvoidanceDelay = 500 * time.Millisecond
|
|
|
|
|
|
|
|
|
|
// closeWrite flushes any outstanding data and sends a FIN packet (if
|
|
|
|
|
// client is connected via TCP), signalling that we're done. We then
|
|
|
|
|
// pause for a bit, hoping the client processes it before `any
|
|
|
|
|
// subsequent RST.
|
|
|
|
|
//
|
|
|
|
|
// See http://golang.org/issue/3595
|
|
|
|
|
func (c *conn) closeWriteAndWait() {
|
2012-05-29 12:40:13 -07:00
|
|
|
c.finalFlush()
|
|
|
|
|
if tcp, ok := c.rwc.(*net.TCPConn); ok {
|
|
|
|
|
tcp.CloseWrite()
|
|
|
|
|
}
|
2012-11-12 15:20:18 -08:00
|
|
|
time.Sleep(rstAvoidanceDelay)
|
2012-05-29 12:40:13 -07:00
|
|
|
}
|
|
|
|
|
|
2013-07-23 11:59:49 +10:00
|
|
|
// validNPN reports whether the proto is not a blacklisted Next
|
2013-02-04 13:55:38 -08:00
|
|
|
// Protocol Negotiation protocol. Empty and built-in protocol types
|
|
|
|
|
// are blacklisted and can't be overridden with alternate
|
|
|
|
|
// implementations.
|
|
|
|
|
func validNPN(proto string) bool {
|
|
|
|
|
switch proto {
|
|
|
|
|
case "", "http/1.1", "http/1.0":
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-27 18:29:00 -08:00
|
|
|
func (c *conn) setState(nc net.Conn, state ConnState) {
|
|
|
|
|
if hook := c.server.ConnState; hook != nil {
|
|
|
|
|
hook(nc, state)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-02 18:01:32 -08:00
|
|
|
// Serve a new connection.
|
2010-09-29 14:30:12 +10:00
|
|
|
func (c *conn) serve() {
|
2014-02-27 18:29:00 -08:00
|
|
|
origConn := c.rwc // copy it before it's set nil on Close or Hijack
|
2011-06-02 12:00:26 -07:00
|
|
|
defer func() {
|
2012-12-21 15:14:38 +11:00
|
|
|
if err := recover(); err != nil {
|
2014-02-14 10:15:38 +11:00
|
|
|
const size = 64 << 10
|
2012-12-21 15:14:38 +11:00
|
|
|
buf := make([]byte, size)
|
|
|
|
|
buf = buf[:runtime.Stack(buf, false)]
|
2014-02-28 12:12:51 -08:00
|
|
|
c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
|
2011-06-02 12:00:26 -07:00
|
|
|
}
|
2012-12-21 15:14:38 +11:00
|
|
|
if !c.hijacked() {
|
|
|
|
|
c.close()
|
2014-02-27 18:29:00 -08:00
|
|
|
c.setState(origConn, StateClosed)
|
2012-01-19 14:19:59 -08:00
|
|
|
}
|
2011-06-02 12:00:26 -07:00
|
|
|
}()
|
|
|
|
|
|
2011-09-19 19:56:51 -07:00
|
|
|
if tlsConn, ok := c.rwc.(*tls.Conn); ok {
|
2013-02-04 13:52:45 -08:00
|
|
|
if d := c.server.ReadTimeout; d != 0 {
|
|
|
|
|
c.rwc.SetReadDeadline(time.Now().Add(d))
|
|
|
|
|
}
|
|
|
|
|
if d := c.server.WriteTimeout; d != 0 {
|
|
|
|
|
c.rwc.SetWriteDeadline(time.Now().Add(d))
|
|
|
|
|
}
|
2011-10-18 12:59:32 -04:00
|
|
|
if err := tlsConn.Handshake(); err != nil {
|
2014-02-28 12:12:51 -08:00
|
|
|
c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
|
2011-10-18 12:59:32 -04:00
|
|
|
return
|
|
|
|
|
}
|
2011-09-19 19:56:51 -07:00
|
|
|
c.tlsState = new(tls.ConnectionState)
|
|
|
|
|
*c.tlsState = tlsConn.ConnectionState()
|
2013-02-04 13:55:38 -08:00
|
|
|
if proto := c.tlsState.NegotiatedProtocol; validNPN(proto) {
|
|
|
|
|
if fn := c.server.TLSNextProto[proto]; fn != nil {
|
|
|
|
|
h := initNPNRequest{tlsConn, serverHandler{c.server}}
|
|
|
|
|
fn(c.server, tlsConn, h)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
2011-09-19 19:56:51 -07:00
|
|
|
}
|
|
|
|
|
|
2008-09-24 15:26:55 -07:00
|
|
|
for {
|
2010-09-29 14:30:12 +10:00
|
|
|
w, err := c.readRequest()
|
2014-03-03 18:58:28 -08:00
|
|
|
if c.lr.N != c.server.initialLimitedReaderSize() {
|
|
|
|
|
// If we read any bytes off the wire, we're active.
|
|
|
|
|
c.setState(c.rwc, StateActive)
|
|
|
|
|
}
|
2008-09-24 15:26:55 -07:00
|
|
|
if err != nil {
|
2011-08-09 10:55:14 -07:00
|
|
|
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.
|
2012-11-12 15:20:18 -08:00
|
|
|
io.WriteString(c.rwc, "HTTP/1.1 413 Request Entity Too Large\r\n\r\n")
|
|
|
|
|
c.closeWriteAndWait()
|
|
|
|
|
break
|
2012-03-12 10:42:25 -07:00
|
|
|
} else if err == io.EOF {
|
2011-09-28 09:27:11 -07:00
|
|
|
break // Don't reply
|
2011-08-24 13:10:22 +04:00
|
|
|
} else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
|
|
|
|
|
break // Don't reply
|
2011-08-09 10:55:14 -07:00
|
|
|
}
|
2012-11-12 15:20:18 -08:00
|
|
|
io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\n\r\n")
|
2009-11-09 12:07:39 -08:00
|
|
|
break
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
2011-04-13 14:09:04 -07:00
|
|
|
|
|
|
|
|
// Expect 100 Continue support
|
|
|
|
|
req := w.req
|
|
|
|
|
if req.expectsContinue() {
|
2014-04-10 22:25:31 -07:00
|
|
|
if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
|
2011-04-13 14:09:04 -07:00
|
|
|
// Wrap the Body reader with one that replies on the connection
|
|
|
|
|
req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
|
|
|
|
|
}
|
|
|
|
|
req.Header.Del("Expect")
|
2012-05-28 11:07:24 -07:00
|
|
|
} else if req.Header.get("Expect") != "" {
|
2012-12-05 19:25:43 -08:00
|
|
|
w.sendExpectationFailed()
|
2011-04-13 14:09:04 -07:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-27 21:55:04 -04:00
|
|
|
// HTTP cannot have multiple simultaneous active requests.[*]
|
2009-02-02 18:01:32 -08:00
|
|
|
// Until the server replies to this request, it can't read another,
|
2009-04-07 00:40:07 -07:00
|
|
|
// so we might as well run the handler in this goroutine.
|
2010-09-27 21:55:04 -04:00
|
|
|
// [*] Not strictly true: HTTP pipelining. We could let them all process
|
|
|
|
|
// in parallel even if their responses need to be serialized.
|
2013-02-04 13:55:38 -08:00
|
|
|
serverHandler{c.server}.ServeHTTP(w, w.req)
|
2012-12-05 19:25:43 -08:00
|
|
|
if c.hijacked() {
|
2009-11-09 12:07:39 -08:00
|
|
|
return
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2010-09-29 14:30:12 +10:00
|
|
|
w.finishRequest()
|
|
|
|
|
if w.closeAfterReply {
|
2012-05-29 12:40:13 -07:00
|
|
|
if w.requestBodyLimitHit {
|
2012-11-12 15:20:18 -08:00
|
|
|
c.closeWriteAndWait()
|
2012-05-29 12:40:13 -07:00
|
|
|
}
|
2009-11-09 12:07:39 -08:00
|
|
|
break
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
2014-02-27 18:29:00 -08:00
|
|
|
c.setState(c.rwc, StateIdle)
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
2009-02-03 14:16:22 -08:00
|
|
|
}
|
|
|
|
|
|
2012-12-05 19:25:43 -08:00
|
|
|
func (w *response) sendExpectationFailed() {
|
|
|
|
|
// 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()
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-07 12:04:04 -08:00
|
|
|
// Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
|
|
|
|
|
// and a Hijacker.
|
2011-11-01 22:04:37 -04:00
|
|
|
func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
|
2013-01-11 10:03:43 -08:00
|
|
|
if w.wroteHeader {
|
|
|
|
|
w.cw.flush()
|
|
|
|
|
}
|
2013-12-26 11:52:14 -08:00
|
|
|
// Release the bufioWriter that writes to the chunk writer, it is not
|
|
|
|
|
// used after a connection has been hijacked.
|
|
|
|
|
rwc, buf, err = w.conn.hijack()
|
|
|
|
|
if err == nil {
|
|
|
|
|
putBufioWriter(w.w)
|
|
|
|
|
w.w = nil
|
|
|
|
|
}
|
|
|
|
|
return rwc, buf, err
|
2012-12-05 19:25:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *response) CloseNotify() <-chan bool {
|
|
|
|
|
return w.conn.closeNotify()
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
|
|
|
|
|
2009-03-11 12:51:10 -07: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-29 14:30:12 +10:00
|
|
|
type HandlerFunc func(ResponseWriter, *Request)
|
2009-03-11 12:51:10 -07:00
|
|
|
|
2011-06-18 21:53:18 +10:00
|
|
|
// ServeHTTP calls f(w, r).
|
2010-09-29 14:30:12 +10:00
|
|
|
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
|
|
|
|
|
f(w, r)
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper handlers
|
|
|
|
|
|
2010-03-20 10:22:09 +11:00
|
|
|
// Error replies to the request with the specified error message and HTTP code.
|
2013-08-01 12:05:05 -07:00
|
|
|
// The error message should be plain text.
|
2010-09-29 14:30:12 +10:00
|
|
|
func Error(w ResponseWriter, error string, code int) {
|
2011-03-09 09:41:01 -08:00
|
|
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
2010-09-29 14:30:12 +10:00
|
|
|
w.WriteHeader(code)
|
|
|
|
|
fmt.Fprintln(w, error)
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2010-03-20 10:22:09 +11:00
|
|
|
// NotFound replies to the request with an HTTP 404 not found error.
|
2010-09-29 14:30:12 +10:00
|
|
|
func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }
|
2010-03-20 10:22:09 +11:00
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// NotFoundHandler returns a simple request handler
|
|
|
|
|
// that replies to each request with a ``404 page not found'' reply.
|
2009-12-15 15:35:38 -08:00
|
|
|
func NotFoundHandler() Handler { return HandlerFunc(NotFound) }
|
2009-02-02 18:01:32 -08:00
|
|
|
|
2011-06-27 11:03:43 -07:00
|
|
|
// 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 {
|
2013-03-18 13:44:20 -07:00
|
|
|
if prefix == "" {
|
|
|
|
|
return h
|
|
|
|
|
}
|
2011-06-27 11:03:43 -07:00
|
|
|
return HandlerFunc(func(w ResponseWriter, r *Request) {
|
2013-03-18 13:44:20 -07:00
|
|
|
if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
|
|
|
|
|
r.URL.Path = p
|
|
|
|
|
h.ServeHTTP(w, r)
|
|
|
|
|
} else {
|
2011-06-27 11:03:43 -07:00
|
|
|
NotFound(w, r)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-14 20:31:31 -07:00
|
|
|
// Redirect replies to the request with a redirect to url,
|
|
|
|
|
// which may be a path relative to the request path.
|
2011-08-17 13:36:02 +10:00
|
|
|
func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
|
|
|
|
|
if u, err := url.Parse(urlStr); err == nil {
|
2011-01-11 17:15:28 -05:00
|
|
|
// 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 18:40:55 -07:00
|
|
|
}
|
2011-01-11 17:15:28 -05:00
|
|
|
if u.Scheme == "" {
|
|
|
|
|
// no leading http://server
|
2011-08-17 13:36:02 +10:00
|
|
|
if urlStr == "" || urlStr[0] != '/' {
|
2011-01-11 17:15:28 -05:00
|
|
|
// make relative path absolute
|
|
|
|
|
olddir, _ := path.Split(oldpath)
|
2011-08-17 13:36:02 +10:00
|
|
|
urlStr = olddir + urlStr
|
2011-01-11 17:15:28 -05:00
|
|
|
}
|
2009-04-15 18:40:55 -07:00
|
|
|
|
2011-05-11 04:30:05 -07:00
|
|
|
var query string
|
2013-08-05 16:27:24 -07:00
|
|
|
if i := strings.Index(urlStr, "?"); i != -1 {
|
2011-08-17 13:36:02 +10:00
|
|
|
urlStr, query = urlStr[:i], urlStr[i:]
|
2011-05-11 04:30:05 -07:00
|
|
|
}
|
|
|
|
|
|
2011-01-11 17:15:28 -05:00
|
|
|
// clean up but preserve trailing slash
|
2013-04-20 17:20:14 -07:00
|
|
|
trailing := strings.HasSuffix(urlStr, "/")
|
2011-08-17 13:36:02 +10:00
|
|
|
urlStr = path.Clean(urlStr)
|
2013-04-20 17:20:14 -07:00
|
|
|
if trailing && !strings.HasSuffix(urlStr, "/") {
|
2011-08-17 13:36:02 +10:00
|
|
|
urlStr += "/"
|
2011-01-11 17:15:28 -05:00
|
|
|
}
|
2011-08-17 13:36:02 +10:00
|
|
|
urlStr += query
|
2009-04-15 18:40:55 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-17 13:36:02 +10:00
|
|
|
w.Header().Set("Location", urlStr)
|
2010-09-29 14:30:12 +10:00
|
|
|
w.WriteHeader(code)
|
2011-01-11 17:15:28 -05: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 14:34:31 -05:00
|
|
|
// Shouldn't send the response for POST or HEAD; that leaves GET.
|
|
|
|
|
if r.Method == "GET" {
|
2011-08-17 13:36:02 +10:00
|
|
|
note := "<a href=\"" + htmlEscape(urlStr) + "\">" + statusText[code] + "</a>.\n"
|
2011-01-13 14:34:31 -05:00
|
|
|
fmt.Fprintln(w, note)
|
2011-01-11 17:15:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-03 15:19:04 -07:00
|
|
|
var htmlReplacer = strings.NewReplacer(
|
|
|
|
|
"&", "&",
|
|
|
|
|
"<", "<",
|
|
|
|
|
">", ">",
|
2012-04-12 09:35:43 +10:00
|
|
|
// """ is shorter than """.
|
|
|
|
|
`"`, """,
|
|
|
|
|
// "'" is shorter than "'" and apos was not in HTML until HTML5.
|
|
|
|
|
"'", "'",
|
2011-10-03 15:19:04 -07:00
|
|
|
)
|
|
|
|
|
|
2011-01-11 17:15:28 -05:00
|
|
|
func htmlEscape(s string) string {
|
2011-10-03 15:19:04 -07:00
|
|
|
return htmlReplacer.Replace(s)
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-14 20:31:31 -07:00
|
|
|
// Redirect to a fixed URL
|
2009-05-12 15:41:19 -07:00
|
|
|
type redirectHandler struct {
|
2009-12-15 15:35:38 -08:00
|
|
|
url string
|
|
|
|
|
code int
|
2009-05-12 15:41:19 -07:00
|
|
|
}
|
2009-10-06 19:41:51 -07:00
|
|
|
|
2010-09-29 14:30:12 +10:00
|
|
|
func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
|
|
|
|
|
Redirect(w, r, rh.url, rh.code)
|
2009-04-14 20:31:31 -07:00
|
|
|
}
|
|
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// RedirectHandler returns a request handler that redirects
|
2009-05-12 15:41:19 -07:00
|
|
|
// each request it receives to the given url using the given
|
|
|
|
|
// status code.
|
|
|
|
|
func RedirectHandler(url string, code int) Handler {
|
2009-11-09 12:07:39 -08:00
|
|
|
return &redirectHandler{url, code}
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2009-03-11 12:51:10 -07: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.
|
|
|
|
|
//
|
2012-06-28 15:18:35 -07:00
|
|
|
// Patterns name fixed, rooted paths, like "/favicon.ico",
|
2011-02-01 13:58:59 -05:00
|
|
|
// or rooted subtrees, like "/images/" (note the trailing slash).
|
2009-03-11 12:51:10 -07:00
|
|
|
// 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
|
2012-06-28 15:18:35 -07:00
|
|
|
// former will receive requests for any other paths in the
|
2009-03-11 12:51:10 -07:00
|
|
|
// "/images/" subtree.
|
|
|
|
|
//
|
2013-09-12 11:20:16 +01:00
|
|
|
// Note that since a pattern ending in a slash names a rooted subtree,
|
|
|
|
|
// the pattern "/" matches all paths not matched by other registered
|
|
|
|
|
// patterns, not just the URL with Path == "/".
|
|
|
|
|
//
|
2011-02-01 13:58:59 -05:00
|
|
|
// 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/".
|
2009-04-07 00:40:07 -07: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 18:01:32 -08:00
|
|
|
type ServeMux struct {
|
2012-05-28 10:58:49 -07:00
|
|
|
mu sync.RWMutex
|
|
|
|
|
m map[string]muxEntry
|
|
|
|
|
hosts bool // whether any patterns contain hostnames
|
2012-02-08 13:50:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type muxEntry struct {
|
|
|
|
|
explicit bool
|
|
|
|
|
h Handler
|
2012-08-31 12:16:31 -04:00
|
|
|
pattern string
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// NewServeMux allocates and returns a new ServeMux.
|
2012-02-08 13:50:00 -05:00
|
|
|
func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} }
|
2009-02-02 18:01:32 -08:00
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// DefaultServeMux is the default ServeMux used by Serve.
|
2009-10-06 19:41:51 -07:00
|
|
|
var DefaultServeMux = NewServeMux()
|
2009-02-02 18:01:32 -08:00
|
|
|
|
|
|
|
|
// Does path match pattern?
|
|
|
|
|
func pathMatch(pattern, path string) bool {
|
|
|
|
|
if len(pattern) == 0 {
|
|
|
|
|
// should not happen
|
2009-11-09 12:07:39 -08:00
|
|
|
return false
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
n := len(pattern)
|
2009-02-02 18:01:32 -08:00
|
|
|
if pattern[n-1] != '/' {
|
2009-11-09 12:07:39 -08:00
|
|
|
return pattern == path
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
return len(path) >= n && path[0:n] == pattern
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
|
2009-04-07 00:40:07 -07:00
|
|
|
// Return the canonical path for p, eliminating . and .. elements.
|
|
|
|
|
func cleanPath(p string) string {
|
|
|
|
|
if p == "" {
|
2009-11-09 12:07:39 -08:00
|
|
|
return "/"
|
2009-04-07 00:40:07 -07:00
|
|
|
}
|
|
|
|
|
if p[0] != '/' {
|
2009-11-09 21:23:52 -08:00
|
|
|
p = "/" + p
|
2009-04-07 00:40:07 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
np := path.Clean(p)
|
2009-04-07 00:40:07 -07: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 12:07:39 -08:00
|
|
|
np += "/"
|
2009-04-07 00:40:07 -07:00
|
|
|
}
|
2009-12-15 15:35:38 -08:00
|
|
|
return np
|
2009-04-07 00:40:07 -07:00
|
|
|
}
|
|
|
|
|
|
2011-02-01 13:58:59 -05:00
|
|
|
// Find a handler on a handler map given a path string
|
|
|
|
|
// Most-specific (longest) pattern wins
|
2012-08-31 12:16:31 -04:00
|
|
|
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
|
2009-12-15 15:35:38 -08:00
|
|
|
var n = 0
|
2009-02-02 18:01:32 -08:00
|
|
|
for k, v := range mux.m {
|
2011-02-01 13:58:59 -05:00
|
|
|
if !pathMatch(k, path) {
|
2009-11-09 12:07:39 -08:00
|
|
|
continue
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
if h == nil || len(k) > n {
|
2009-12-15 15:35:38 -08:00
|
|
|
n = len(k)
|
2012-02-08 13:50:00 -05:00
|
|
|
h = v.h
|
2012-08-31 12:16:31 -04:00
|
|
|
pattern = v.pattern
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
}
|
2012-08-31 12:16:31 -04:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handler returns the handler to use for the given request,
|
|
|
|
|
// consulting r.Method, r.Host, and r.URL.Path. It always returns
|
|
|
|
|
// a non-nil handler. If the path is not in its canonical form, the
|
|
|
|
|
// handler will be an internally-generated handler that redirects
|
|
|
|
|
// to the canonical path.
|
|
|
|
|
//
|
|
|
|
|
// Handler also returns the registered pattern that matches the
|
|
|
|
|
// request or, in the case of internally-generated redirects,
|
|
|
|
|
// the pattern that will match after following the redirect.
|
|
|
|
|
//
|
|
|
|
|
// If there is no registered handler that applies to the request,
|
|
|
|
|
// Handler returns a ``page not found'' handler and an empty pattern.
|
|
|
|
|
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
|
|
|
|
|
if r.Method != "CONNECT" {
|
|
|
|
|
if p := cleanPath(r.URL.Path); p != r.URL.Path {
|
|
|
|
|
_, pattern = mux.handler(r.Host, p)
|
2013-08-29 13:55:12 -07:00
|
|
|
url := *r.URL
|
|
|
|
|
url.Path = p
|
|
|
|
|
return RedirectHandler(url.String(), StatusMovedPermanently), pattern
|
2012-08-31 12:16:31 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mux.handler(r.Host, r.URL.Path)
|
2011-02-01 13:58:59 -05:00
|
|
|
}
|
|
|
|
|
|
2012-08-31 12:16:31 -04:00
|
|
|
// handler is the main implementation of Handler.
|
|
|
|
|
// The path is known to be in canonical form, except for CONNECT methods.
|
|
|
|
|
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
|
2012-02-08 13:50:00 -05:00
|
|
|
mux.mu.RLock()
|
|
|
|
|
defer mux.mu.RUnlock()
|
|
|
|
|
|
|
|
|
|
// Host-specific pattern takes precedence over generic ones
|
2012-05-28 10:58:49 -07:00
|
|
|
if mux.hosts {
|
2012-08-31 12:16:31 -04:00
|
|
|
h, pattern = mux.match(host + path)
|
2012-05-28 10:58:49 -07:00
|
|
|
}
|
2012-02-08 13:50:00 -05:00
|
|
|
if h == nil {
|
2012-08-31 12:16:31 -04:00
|
|
|
h, pattern = mux.match(path)
|
2012-02-08 13:50:00 -05:00
|
|
|
}
|
|
|
|
|
if h == nil {
|
2012-08-31 12:16:31 -04:00
|
|
|
h, pattern = NotFoundHandler(), ""
|
2012-02-08 13:50:00 -05:00
|
|
|
}
|
2012-08-31 12:16:31 -04:00
|
|
|
return
|
2012-02-08 13:50:00 -05:00
|
|
|
}
|
|
|
|
|
|
2011-02-01 13:58:59 -05:00
|
|
|
// ServeHTTP dispatches the request to the handler whose
|
|
|
|
|
// pattern most closely matches the request URL.
|
|
|
|
|
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
2012-12-11 12:07:27 -05:00
|
|
|
if r.RequestURI == "*" {
|
2013-08-06 18:37:34 -07:00
|
|
|
if r.ProtoAtLeast(1, 1) {
|
|
|
|
|
w.Header().Set("Connection", "close")
|
|
|
|
|
}
|
2012-12-11 12:07:27 -05:00
|
|
|
w.WriteHeader(StatusBadRequest)
|
|
|
|
|
return
|
|
|
|
|
}
|
2012-08-31 12:16:31 -04:00
|
|
|
h, _ := mux.Handler(r)
|
|
|
|
|
h.ServeHTTP(w, r)
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2008-09-24 15:26:55 -07:00
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// Handle registers the handler for the given pattern.
|
2012-02-08 13:50:00 -05:00
|
|
|
// If a handler already exists for pattern, Handle panics.
|
2009-02-02 18:01:32 -08:00
|
|
|
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
2012-02-08 13:50:00 -05:00
|
|
|
mux.mu.Lock()
|
|
|
|
|
defer mux.mu.Unlock()
|
|
|
|
|
|
2011-02-01 13:58:59 -05:00
|
|
|
if pattern == "" {
|
2010-03-24 16:46:53 -07:00
|
|
|
panic("http: invalid pattern " + pattern)
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2012-02-08 13:50:00 -05:00
|
|
|
if handler == nil {
|
|
|
|
|
panic("http: nil handler")
|
|
|
|
|
}
|
|
|
|
|
if mux.m[pattern].explicit {
|
|
|
|
|
panic("http: multiple registrations for " + pattern)
|
|
|
|
|
}
|
2009-02-02 18:01:32 -08:00
|
|
|
|
2012-08-31 12:16:31 -04:00
|
|
|
mux.m[pattern] = muxEntry{explicit: true, h: handler, pattern: pattern}
|
2009-02-02 18:01:32 -08:00
|
|
|
|
2012-05-28 10:58:49 -07:00
|
|
|
if pattern[0] != '/' {
|
|
|
|
|
mux.hosts = true
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-02 18:01:32 -08:00
|
|
|
// Helpful behavior:
|
2012-02-08 13:50:00 -05:00
|
|
|
// If pattern is /tree/, insert an implicit permanent redirect for /tree.
|
|
|
|
|
// It can be overridden by an explicit registration.
|
2009-12-15 15:35:38 -08:00
|
|
|
n := len(pattern)
|
2012-02-08 13:50:00 -05:00
|
|
|
if n > 0 && pattern[n-1] == '/' && !mux.m[pattern[0:n-1]].explicit {
|
2012-08-31 12:00:01 -04:00
|
|
|
// If pattern contains a host name, strip it and use remaining
|
|
|
|
|
// path for redirect.
|
|
|
|
|
path := pattern
|
|
|
|
|
if pattern[0] != '/' {
|
|
|
|
|
// In pattern, at least the last character is a '/', so
|
|
|
|
|
// strings.Index can't be -1.
|
2013-08-05 16:27:24 -07:00
|
|
|
path = pattern[strings.Index(pattern, "/"):]
|
2012-08-31 12:00:01 -04:00
|
|
|
}
|
2012-08-31 12:16:31 -04:00
|
|
|
mux.m[pattern[0:n-1]] = muxEntry{h: RedirectHandler(path, StatusMovedPermanently), pattern: pattern}
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 10:02:37 +11:00
|
|
|
// HandleFunc registers the handler function for the given pattern.
|
2010-09-29 14:30:12 +10:00
|
|
|
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
|
2010-03-29 10:02:37 +11:00
|
|
|
mux.Handle(pattern, HandlerFunc(handler))
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// Handle registers the handler for the given pattern
|
|
|
|
|
// in the DefaultServeMux.
|
2011-02-22 11:16:25 +11:00
|
|
|
// The documentation for ServeMux explains how patterns are matched.
|
2009-12-15 15:35:38 -08:00
|
|
|
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
|
2009-02-02 18:01:32 -08:00
|
|
|
|
2010-03-29 10:02:37 +11:00
|
|
|
// HandleFunc registers the handler function for the given pattern
|
|
|
|
|
// in the DefaultServeMux.
|
2011-02-22 11:16:25 +11:00
|
|
|
// The documentation for ServeMux explains how patterns are matched.
|
2010-09-29 14:30:12 +10:00
|
|
|
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
|
2010-03-29 10:02:37 +11:00
|
|
|
DefaultServeMux.HandleFunc(pattern, handler)
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-11 12:51:10 -07:00
|
|
|
// Serve accepts incoming HTTP connections on the listener l,
|
2013-01-16 14:05:41 -08:00
|
|
|
// creating a new service goroutine for each. The service goroutines
|
2009-03-11 12:51:10 -07:00
|
|
|
// read requests and then call handler to reply to them.
|
|
|
|
|
// Handler is typically nil, in which case the DefaultServeMux is used.
|
2011-11-01 22:04:37 -04:00
|
|
|
func Serve(l net.Listener, handler Handler) error {
|
2011-02-10 14:36:22 -08:00
|
|
|
srv := &Server{Handler: handler}
|
|
|
|
|
return srv.Serve(l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A Server defines parameters for running an HTTP server.
|
2014-02-28 07:40:25 -08:00
|
|
|
// The zero value for Server is a valid configuration.
|
2011-02-10 14:36:22 -08:00
|
|
|
type Server struct {
|
2011-12-13 10:42:56 +11:00
|
|
|
Addr string // TCP address to listen on, ":http" if empty
|
|
|
|
|
Handler Handler // handler to invoke, http.DefaultServeMux if nil
|
2012-01-18 16:24:06 -08:00
|
|
|
ReadTimeout time.Duration // maximum duration before timing out read of the request
|
|
|
|
|
WriteTimeout time.Duration // maximum duration before timing out write of the response
|
2011-12-13 10:42:56 +11:00
|
|
|
MaxHeaderBytes int // maximum size of request headers, DefaultMaxHeaderBytes if 0
|
2012-02-21 10:24:15 +11:00
|
|
|
TLSConfig *tls.Config // optional TLS config, used by ListenAndServeTLS
|
2013-02-04 13:55:38 -08:00
|
|
|
|
|
|
|
|
// TLSNextProto optionally specifies a function to take over
|
|
|
|
|
// ownership of the provided TLS connection when an NPN
|
2013-04-24 04:46:14 +08:00
|
|
|
// protocol upgrade has occurred. The map key is the protocol
|
2013-02-04 13:55:38 -08:00
|
|
|
// name negotiated. The Handler argument should be used to
|
|
|
|
|
// handle HTTP requests and will initialize the Request's TLS
|
|
|
|
|
// and RemoteAddr if not already set. The connection is
|
|
|
|
|
// automatically closed when the function returns.
|
|
|
|
|
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
|
2014-02-27 18:29:00 -08:00
|
|
|
|
|
|
|
|
// ConnState specifies an optional callback function that is
|
|
|
|
|
// called when a client connection changes state. See the
|
|
|
|
|
// ConnState type and associated constants for details.
|
|
|
|
|
ConnState func(net.Conn, ConnState)
|
2014-02-28 07:40:25 -08:00
|
|
|
|
2014-02-28 12:12:51 -08:00
|
|
|
// ErrorLog specifies an optional logger for errors accepting
|
|
|
|
|
// connections and unexpected behavior from handlers.
|
|
|
|
|
// If nil, logging goes to os.Stderr via the log package's
|
|
|
|
|
// standard logger.
|
|
|
|
|
ErrorLog *log.Logger
|
|
|
|
|
|
2014-02-28 07:40:25 -08:00
|
|
|
disableKeepAlives int32 // accessed atomically.
|
2014-02-27 18:29:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A ConnState represents the state of a client connection to a server.
|
|
|
|
|
// It's used by the optional Server.ConnState hook.
|
|
|
|
|
type ConnState int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
// StateNew represents a new connection that is expected to
|
|
|
|
|
// send a request immediately. Connections begin at this
|
|
|
|
|
// state and then transition to either StateActive or
|
|
|
|
|
// StateClosed.
|
|
|
|
|
StateNew ConnState = iota
|
|
|
|
|
|
|
|
|
|
// StateActive represents a connection that has read 1 or more
|
|
|
|
|
// bytes of a request. The Server.ConnState hook for
|
|
|
|
|
// StateActive fires before the request has entered a handler
|
|
|
|
|
// and doesn't fire again until the request has been
|
|
|
|
|
// handled. After the request is handled, the state
|
|
|
|
|
// transitions to StateClosed, StateHijacked, or StateIdle.
|
|
|
|
|
StateActive
|
|
|
|
|
|
|
|
|
|
// StateIdle represents a connection that has finished
|
|
|
|
|
// handling a request and is in the keep-alive state, waiting
|
|
|
|
|
// for a new request. Connections transition from StateIdle
|
|
|
|
|
// to either StateActive or StateClosed.
|
|
|
|
|
StateIdle
|
|
|
|
|
|
|
|
|
|
// StateHijacked represents a hijacked connection.
|
|
|
|
|
// This is a terminal state. It does not transition to StateClosed.
|
|
|
|
|
StateHijacked
|
|
|
|
|
|
|
|
|
|
// StateClosed represents a closed connection.
|
|
|
|
|
// This is a terminal state. Hijacked connections do not
|
|
|
|
|
// transition to StateClosed.
|
|
|
|
|
StateClosed
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var stateName = map[ConnState]string{
|
|
|
|
|
StateNew: "new",
|
|
|
|
|
StateActive: "active",
|
|
|
|
|
StateIdle: "idle",
|
|
|
|
|
StateHijacked: "hijacked",
|
|
|
|
|
StateClosed: "closed",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c ConnState) String() string {
|
|
|
|
|
return stateName[c]
|
2013-02-04 13:55:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// serverHandler delegates to either the server's Handler or
|
|
|
|
|
// DefaultServeMux and also handles "OPTIONS *" requests.
|
|
|
|
|
type serverHandler struct {
|
|
|
|
|
srv *Server
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
|
|
|
|
|
handler := sh.srv.Handler
|
|
|
|
|
if handler == nil {
|
|
|
|
|
handler = DefaultServeMux
|
|
|
|
|
}
|
|
|
|
|
if req.RequestURI == "*" && req.Method == "OPTIONS" {
|
|
|
|
|
handler = globalOptionsHandler{}
|
|
|
|
|
}
|
|
|
|
|
handler.ServeHTTP(rw, req)
|
2011-02-10 14:36:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.
|
2011-11-01 22:04:37 -04:00
|
|
|
func (srv *Server) ListenAndServe() error {
|
2011-02-10 14:36:22 -08:00
|
|
|
addr := srv.Addr
|
|
|
|
|
if addr == "" {
|
|
|
|
|
addr = ":http"
|
|
|
|
|
}
|
2014-01-09 15:05:09 -08:00
|
|
|
ln, err := net.Listen("tcp", addr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
2011-02-10 14:36:22 -08:00
|
|
|
}
|
2014-01-09 15:05:09 -08:00
|
|
|
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
|
2011-02-10 14:36:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Serve accepts incoming connections on the Listener l, creating a
|
2013-01-16 14:05:41 -08:00
|
|
|
// new service goroutine for each. The service goroutines read requests and
|
2011-02-10 14:36:22 -08:00
|
|
|
// then call srv.Handler to reply to them.
|
2011-11-01 22:04:37 -04:00
|
|
|
func (srv *Server) Serve(l net.Listener) error {
|
2011-02-10 14:36:22 -08:00
|
|
|
defer l.Close()
|
2012-02-14 15:04:29 +11:00
|
|
|
var tempDelay time.Duration // how long to sleep on accept failure
|
2008-09-24 15:26:55 -07:00
|
|
|
for {
|
2009-12-15 15:35:38 -08:00
|
|
|
rw, e := l.Accept()
|
2008-09-24 15:26:55 -07:00
|
|
|
if e != nil {
|
2011-06-03 12:23:50 -07:00
|
|
|
if ne, ok := e.(net.Error); ok && ne.Temporary() {
|
2012-02-14 15:04:29 +11:00
|
|
|
if tempDelay == 0 {
|
|
|
|
|
tempDelay = 5 * time.Millisecond
|
|
|
|
|
} else {
|
|
|
|
|
tempDelay *= 2
|
|
|
|
|
}
|
|
|
|
|
if max := 1 * time.Second; tempDelay > max {
|
|
|
|
|
tempDelay = max
|
|
|
|
|
}
|
2014-02-28 12:12:51 -08:00
|
|
|
srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
|
2012-02-14 15:04:29 +11:00
|
|
|
time.Sleep(tempDelay)
|
2011-06-03 12:23:50 -07:00
|
|
|
continue
|
|
|
|
|
}
|
2009-11-09 12:07:39 -08:00
|
|
|
return e
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
2012-02-14 15:04:29 +11:00
|
|
|
tempDelay = 0
|
2011-08-09 10:55:14 -07:00
|
|
|
c, err := srv.newConn(rw)
|
2009-02-02 18:01:32 -08:00
|
|
|
if err != nil {
|
2009-11-09 12:07:39 -08:00
|
|
|
continue
|
2009-02-02 18:01:32 -08:00
|
|
|
}
|
2014-03-01 20:32:42 -08:00
|
|
|
c.setState(c.rwc, StateNew) // before Serve can return
|
2009-12-15 15:35:38 -08:00
|
|
|
go c.serve()
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-28 07:40:25 -08:00
|
|
|
func (s *Server) doKeepAlives() bool {
|
|
|
|
|
return atomic.LoadInt32(&s.disableKeepAlives) == 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetKeepAlivesEnabled controls whether HTTP keep-alives are enabled.
|
|
|
|
|
// By default, keep-alives are always enabled. Only very
|
|
|
|
|
// resource-constrained environments or servers in the process of
|
|
|
|
|
// shutting down should disable them.
|
|
|
|
|
func (s *Server) SetKeepAlivesEnabled(v bool) {
|
|
|
|
|
if v {
|
|
|
|
|
atomic.StoreInt32(&s.disableKeepAlives, 0)
|
|
|
|
|
} else {
|
|
|
|
|
atomic.StoreInt32(&s.disableKeepAlives, 1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-28 12:12:51 -08:00
|
|
|
func (s *Server) logf(format string, args ...interface{}) {
|
|
|
|
|
if s.ErrorLog != nil {
|
|
|
|
|
s.ErrorLog.Printf(format, args...)
|
|
|
|
|
} else {
|
|
|
|
|
log.Printf(format, args...)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-11 12:51:10 -07: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 22:55:05 -07:00
|
|
|
// "io"
|
2011-11-18 18:33:44 -05:00
|
|
|
// "net/http"
|
2010-04-05 22:55:05 -07:00
|
|
|
// "log"
|
2009-03-11 12:51:10 -07:00
|
|
|
// )
|
|
|
|
|
//
|
|
|
|
|
// // hello world, the web server
|
2010-09-29 14:30:12 +10:00
|
|
|
// func HelloServer(w http.ResponseWriter, req *http.Request) {
|
|
|
|
|
// io.WriteString(w, "hello, world!\n")
|
2009-03-11 12:51:10 -07:00
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// func main() {
|
2010-04-05 22:55:05 -07:00
|
|
|
// http.HandleFunc("/hello", HelloServer)
|
|
|
|
|
// err := http.ListenAndServe(":12345", nil)
|
2009-03-11 12:51:10 -07:00
|
|
|
// if err != nil {
|
2011-12-11 09:29:44 -08:00
|
|
|
// log.Fatal("ListenAndServe: ", err)
|
2009-03-11 12:51:10 -07:00
|
|
|
// }
|
|
|
|
|
// }
|
2011-11-01 22:04:37 -04:00
|
|
|
func ListenAndServe(addr string, handler Handler) error {
|
2011-02-10 14:36:22 -08:00
|
|
|
server := &Server{Addr: addr, Handler: handler}
|
|
|
|
|
return server.ListenAndServe()
|
2008-09-24 15:26:55 -07:00
|
|
|
}
|
2010-07-02 13:00:18 -04:00
|
|
|
|
2010-07-02 16:43:48 -04:00
|
|
|
// ListenAndServeTLS acts identically to ListenAndServe, except that it
|
|
|
|
|
// expects HTTPS connections. Additionally, files containing a certificate and
|
2011-06-20 12:19:26 -07:00
|
|
|
// 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.
|
2010-07-02 13:00:18 -04:00
|
|
|
//
|
|
|
|
|
// A trivial example server is:
|
|
|
|
|
//
|
|
|
|
|
// import (
|
|
|
|
|
// "log"
|
2011-11-18 18:33:44 -05:00
|
|
|
// "net/http"
|
2010-07-02 13:00:18 -04:00
|
|
|
// )
|
|
|
|
|
//
|
2010-09-29 14:30:12 +10:00
|
|
|
// func handler(w http.ResponseWriter, req *http.Request) {
|
2011-03-09 09:41:01 -08:00
|
|
|
// w.Header().Set("Content-Type", "text/plain")
|
2010-09-29 14:30:12 +10:00
|
|
|
// w.Write([]byte("This is an example server.\n"))
|
2010-07-02 13:00:18 -04: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 12:59:18 -07:00
|
|
|
// log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
|
2010-08-16 11:22:22 -04:00
|
|
|
// err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
|
2010-07-02 13:00:18 -04:00
|
|
|
// if err != nil {
|
2011-02-01 12:47:35 -08:00
|
|
|
// log.Fatal(err)
|
2010-07-02 13:00:18 -04:00
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
|
2011-11-01 22:04:37 -04:00
|
|
|
func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error {
|
2011-06-20 12:19:26 -07:00
|
|
|
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.
|
2012-01-30 11:58:49 -08:00
|
|
|
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
|
|
|
|
|
addr := srv.Addr
|
2011-06-20 12:19:26 -07:00
|
|
|
if addr == "" {
|
|
|
|
|
addr = ":https"
|
|
|
|
|
}
|
2012-02-21 10:24:15 +11:00
|
|
|
config := &tls.Config{}
|
|
|
|
|
if srv.TLSConfig != nil {
|
|
|
|
|
*config = *srv.TLSConfig
|
|
|
|
|
}
|
|
|
|
|
if config.NextProtos == nil {
|
|
|
|
|
config.NextProtos = []string{"http/1.1"}
|
2010-07-02 13:00:18 -04:00
|
|
|
}
|
|
|
|
|
|
2011-11-01 22:04:37 -04:00
|
|
|
var err error
|
2010-07-02 13:00:18 -04:00
|
|
|
config.Certificates = make([]tls.Certificate, 1)
|
|
|
|
|
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-09 15:05:09 -08:00
|
|
|
ln, err := net.Listen("tcp", addr)
|
2010-07-02 13:00:18 -04:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-09 15:05:09 -08:00
|
|
|
tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
|
2012-01-30 11:58:49 -08:00
|
|
|
return srv.Serve(tlsListener)
|
2010-07-02 13:00:18 -04:00
|
|
|
}
|
2011-04-15 12:53:32 -07:00
|
|
|
|
|
|
|
|
// 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
|
2013-01-03 10:06:04 -08:00
|
|
|
// call runs for longer than its time limit, the handler responds with
|
2011-04-15 12:53:32 -07:00
|
|
|
// 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.
|
2011-11-30 12:01:46 -05:00
|
|
|
func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
|
|
|
|
|
f := func() <-chan time.Time {
|
|
|
|
|
return time.After(dt)
|
2011-04-15 12:53:32 -07:00
|
|
|
}
|
|
|
|
|
return &timeoutHandler{h, f, msg}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ErrHandlerTimeout is returned on ResponseWriter Write calls
|
|
|
|
|
// in handlers which have timed out.
|
2011-11-01 22:04:37 -04:00
|
|
|
var ErrHandlerTimeout = errors.New("http: Handler timeout")
|
2011-04-15 12:53:32 -07:00
|
|
|
|
|
|
|
|
type timeoutHandler struct {
|
|
|
|
|
handler Handler
|
2011-11-30 12:01:46 -05:00
|
|
|
timeout func() <-chan time.Time // returns channel producing a timeout
|
2011-04-15 12:53:32 -07:00
|
|
|
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) {
|
2013-02-26 17:12:50 -08:00
|
|
|
done := make(chan bool, 1)
|
2011-04-15 12:53:32 -07:00
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-01 22:04:37 -04:00
|
|
|
func (tw *timeoutWriter) Write(p []byte) (int, error) {
|
2011-04-15 12:53:32 -07:00
|
|
|
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)
|
|
|
|
|
}
|
net/http: fix Transport races & deadlocks
Thanks to Dustin Sallings for exposing the most frustrating
bug ever, and for providing repro cases (which formed the
basis of the new tests in this CL), and to Dave Cheney and
Dmitry Vyukov for help debugging and fixing.
This CL depends on submited pollster CLs ffd1e075c260 (Unix)
and 14b544194509 (Windows), as well as unsubmitted 6852085.
Some operating systems (OpenBSD, NetBSD, ?) may still require
more pollster work, fixing races (Issue 4434 and
http://goo.gl/JXB6W).
Tested on linux-amd64 and darwin-amd64, both with GOMAXPROCS 1
and 4 (all combinations of which previously failed differently)
Fixes #4191
Update #4434 (related fallout from this bug)
R=dave, bradfitz, dsallings, rsc, fullung
CC=golang-dev
https://golang.org/cl/6851061
2012-11-26 13:31:02 -08:00
|
|
|
|
2014-01-09 15:05:09 -08:00
|
|
|
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
|
|
|
|
|
// connections. It's used by ListenAndServe and ListenAndServeTLS so
|
|
|
|
|
// dead TCP connections (e.g. closing laptop mid-download) eventually
|
|
|
|
|
// go away.
|
|
|
|
|
type tcpKeepAliveListener struct {
|
|
|
|
|
*net.TCPListener
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
|
|
|
|
tc, err := ln.AcceptTCP()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
tc.SetKeepAlive(true)
|
|
|
|
|
tc.SetKeepAlivePeriod(3 * time.Minute)
|
|
|
|
|
return tc, nil
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-11 12:07:27 -05:00
|
|
|
// globalOptionsHandler responds to "OPTIONS *" requests.
|
|
|
|
|
type globalOptionsHandler struct{}
|
|
|
|
|
|
|
|
|
|
func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
|
|
|
|
|
w.Header().Set("Content-Length", "0")
|
|
|
|
|
if r.ContentLength != 0 {
|
|
|
|
|
// Read up to 4KB of OPTIONS body (as mentioned in the
|
|
|
|
|
// spec as being reserved for future use), but anything
|
|
|
|
|
// over that is considered a waste of server resources
|
|
|
|
|
// (or an attack) and we abort and close the connection,
|
|
|
|
|
// courtesy of MaxBytesReader's EOF behavior.
|
|
|
|
|
mb := MaxBytesReader(w, r.Body, 4<<10)
|
|
|
|
|
io.Copy(ioutil.Discard, mb)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-25 06:44:51 -07:00
|
|
|
type eofReaderWithWriteTo struct{}
|
|
|
|
|
|
|
|
|
|
func (eofReaderWithWriteTo) WriteTo(io.Writer) (int64, error) { return 0, nil }
|
|
|
|
|
func (eofReaderWithWriteTo) Read([]byte) (int, error) { return 0, io.EOF }
|
|
|
|
|
|
2013-02-04 13:55:38 -08:00
|
|
|
// eofReader is a non-nil io.ReadCloser that always returns EOF.
|
2014-04-25 06:44:51 -07:00
|
|
|
// It has a WriteTo method so io.Copy won't need a buffer.
|
2013-05-20 07:23:59 -07:00
|
|
|
var eofReader = &struct {
|
2014-04-25 06:44:51 -07:00
|
|
|
eofReaderWithWriteTo
|
2013-05-20 07:23:59 -07:00
|
|
|
io.Closer
|
|
|
|
|
}{
|
2014-04-25 06:44:51 -07:00
|
|
|
eofReaderWithWriteTo{},
|
2013-05-20 07:23:59 -07:00
|
|
|
ioutil.NopCloser(nil),
|
|
|
|
|
}
|
2013-02-04 13:55:38 -08:00
|
|
|
|
2014-04-25 06:44:51 -07:00
|
|
|
// Verify that an io.Copy from an eofReader won't require a buffer.
|
|
|
|
|
var _ io.WriterTo = eofReader
|
|
|
|
|
|
2013-02-04 13:55:38 -08:00
|
|
|
// initNPNRequest is an HTTP handler that initializes certain
|
|
|
|
|
// uninitialized fields in its *Request. Such partially-initialized
|
|
|
|
|
// Requests come from NPN protocol handlers.
|
|
|
|
|
type initNPNRequest struct {
|
|
|
|
|
c *tls.Conn
|
|
|
|
|
h serverHandler
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (h initNPNRequest) ServeHTTP(rw ResponseWriter, req *Request) {
|
|
|
|
|
if req.TLS == nil {
|
|
|
|
|
req.TLS = &tls.ConnectionState{}
|
|
|
|
|
*req.TLS = h.c.ConnectionState()
|
|
|
|
|
}
|
|
|
|
|
if req.Body == nil {
|
|
|
|
|
req.Body = eofReader
|
|
|
|
|
}
|
|
|
|
|
if req.RemoteAddr == "" {
|
|
|
|
|
req.RemoteAddr = h.c.RemoteAddr().String()
|
|
|
|
|
}
|
|
|
|
|
h.h.ServeHTTP(rw, req)
|
|
|
|
|
}
|
|
|
|
|
|
net/http: fix Transport races & deadlocks
Thanks to Dustin Sallings for exposing the most frustrating
bug ever, and for providing repro cases (which formed the
basis of the new tests in this CL), and to Dave Cheney and
Dmitry Vyukov for help debugging and fixing.
This CL depends on submited pollster CLs ffd1e075c260 (Unix)
and 14b544194509 (Windows), as well as unsubmitted 6852085.
Some operating systems (OpenBSD, NetBSD, ?) may still require
more pollster work, fixing races (Issue 4434 and
http://goo.gl/JXB6W).
Tested on linux-amd64 and darwin-amd64, both with GOMAXPROCS 1
and 4 (all combinations of which previously failed differently)
Fixes #4191
Update #4434 (related fallout from this bug)
R=dave, bradfitz, dsallings, rsc, fullung
CC=golang-dev
https://golang.org/cl/6851061
2012-11-26 13:31:02 -08:00
|
|
|
// loggingConn is used for debugging.
|
|
|
|
|
type loggingConn struct {
|
|
|
|
|
name string
|
|
|
|
|
net.Conn
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
uniqNameMu sync.Mutex
|
|
|
|
|
uniqNameNext = make(map[string]int)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func newLoggingConn(baseName string, c net.Conn) net.Conn {
|
|
|
|
|
uniqNameMu.Lock()
|
|
|
|
|
defer uniqNameMu.Unlock()
|
|
|
|
|
uniqNameNext[baseName]++
|
|
|
|
|
return &loggingConn{
|
|
|
|
|
name: fmt.Sprintf("%s-%d", baseName, uniqNameNext[baseName]),
|
|
|
|
|
Conn: c,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *loggingConn) Write(p []byte) (n int, err error) {
|
|
|
|
|
log.Printf("%s.Write(%d) = ....", c.name, len(p))
|
|
|
|
|
n, err = c.Conn.Write(p)
|
|
|
|
|
log.Printf("%s.Write(%d) = %d, %v", c.name, len(p), n, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *loggingConn) Read(p []byte) (n int, err error) {
|
|
|
|
|
log.Printf("%s.Read(%d) = ....", c.name, len(p))
|
|
|
|
|
n, err = c.Conn.Read(p)
|
|
|
|
|
log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *loggingConn) Close() (err error) {
|
|
|
|
|
log.Printf("%s.Close() = ...", c.name)
|
|
|
|
|
err = c.Conn.Close()
|
|
|
|
|
log.Printf("%s.Close() = %v", c.name, err)
|
|
|
|
|
return
|
|
|
|
|
}
|