summaryrefslogtreecommitdiff
path: root/libgo/go/net/http/fcgi/child.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/http/fcgi/child.go')
-rw-r--r--libgo/go/net/http/fcgi/child.go41
1 files changed, 31 insertions, 10 deletions
diff --git a/libgo/go/net/http/fcgi/child.go b/libgo/go/net/http/fcgi/child.go
index c8b9a33c87b..60b794e0775 100644
--- a/libgo/go/net/http/fcgi/child.go
+++ b/libgo/go/net/http/fcgi/child.go
@@ -10,10 +10,12 @@ import (
"errors"
"fmt"
"io"
+ "io/ioutil"
"net"
"net/http"
"net/http/cgi"
"os"
+ "strings"
"time"
)
@@ -152,20 +154,23 @@ func (c *child) serve() {
var errCloseConn = errors.New("fcgi: connection should be closed")
+var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+
func (c *child) handleRecord(rec *record) error {
req, ok := c.requests[rec.h.Id]
if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
// The spec says to ignore unknown request IDs.
return nil
}
- if ok && rec.h.Type == typeBeginRequest {
- // The server is trying to begin a request with the same ID
- // as an in-progress request. This is an error.
- return errors.New("fcgi: received ID that is already in-flight")
- }
switch rec.h.Type {
case typeBeginRequest:
+ if req != nil {
+ // The server is trying to begin a request with the same ID
+ // as an in-progress request. This is an error.
+ return errors.New("fcgi: received ID that is already in-flight")
+ }
+
var br beginRequest
if err := br.read(rec.content()); err != nil {
return err
@@ -175,6 +180,7 @@ func (c *child) handleRecord(rec *record) error {
return nil
}
c.requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
+ return nil
case typeParams:
// NOTE(eds): Technically a key-value pair can straddle the boundary
// between two packets. We buffer until we've received all parameters.
@@ -183,6 +189,7 @@ func (c *child) handleRecord(rec *record) error {
return nil
}
req.parseParams()
+ return nil
case typeStdin:
content := rec.content()
if req.pw == nil {
@@ -191,6 +198,8 @@ func (c *child) handleRecord(rec *record) error {
// body could be an io.LimitReader, but it shouldn't matter
// as long as both sides are behaving.
body, req.pw = io.Pipe()
+ } else {
+ body = emptyBody
}
go c.serveRequest(req, body)
}
@@ -201,24 +210,29 @@ func (c *child) handleRecord(rec *record) error {
} else if req.pw != nil {
req.pw.Close()
}
+ return nil
case typeGetValues:
values := map[string]string{"FCGI_MPXS_CONNS": "1"}
c.conn.writePairs(typeGetValuesResult, 0, values)
+ return nil
case typeData:
// If the filter role is implemented, read the data stream here.
+ return nil
case typeAbortRequest:
+ println("abort")
delete(c.requests, rec.h.Id)
c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
if !req.keepConn {
// connection will close upon return
return errCloseConn
}
+ return nil
default:
b := make([]byte, 8)
b[0] = byte(rec.h.Type)
c.conn.writeRecord(typeUnknownType, 0, b)
+ return nil
}
- return nil
}
func (c *child) serveRequest(req *request, body io.ReadCloser) {
@@ -232,11 +246,19 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) {
httpReq.Body = body
c.handler.ServeHTTP(r, httpReq)
}
- if body != nil {
- body.Close()
- }
r.Close()
c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
+
+ // Consume the entire body, so the host isn't still writing to
+ // us when we close the socket below in the !keepConn case,
+ // otherwise we'd send a RST. (golang.org/issue/4183)
+ // TODO(bradfitz): also bound this copy in time. Or send
+ // some sort of abort request to the host, so the host
+ // can properly cut off the client sending all the data.
+ // For now just bound it a little and
+ io.CopyN(ioutil.Discard, body, 100<<20)
+ body.Close()
+
if !req.keepConn {
c.conn.Close()
}
@@ -267,5 +289,4 @@ func Serve(l net.Listener, handler http.Handler) error {
c := newChild(rw, handler)
go c.serve()
}
- panic("unreachable")
}