Exemple #1
0
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
}
Exemple #2
0
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()
	}
}
Exemple #3
0
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:
		}
	}
}