mirror of
https://github.com/golang/go
synced 2024-11-25 04:47:57 -07:00
http: reply to Expect 100-continue requests automatically
This CL replaces my earlier https://golang.org/cl/1640044/show in which Continue handling was explicit. Instead, this CL makes it automatic. Reading from Body() is an implicit acknowledgement that the request headers were fine and the body is wanted. In that case, the 100 Continue response is written automatically when the request continues the "Expect: 100-continue" header. R=rsc, adg CC=golang-dev https://golang.org/cl/1610042
This commit is contained in:
parent
93ea2ae362
commit
743f818218
@ -635,3 +635,8 @@ func (r *Request) FormValue(key string) string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Request) expectsContinue() bool {
|
||||||
|
expectation, ok := r.Header["Expect"]
|
||||||
|
return ok && strings.ToLower(expectation) == "100-continue"
|
||||||
|
}
|
||||||
|
@ -56,6 +56,7 @@ type Conn struct {
|
|||||||
closeAfterReply bool // close connection after this reply
|
closeAfterReply bool // close connection after this reply
|
||||||
chunking bool // using chunked transfer encoding for reply body
|
chunking bool // using chunked transfer encoding for reply body
|
||||||
wroteHeader bool // reply header has been written
|
wroteHeader bool // reply header has been written
|
||||||
|
wroteContinue bool // 100 Continue response was written
|
||||||
header map[string]string // reply header parameters
|
header map[string]string // reply header parameters
|
||||||
written int64 // number of bytes written in body
|
written int64 // number of bytes written in body
|
||||||
status int // status code passed to WriteHeader
|
status int // status code passed to WriteHeader
|
||||||
@ -75,6 +76,28 @@ func newConn(rwc net.Conn, handler Handler) (c *Conn, err os.Error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wrapper around io.ReaderCloser which on first read, sends an
|
||||||
|
// HTTP/1.1 100 Continue header
|
||||||
|
type expectContinueReader struct {
|
||||||
|
conn *Conn
|
||||||
|
readCloser io.ReadCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ecr *expectContinueReader) Read(p []byte) (n int, err os.Error) {
|
||||||
|
if !ecr.conn.wroteContinue && !ecr.conn.hijacked {
|
||||||
|
ecr.conn.wroteContinue = true
|
||||||
|
if ecr.conn.Req.ProtoAtLeast(1, 1) {
|
||||||
|
io.WriteString(ecr.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n")
|
||||||
|
ecr.conn.buf.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ecr.readCloser.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ecr *expectContinueReader) Close() os.Error {
|
||||||
|
return ecr.readCloser.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// Read next request from connection.
|
// Read next request from connection.
|
||||||
func (c *Conn) readRequest() (req *Request, err os.Error) {
|
func (c *Conn) readRequest() (req *Request, err os.Error) {
|
||||||
if c.hijacked {
|
if c.hijacked {
|
||||||
@ -87,8 +110,15 @@ func (c *Conn) readRequest() (req *Request, err os.Error) {
|
|||||||
// Reset per-request connection state.
|
// Reset per-request connection state.
|
||||||
c.header = make(map[string]string)
|
c.header = make(map[string]string)
|
||||||
c.wroteHeader = false
|
c.wroteHeader = false
|
||||||
|
c.wroteContinue = false
|
||||||
c.Req = req
|
c.Req = req
|
||||||
|
|
||||||
|
// Expect 100 Continue support
|
||||||
|
if req.expectsContinue() {
|
||||||
|
// Wrap the Body reader with one that replies on the connection
|
||||||
|
req.Body = &expectContinueReader{readCloser: req.Body, conn: c}
|
||||||
|
}
|
||||||
|
|
||||||
// Default output is HTML encoded in UTF-8.
|
// Default output is HTML encoded in UTF-8.
|
||||||
c.SetHeader("Content-Type", "text/html; charset=utf-8")
|
c.SetHeader("Content-Type", "text/html; charset=utf-8")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user