func (c *child) serveRequest(req *request, body io.ReadCloser) { r := newResponse(c, req) httpReq, err := cgi.RequestFromMap(req.params) // 根据参数构建http请求 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) } r.Close() c.mu.Lock() delete(c.requests, req.reqId) c.mu.Unlock() 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() } }
func RequestHandler(env *map[string]string, wsgi_req *interface{}) { httpReq, err := cgi.RequestFromMap(*env) if err == nil { httpReq.Body = &BodyReader{wsgi_req} w := ResponseWriter{httpReq, wsgi_req, http.Header{}, false} http.DefaultServeMux.ServeHTTP(&w, httpReq) } }
//export uwsgi_go_helper_request func uwsgi_go_helper_request(env *map[string]string, wsgi_req *C.struct_wsgi_request) { httpReq, err := cgi.RequestFromMap(*env) if err != nil { } else { httpReq.Body = &BodyReader{wsgi_req} w := ResponseWriter{httpReq, wsgi_req, http.Header{}, false} if uwsgi_default_request_handler != nil { uwsgi_default_request_handler(&w, httpReq) } else if uwsgi_default_handler != nil { uwsgi_default_handler.ServeHTTP(&w, httpReq) } else { http.DefaultServeMux.ServeHTTP(&w, httpReq) } } }
func (s *Server) readScgiRequest(fd io.ReadWriteCloser) (*http.Request, error) { reader := bufio.NewReader(fd) line, err := reader.ReadString(':') if err != nil { return nil, err } length, err := strconv.Atoi(line[0 : len(line)-1]) if err != nil { return nil, err } if length > 16384 { return nil, errors.New("Max header size is 16k") } headerData := make([]byte, length) _, err = reader.Read(headerData) if err != nil { return nil, err } b, err := reader.ReadByte() if err != nil { return nil, err } // discard the trailing comma if b != ',' { return nil, errors.New("SCGI protocol error: missing comma") } headerList := bytes.Split(headerData, []byte{0}) headers := map[string]string{} for i := 0; i < len(headerList)-1; i += 2 { headers[string(headerList[i])] = string(headerList[i+1]) } httpReq, err := cgi.RequestFromMap(headers) if err != nil { return nil, err } if httpReq.ContentLength > 0 { httpReq.Body = &scgiBody{ reader: io.LimitReader(reader, httpReq.ContentLength), conn: fd, } } else { httpReq.Body = &scgiBody{reader: reader, conn: fd} } return httpReq, nil }
func readScgiRequest(buf *bytes.Buffer) (*http.Request, error) { headers := map[string]string{} data := buf.Bytes() var clen int colon := bytes.IndexByte(data, ':') data = data[colon+1:] var err error //find the CONTENT_LENGTH clfields := bytes.SplitN(data, []byte{0}, 3) if len(clfields) != 3 { return nil, errors.New("Invalid SCGI Request -- no fields") } clfields = clfields[0:2] if string(clfields[0]) != "CONTENT_LENGTH" { return nil, errors.New("Invalid SCGI Request -- expecting CONTENT_LENGTH") } if clen, err = strconv.Atoi(string(clfields[1])); err != nil { return nil, errors.New("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.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() } }
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 == io.EOF { break } if err != nil { s.Logger.Println("FCGI Error", err.Error()) break } content := make([]byte, h.ContentLength) _, err = io.ReadFull(br, content) if err != nil { s.Logger.Println("FCGI Error", err.Error()) 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.Error()) 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: } } }