コード例 #1
0
ファイル: https.go プロジェクト: erkl/relay
func (p *Proxy) forward(req *heat.Request) (*heat.Response, error) {
	if req.Body != nil {
		defer req.Body.Close()
	}

	// Enable keep-alive connections for outgoing requests.
	isKeepAlive := !heat.Closing(req.Major, req.Minor, req.Fields)
	req.Fields.Set("Connection", "keep-alive")

	// Issue the request.
	resp, err := p.RoundTrip(req)
	if err != nil {
		return nil, err
	}

	// Does the client expect the connection to be closed?
	if !isKeepAlive {
		resp.Fields.Set("Connection", "close")
	} else {
		resp.Fields.Set("Connection", "keep-alive")
	}

	return resp, nil
}
コード例 #2
0
ファイル: https.go プロジェクト: erkl/relay
func (p *Proxy) serveHTTPS(conn net.Conn, addr string) error {
	rw := xo.NewReadWriter(
		xo.NewReader(conn, make([]byte, 4096)),
		xo.NewWriter(conn, make([]byte, 4096)),
	)

	for {
		req, body, err := readRequest(rw)
		if err != nil {
			switch err {
			case heat.ErrRequestHeader:
				resp := statusResponse(404, "Malformed HTTP request header.")
				return writeResponse(rw, resp, req.Method)

			case heat.ErrRequestVersion:
				resp := statusResponse(505, "Unsupported HTTP version number.")
				return writeResponse(rw, resp, req.Method)

			// If the connection terminated cleanly, stop.
			case io.EOF:
				return nil

			// Any other error would be from the underlying connection, and
			// should be propagated.
			default:
				return err
			}
		}

		// Populate the scheme and remote address.
		req.Scheme = "https"
		req.Remote = addr

		// Will the client close this connection after receiving a response?
		closing := heat.Closing(req.Major, req.Minor, req.Fields)

		// Forward the request to the upstream server.
		resp, err := p.forward(req)
		if err != nil {
			resp = statusResponse(500, "Round-trip to upstream failed: %s.", err)
		}

		// Are we closing the connection after sending the response?
		if !closing && (body == nil || body.LastError() == io.EOF) {
			resp.Fields.Set("Connection", "keep-alive")
		} else {
			resp.Fields.Set("Connection", "close")
			closing = true
		}

		// Write the response.
		err = writeResponse(rw, resp, req.Method)
		if err != nil {
			return err
		}

		// Stop if the connection isn't keep-alive.
		if closing {
			return nil
		}
	}
}
コード例 #3
0
ファイル: http.go プロジェクト: erkl/relay
func (p *Proxy) serveHTTP(conn net.Conn) error {
	rw := xo.NewReadWriter(
		xo.NewReader(conn, make([]byte, 4096)),
		xo.NewWriter(conn, make([]byte, 4096)),
	)

	for {
		// Read the next request.
		req, body, err := readRequest(rw)
		if err != nil {
			switch err {
			case heat.ErrRequestHeader:
				resp := statusResponse(404, "Malformed HTTP request header.")
				return writeResponse(rw, resp, req.Method)

			case heat.ErrRequestVersion:
				resp := statusResponse(505, "Unsupported HTTP version number.")
				return writeResponse(rw, resp, req.Method)

			// If the connection terminated cleanly, stop.
			case io.EOF:
				return nil

			// Any other error would be from the underlying connection, and
			// should be propagated.
			default:
				return err
			}
		}

		// Support CONNECT tunneling.
		if req.Method == "CONNECT" {
			return p.connect(conn, rw, req)
		}

		// Will the client close this connection after receiving a response?
		closing := heat.Closing(req.Major, req.Minor, req.Fields)

		// Fetch the actual response from the upstream server.
		resp, err := p.proxy(req)
		if err != nil {
			resp := statusResponse(500, "Unknown error: %s.", err)
			return writeResponse(rw, resp, req.Method)
		}

		// Are we closing the connection after sending the response?
		if !closing && (body == nil || body.LastError() == io.EOF) {
			resp.Fields.Set("Connection", "keep-alive")
		} else {
			resp.Fields.Set("Connection", "close")
			closing = true
		}

		// Write the response.
		err = writeResponse(rw, resp, req.Method)
		if err != nil {
			return err
		}

		// Stop if the connection isn't keep-alive.
		if closing {
			return nil
		}
	}
}