func readScgiRequest(buf *bytes.Buffer) (*http.Request, os.Error) { headers := map[string]string{} data := buf.Bytes() var clen int colon := bytes.IndexByte(data, ':') data = data[colon+1:] var err os.Error //find the CONTENT_LENGTH clfields := bytes.SplitN(data, []byte{0}, 3) if len(clfields) != 3 { return nil, os.NewError("Invalid SCGI Request -- no fields") } clfields = clfields[0:2] if string(clfields[0]) != "CONTENT_LENGTH" { return nil, os.NewError("Invalid SCGI Request -- expecting CONTENT_LENGTH") } if clen, err = strconv.Atoi(string(clfields[1])); err != nil { return nil, os.NewError("Invalid SCGI Request -- invalid CONTENT_LENGTH field") } content := data[len(data)-clen:] fields := bytes.Split(data[0:len(data)-clen], []byte{0}) for i := 0; i < len(fields)-1; i += 2 { key := string(fields[i]) value := string(fields[i+1]) headers[key] = value } body := bytes.NewBuffer(content) req, _ := cgi.RequestFromMap(headers) req.Body = ioutil.NopCloser(body) return req, 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.String())) } 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() } }
func (s *Server) handleFcgiConnection(fd io.ReadWriteCloser) { br := bufio.NewReader(fd) var req *http.Request var fc *fcgiConn var body bytes.Buffer headers := map[string]string{} for { var h fcgiHeader err := binary.Read(br, binary.BigEndian, &h) if err == os.EOF { break } if err != nil { s.Logger.Println("FCGI Error", err.String()) break } content := make([]byte, h.ContentLength) _, err = io.ReadFull(br, content) if err != nil { s.Logger.Println("FCGI Error", err.String()) break } //read padding if h.PaddingLength > 0 { padding := make([]byte, h.PaddingLength) _, err = io.ReadFull(br, padding) if err != nil { s.Logger.Println("FCGI Error", err.String()) break } } switch h.Type { case fcgiBeginRequest: fc = &fcgiConn{h.RequestId, req, fd, make(map[string][]string), false} case fcgiParams: if h.ContentLength > 0 { readFcgiParams(content, headers) } case fcgiStdin: if h.ContentLength > 0 { body.Write(content) } else if h.ContentLength == 0 { req, _ = cgi.RequestFromMap(headers) req.Body = ioutil.NopCloser(&body) fc.req = req s.routeHandler(req, fc) //we close the connection after processing //TODO: is there a way to keep it open for future requests? fc.complete() return } case fcgiData: if h.ContentLength > 0 { body.Write(content) } case fcgiAbortRequest: } } }