aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libgo/go/net/http/fcgi/child.go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libgo/go/net/http/fcgi/child.go')
-rw-r--r--gcc-4.8.1/libgo/go/net/http/fcgi/child.go271
1 files changed, 0 insertions, 271 deletions
diff --git a/gcc-4.8.1/libgo/go/net/http/fcgi/child.go b/gcc-4.8.1/libgo/go/net/http/fcgi/child.go
deleted file mode 100644
index c8b9a33c8..000000000
--- a/gcc-4.8.1/libgo/go/net/http/fcgi/child.go
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright 2011 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.
-
-package fcgi
-
-// This file implements FastCGI from the perspective of a child process.
-
-import (
- "errors"
- "fmt"
- "io"
- "net"
- "net/http"
- "net/http/cgi"
- "os"
- "time"
-)
-
-// request holds the state for an in-progress request. As soon as it's complete,
-// it's converted to an http.Request.
-type request struct {
- pw *io.PipeWriter
- reqId uint16
- params map[string]string
- buf [1024]byte
- rawParams []byte
- keepConn bool
-}
-
-func newRequest(reqId uint16, flags uint8) *request {
- r := &request{
- reqId: reqId,
- params: map[string]string{},
- keepConn: flags&flagKeepConn != 0,
- }
- r.rawParams = r.buf[:0]
- return r
-}
-
-// parseParams reads an encoded []byte into Params.
-func (r *request) parseParams() {
- text := r.rawParams
- r.rawParams = nil
- for len(text) > 0 {
- keyLen, n := readSize(text)
- if n == 0 {
- return
- }
- text = text[n:]
- valLen, n := readSize(text)
- if n == 0 {
- return
- }
- text = text[n:]
- key := readString(text, keyLen)
- text = text[keyLen:]
- val := readString(text, valLen)
- text = text[valLen:]
- r.params[key] = val
- }
-}
-
-// response implements http.ResponseWriter.
-type response struct {
- req *request
- header http.Header
- w *bufWriter
- wroteHeader bool
-}
-
-func newResponse(c *child, req *request) *response {
- return &response{
- req: req,
- header: http.Header{},
- w: newWriter(c.conn, typeStdout, req.reqId),
- }
-}
-
-func (r *response) Header() http.Header {
- return r.header
-}
-
-func (r *response) Write(data []byte) (int, error) {
- if !r.wroteHeader {
- r.WriteHeader(http.StatusOK)
- }
- return r.w.Write(data)
-}
-
-func (r *response) WriteHeader(code int) {
- if r.wroteHeader {
- return
- }
- r.wroteHeader = true
- if code == http.StatusNotModified {
- // Must not have body.
- r.header.Del("Content-Type")
- r.header.Del("Content-Length")
- r.header.Del("Transfer-Encoding")
- } else if r.header.Get("Content-Type") == "" {
- r.header.Set("Content-Type", "text/html; charset=utf-8")
- }
-
- if r.header.Get("Date") == "" {
- r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
- }
-
- fmt.Fprintf(r.w, "Status: %d %s\r\n", code, http.StatusText(code))
- r.header.Write(r.w)
- r.w.WriteString("\r\n")
-}
-
-func (r *response) Flush() {
- if !r.wroteHeader {
- r.WriteHeader(http.StatusOK)
- }
- r.w.Flush()
-}
-
-func (r *response) Close() error {
- r.Flush()
- return r.w.Close()
-}
-
-type child struct {
- conn *conn
- handler http.Handler
- requests map[uint16]*request // keyed by request ID
-}
-
-func newChild(rwc io.ReadWriteCloser, handler http.Handler) *child {
- return &child{
- conn: newConn(rwc),
- handler: handler,
- requests: make(map[uint16]*request),
- }
-}
-
-func (c *child) serve() {
- defer c.conn.Close()
- var rec record
- for {
- if err := rec.read(c.conn.rwc); err != nil {
- return
- }
- if err := c.handleRecord(&rec); err != nil {
- return
- }
- }
-}
-
-var errCloseConn = errors.New("fcgi: connection should be closed")
-
-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:
- var br beginRequest
- if err := br.read(rec.content()); err != nil {
- return err
- }
- if br.role != roleResponder {
- c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
- return nil
- }
- c.requests[rec.h.Id] = newRequest(rec.h.Id, br.flags)
- case typeParams:
- // NOTE(eds): Technically a key-value pair can straddle the boundary
- // between two packets. We buffer until we've received all parameters.
- if len(rec.content()) > 0 {
- req.rawParams = append(req.rawParams, rec.content()...)
- return nil
- }
- req.parseParams()
- case typeStdin:
- content := rec.content()
- if req.pw == nil {
- var body io.ReadCloser
- if len(content) > 0 {
- // body could be an io.LimitReader, but it shouldn't matter
- // as long as both sides are behaving.
- body, req.pw = io.Pipe()
- }
- go c.serveRequest(req, body)
- }
- if len(content) > 0 {
- // TODO(eds): This blocks until the handler reads from the pipe.
- // If the handler takes a long time, it might be a problem.
- req.pw.Write(content)
- } else if req.pw != nil {
- req.pw.Close()
- }
- case typeGetValues:
- values := map[string]string{"FCGI_MPXS_CONNS": "1"}
- c.conn.writePairs(typeGetValuesResult, 0, values)
- case typeData:
- // If the filter role is implemented, read the data stream here.
- case typeAbortRequest:
- delete(c.requests, rec.h.Id)
- c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
- if !req.keepConn {
- // connection will close upon return
- return errCloseConn
- }
- default:
- b := make([]byte, 8)
- b[0] = byte(rec.h.Type)
- c.conn.writeRecord(typeUnknownType, 0, b)
- }
- return nil
-}
-
-func (c *child) serveRequest(req *request, body io.ReadCloser) {
- r := newResponse(c, req)
- httpReq, err := cgi.RequestFromMap(req.params)
- if err != nil {
- // there was an error reading the request
- r.WriteHeader(http.StatusInternalServerError)
- c.conn.writeRecord(typeStderr, req.reqId, []byte(err.Error()))
- } else {
- httpReq.Body = body
- c.handler.ServeHTTP(r, httpReq)
- }
- if body != nil {
- body.Close()
- }
- r.Close()
- c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
- if !req.keepConn {
- c.conn.Close()
- }
-}
-
-// Serve accepts incoming FastCGI connections on the listener l, creating a new
-// goroutine for each. The goroutine reads requests and then calls handler
-// to reply to them.
-// If l is nil, Serve accepts connections from os.Stdin.
-// If handler is nil, http.DefaultServeMux is used.
-func Serve(l net.Listener, handler http.Handler) error {
- if l == nil {
- var err error
- l, err = net.FileListener(os.Stdin)
- if err != nil {
- return err
- }
- defer l.Close()
- }
- if handler == nil {
- handler = http.DefaultServeMux
- }
- for {
- rw, err := l.Accept()
- if err != nil {
- return err
- }
- c := newChild(rw, handler)
- go c.serve()
- }
- panic("unreachable")
-}