Imports #
"context"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/http/cgi"
"os"
"strings"
"time"
"bufio"
"bytes"
"encoding/binary"
"errors"
"io"
"sync"
"context"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/http/cgi"
"os"
"strings"
"time"
"bufio"
"bytes"
"encoding/binary"
"errors"
"io"
"sync"
ErrConnClosed is returned by Read when a handler attempts to read the body of a request after the connection to the web server has been closed.
var ErrConnClosed = *ast.CallExprErrRequestAborted is returned by Read when a handler attempts to read the body of a request that has been aborted by the web server.
var ErrRequestAborted = *ast.CallExprvar emptyBody = *ast.CallExprvar errCloseConn = *ast.CallExprkeep the connection between web-server and responder open after request
const flagKeepConn = 1const maxPad = 255const maxWrite = 65535for padding so we don't have to allocate all the time not synchronized because we don't care what the contents are
var pad [maxPad]byteconst roleAuthorizerconst roleFilterconst roleResponder = *ast.BinaryExprconst statusCantMultiplexconst statusOverloadedconst statusRequestComplete = iotaconst statusUnknownRoleconst typeAbortRequest recType = 2const typeBeginRequest recType = 1const typeData recType = 8const typeEndRequest recType = 3const typeGetValues recType = 9const typeGetValuesResult recType = 10const typeParams recType = 4const typeStderr recType = 7const typeStdin recType = 5const typeStdout recType = 6const typeUnknownType recType = 11recType is a record type, as defined by https://web.archive.org/web/20150420080736/http://www.fastcgi.com/drupal/node/6?q=node/22#S8
type recType uint8type beginRequest struct {
role uint16
flags uint8
reserved [5]uint8
}bufWriter encapsulates bufio.Writer but also closes the underlying stream when Closed.
type bufWriter struct {
closer io.Closer
*bufio.Writer
}type child struct {
conn *conn
handler http.Handler
requests map[uint16]*request
}conn sends records over rwc
type conn struct {
mutex sync.Mutex
rwc io.ReadWriteCloser
closeErr error
closed bool
buf bytes.Buffer
h header
}envVarsContextKey uniquely identifies a mapping of CGI environment variables to their values in a request context
type envVarsContextKey struct {
}type header struct {
Version uint8
Type recType
Id uint16
ContentLength uint16
PaddingLength uint8
Reserved uint8
}type record struct {
h header
buf [*ast.BinaryExpr]byte
}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
}response implements http.ResponseWriter.
type response struct {
req *request
header http.Header
code int
wroteHeader bool
wroteCGIHeader bool
w *bufWriter
}streamWriter abstracts out the separation of a stream into discrete records. It only writes maxWrite bytes at a time.
type streamWriter struct {
c *conn
recType recType
reqId uint16
}func (w *streamWriter) Close() errorfunc (w *bufWriter) Close() errorClose closes the conn if it is not already closed.
func (c *conn) Close() errorfunc (r *response) Close() errorfunc (r *response) Flush()func (r *response) Header() http.HeaderProcessEnv returns FastCGI environment variables associated with the request r for which no effort was made to be included in the request itself - the data is hidden in the request's context. As an example, if REMOTE_USER is set for a request, it will not be found anywhere in r, but it will be included in ProcessEnv's response (via r's context).
func ProcessEnv(r *http.Request) map[string]stringServe 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) errorfunc (w *streamWriter) Write(p []byte) (int, error)func (r *response) Write(p []byte) (n int, err error)func (r *response) WriteHeader(code int)addFastCGIEnvToContext reports whether to include the FastCGI environment variable s in the http.Request.Context, accessible via ProcessEnv.
func addFastCGIEnvToContext(s string) boolfunc (c *child) cleanUp()func (r *record) content() []bytefunc encodeSize(b []byte, size uint32) intfilterOutUsedEnvVars returns a new map of env vars without the variables in the given envVars map that are read for creating each http.Request
func filterOutUsedEnvVars(envVars map[string]string) map[string]stringfunc (c *child) handleRecord(rec *record) errorfunc (h *header) init(recType recType, reqId uint16, contentLength int)func newChild(rwc io.ReadWriteCloser, handler http.Handler) *childfunc newConn(rwc io.ReadWriteCloser) *connfunc newRequest(reqId uint16, flags uint8) *requestfunc newResponse(c *child, req *request) *responsefunc newWriter(c *conn, recType recType, reqId uint16) *bufWriterparseParams reads an encoded []byte into Params.
func (r *request) parseParams()func (rec *record) read(r io.Reader) (err error)func (br *beginRequest) read(content []byte) errorfunc readSize(s []byte) (uint32, int)func readString(s []byte, size uint32) stringfunc (c *child) serve()func (c *child) serveRequest(req *request, body io.ReadCloser)writeCGIHeader finalizes the header sent to the client and writes it to the output. 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.
func (r *response) writeCGIHeader(p []byte)func (c *conn) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) errorfunc (c *conn) writePairs(recType recType, reqId uint16, pairs map[string]string) errorwriteRecord writes and sends a single record.
func (c *conn) writeRecord(recType recType, reqId uint16, b []byte) errorGenerated with Arrow