child.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package fcgi
  5. // This file implements FastCGI from the perspective of a child process.
  6. import (
  7. "context"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "net"
  12. "net/http"
  13. "net/http/cgi"
  14. "os"
  15. "strings"
  16. "time"
  17. )
  18. // request holds the state for an in-progress request. As soon as it's complete,
  19. // it's converted to an http.Request.
  20. type request struct {
  21. pw *io.PipeWriter
  22. reqId uint16
  23. params map[string]string
  24. buf [1024]byte
  25. rawParams []byte
  26. keepConn bool
  27. }
  28. // envVarsContextKey uniquely identifies a mapping of CGI
  29. // environment variables to their values in a request context
  30. type envVarsContextKey struct{}
  31. func newRequest(reqId uint16, flags uint8) *request {
  32. r := &request{
  33. reqId: reqId,
  34. params: map[string]string{},
  35. keepConn: flags&flagKeepConn != 0,
  36. }
  37. r.rawParams = r.buf[:0]
  38. return r
  39. }
  40. // parseParams reads an encoded []byte into Params.
  41. func (r *request) parseParams() {
  42. text := r.rawParams
  43. r.rawParams = nil
  44. for len(text) > 0 {
  45. keyLen, n := readSize(text)
  46. if n == 0 {
  47. return
  48. }
  49. text = text[n:]
  50. valLen, n := readSize(text)
  51. if n == 0 {
  52. return
  53. }
  54. text = text[n:]
  55. if int(keyLen)+int(valLen) > len(text) {
  56. return
  57. }
  58. key := readString(text, keyLen)
  59. text = text[keyLen:]
  60. val := readString(text, valLen)
  61. text = text[valLen:]
  62. r.params[key] = val
  63. }
  64. }
  65. // response implements http.ResponseWriter.
  66. type response struct {
  67. req *request
  68. header http.Header
  69. code int
  70. wroteHeader bool
  71. wroteCGIHeader bool
  72. w *bufWriter
  73. }
  74. func newResponse(c *child, req *request) *response {
  75. return &response{
  76. req: req,
  77. header: http.Header{},
  78. w: newWriter(c.conn, typeStdout, req.reqId),
  79. }
  80. }
  81. func (r *response) Header() http.Header {
  82. return r.header
  83. }
  84. func (r *response) Write(p []byte) (n int, err error) {
  85. if !r.wroteHeader {
  86. r.WriteHeader(http.StatusOK)
  87. }
  88. if !r.wroteCGIHeader {
  89. r.writeCGIHeader(p)
  90. }
  91. return r.w.Write(p)
  92. }
  93. func (r *response) WriteHeader(code int) {
  94. if r.wroteHeader {
  95. return
  96. }
  97. r.wroteHeader = true
  98. r.code = code
  99. if code == http.StatusNotModified {
  100. // Must not have body.
  101. r.header.Del("Content-Type")
  102. r.header.Del("Content-Length")
  103. r.header.Del("Transfer-Encoding")
  104. }
  105. if r.header.Get("Date") == "" {
  106. r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
  107. }
  108. }
  109. // writeCGIHeader finalizes the header sent to the client and writes it to the output.
  110. // p is not written by writeHeader, but is the first chunk of the body
  111. // that will be written. It is sniffed for a Content-Type if none is
  112. // set explicitly.
  113. func (r *response) writeCGIHeader(p []byte) {
  114. if r.wroteCGIHeader {
  115. return
  116. }
  117. r.wroteCGIHeader = true
  118. fmt.Fprintf(r.w, "Status: %d %s\r\n", r.code, http.StatusText(r.code))
  119. if _, hasType := r.header["Content-Type"]; r.code != http.StatusNotModified && !hasType {
  120. r.header.Set("Content-Type", http.DetectContentType(p))
  121. }
  122. r.header.Write(r.w)
  123. r.w.WriteString("\r\n")
  124. r.w.Flush()
  125. }
  126. func (r *response) Flush() {
  127. if !r.wroteHeader {
  128. r.WriteHeader(http.StatusOK)
  129. }
  130. r.w.Flush()
  131. }
  132. func (r *response) Close() error {
  133. r.Flush()
  134. return r.w.Close()
  135. }
  136. type child struct {
  137. conn *conn
  138. handler http.Handler
  139. requests map[uint16]*request // keyed by request ID
  140. }
  141. func newChild(rwc io.ReadWriteCloser, handler http.Handler) *child {
  142. return &child{
  143. conn: newConn(rwc),
  144. handler: handler,
  145. requests: make(map[uint16]*request),
  146. }
  147. }
  148. func (c *child) serve() {
  149. defer c.conn.Close()
  150. defer c.cleanUp()
  151. var rec record
  152. for {
  153. if err := rec.read(c.conn.rwc); err != nil {
  154. return
  155. }
  156. if err := c.handleRecord(&rec); err != nil {
  157. return
  158. }
  159. }
  160. }
  161. var errCloseConn = errors.New("fcgi: connection should be closed")
  162. var emptyBody = io.NopCloser(strings.NewReader(""))
  163. // ErrRequestAborted is returned by Read when a handler attempts to read the
  164. // body of a request that has been aborted by the web server.
  165. var ErrRequestAborted = errors.New("fcgi: request aborted by web server")
  166. // ErrConnClosed is returned by Read when a handler attempts to read the body of
  167. // a request after the connection to the web server has been closed.
  168. var ErrConnClosed = errors.New("fcgi: connection to web server closed")
  169. func (c *child) handleRecord(rec *record) error {
  170. req, ok := c.requests[rec.h.Id]
  171. if !ok && rec.h.Type != typeBeginRequest && rec.h.Type != typeGetValues {
  172. // The spec says to ignore unknown request IDs.
  173. return nil
  174. }
  175. switch rec.h.Type {
  176. case typeBeginRequest:
  177. if req != nil {
  178. // The server is trying to begin a request with the same ID
  179. // as an in-progress request. This is an error.
  180. return errors.New("fcgi: received ID that is already in-flight")
  181. }
  182. var br beginRequest
  183. if err := br.read(rec.content()); err != nil {
  184. return err
  185. }
  186. if br.role != roleResponder {
  187. c.conn.writeEndRequest(rec.h.Id, 0, statusUnknownRole)
  188. return nil
  189. }
  190. req = newRequest(rec.h.Id, br.flags)
  191. c.requests[rec.h.Id] = req
  192. return nil
  193. case typeParams:
  194. // NOTE(eds): Technically a key-value pair can straddle the boundary
  195. // between two packets. We buffer until we've received all parameters.
  196. if len(rec.content()) > 0 {
  197. req.rawParams = append(req.rawParams, rec.content()...)
  198. return nil
  199. }
  200. req.parseParams()
  201. return nil
  202. case typeStdin:
  203. content := rec.content()
  204. if req.pw == nil {
  205. var body io.ReadCloser
  206. if len(content) > 0 {
  207. // body could be an io.LimitReader, but it shouldn't matter
  208. // as long as both sides are behaving.
  209. body, req.pw = io.Pipe()
  210. } else {
  211. body = emptyBody
  212. }
  213. go c.serveRequest(req, body)
  214. }
  215. if len(content) > 0 {
  216. // TODO(eds): This blocks until the handler reads from the pipe.
  217. // If the handler takes a long time, it might be a problem.
  218. req.pw.Write(content)
  219. } else {
  220. delete(c.requests, req.reqId)
  221. if req.pw != nil {
  222. req.pw.Close()
  223. }
  224. }
  225. return nil
  226. case typeGetValues:
  227. values := map[string]string{"FCGI_MPXS_CONNS": "1"}
  228. c.conn.writePairs(typeGetValuesResult, 0, values)
  229. return nil
  230. case typeData:
  231. // If the filter role is implemented, read the data stream here.
  232. return nil
  233. case typeAbortRequest:
  234. delete(c.requests, rec.h.Id)
  235. c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
  236. if req.pw != nil {
  237. req.pw.CloseWithError(ErrRequestAborted)
  238. }
  239. if !req.keepConn {
  240. // connection will close upon return
  241. return errCloseConn
  242. }
  243. return nil
  244. default:
  245. b := make([]byte, 8)
  246. b[0] = byte(rec.h.Type)
  247. c.conn.writeRecord(typeUnknownType, 0, b)
  248. return nil
  249. }
  250. }
  251. // filterOutUsedEnvVars returns a new map of env vars without the
  252. // variables in the given envVars map that are read for creating each http.Request
  253. func filterOutUsedEnvVars(envVars map[string]string) map[string]string {
  254. withoutUsedEnvVars := make(map[string]string)
  255. for k, v := range envVars {
  256. if addFastCGIEnvToContext(k) {
  257. withoutUsedEnvVars[k] = v
  258. }
  259. }
  260. return withoutUsedEnvVars
  261. }
  262. func (c *child) serveRequest(req *request, body io.ReadCloser) {
  263. r := newResponse(c, req)
  264. httpReq, err := cgi.RequestFromMap(req.params)
  265. if err != nil {
  266. // there was an error reading the request
  267. r.WriteHeader(http.StatusInternalServerError)
  268. c.conn.writeRecord(typeStderr, req.reqId, []byte(err.Error()))
  269. } else {
  270. httpReq.Body = body
  271. withoutUsedEnvVars := filterOutUsedEnvVars(req.params)
  272. envVarCtx := context.WithValue(httpReq.Context(), envVarsContextKey{}, withoutUsedEnvVars)
  273. httpReq = httpReq.WithContext(envVarCtx)
  274. c.handler.ServeHTTP(r, httpReq)
  275. }
  276. // Make sure we serve something even if nothing was written to r
  277. r.Write(nil)
  278. r.Close()
  279. c.conn.writeEndRequest(req.reqId, 0, statusRequestComplete)
  280. // Consume the entire body, so the host isn't still writing to
  281. // us when we close the socket below in the !keepConn case,
  282. // otherwise we'd send a RST. (golang.org/issue/4183)
  283. // TODO(bradfitz): also bound this copy in time. Or send
  284. // some sort of abort request to the host, so the host
  285. // can properly cut off the client sending all the data.
  286. // For now just bound it a little and
  287. io.CopyN(io.Discard, body, 100<<20)
  288. body.Close()
  289. if !req.keepConn {
  290. c.conn.Close()
  291. }
  292. }
  293. func (c *child) cleanUp() {
  294. for _, req := range c.requests {
  295. if req.pw != nil {
  296. // race with call to Close in c.serveRequest doesn't matter because
  297. // Pipe(Reader|Writer).Close are idempotent
  298. req.pw.CloseWithError(ErrConnClosed)
  299. }
  300. }
  301. }
  302. // Serve accepts incoming FastCGI connections on the listener l, creating a new
  303. // goroutine for each. The goroutine reads requests and then calls handler
  304. // to reply to them.
  305. // If l is nil, Serve accepts connections from os.Stdin.
  306. // If handler is nil, http.DefaultServeMux is used.
  307. func Serve(l net.Listener, handler http.Handler) error {
  308. if l == nil {
  309. var err error
  310. l, err = net.FileListener(os.Stdin)
  311. if err != nil {
  312. return err
  313. }
  314. defer l.Close()
  315. }
  316. if handler == nil {
  317. handler = http.DefaultServeMux
  318. }
  319. for {
  320. rw, err := l.Accept()
  321. if err != nil {
  322. return err
  323. }
  324. c := newChild(rw, handler)
  325. go c.serve()
  326. }
  327. }
  328. // ProcessEnv returns FastCGI environment variables associated with the request r
  329. // for which no effort was made to be included in the request itself - the data
  330. // is hidden in the request's context. As an example, if REMOTE_USER is set for a
  331. // request, it will not be found anywhere in r, but it will be included in
  332. // ProcessEnv's response (via r's context).
  333. func ProcessEnv(r *http.Request) map[string]string {
  334. env, _ := r.Context().Value(envVarsContextKey{}).(map[string]string)
  335. return env
  336. }
  337. // addFastCGIEnvToContext reports whether to include the FastCGI environment variable s
  338. // in the http.Request.Context, accessible via ProcessEnv.
  339. func addFastCGIEnvToContext(s string) bool {
  340. // Exclude things supported by net/http natively:
  341. switch s {
  342. case "CONTENT_LENGTH", "CONTENT_TYPE", "HTTPS",
  343. "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR",
  344. "REMOTE_HOST", "REMOTE_PORT", "REQUEST_METHOD",
  345. "REQUEST_URI", "SCRIPT_NAME", "SERVER_PROTOCOL":
  346. return false
  347. }
  348. if strings.HasPrefix(s, "HTTP_") {
  349. return false
  350. }
  351. // Explicitly include FastCGI-specific things.
  352. // This list is redundant with the default "return true" below.
  353. // Consider this documentation of the sorts of things we expect
  354. // to maybe see.
  355. switch s {
  356. case "REMOTE_USER":
  357. return true
  358. }
  359. // Unknown, so include it to be safe.
  360. return true
  361. }