コード例 #1
0
// Round trips the request to one of the upstreams, returns the streamed
// request body length in bytes and the upstream reply.
func (p *ReverseProxy) proxyRequest(
	w http.ResponseWriter, req *http.Request,
	cmd *command.Forward,
	endpoints []loadbalance.Endpoint) (int64, error) {

	// We are allowed to fallback in case of upstream failure,
	// record the request body so we can replay it on errors.
	body, err := netutils.NewBodyBuffer(req.Body)
	if err != nil {
		glog.Errorf("Request read error %s", err)
		return 0, netutils.NewHttpError(http.StatusBadRequest)
	}

	requestLength, err := body.TotalSize()
	if err != nil {
		glog.Errorf("Failed to read stored body length: %s", err)
		return 0, netutils.NewHttpError(http.StatusInternalServerError)
	}

	p.metrics.RequestBodySize.Update(requestLength)
	req.Body = body
	defer body.Close()

	for i := 0; i < len(endpoints); i++ {
		_, err := body.Seek(0, 0)
		if err != nil {
			return 0, err
		}
		endpoint, err := p.nextEndpoint(endpoints)
		if err != nil {
			glog.Errorf("Load Balancer failure: %s", err)
			return 0, err
		}
		glog.Infof("With failover, proxy to upstream: %s", endpoint.Upstream)
		err = p.proxyToUpstream(w, req, cmd, endpoint.Upstream)
		if err != nil {
			if cmd.Failover == nil || !cmd.Failover.Active {
				return 0, err
			}
			glog.Errorf("Upstream: %s error: %s, falling back to another", endpoint.Upstream, err)
			// Mark the endpoint as inactive for the next round of the load balance iteration
			endpoint.Active = false
		} else {
			return 0, nil
		}
	}
	glog.Errorf("All upstreams failed!")
	return requestLength, netutils.NewHttpError(http.StatusBadGateway)
}
コード例 #2
0
// Accepts requests, round trips it to the endpoint, and writes back the response.
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Record the request body so we can replay it on errors.
	body, err := netutils.NewBodyBuffer(r.Body)
	if err != nil || body == nil {
		log.Errorf("Request read error %s", err)
		if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
			p.replyError(errors.FromStatus(http.StatusRequestTimeout), w, r)
		} else {
			p.replyError(errors.FromStatus(http.StatusBadRequest), w, r)
		}
		return
	}
	defer body.Close()
	r.Body = body

	req := request.NewBaseRequest(r, atomic.AddInt64(&p.lastRequestId, 1), body)

	err = p.proxyRequest(w, req)
	if err != nil {
		log.Errorf("%s failed: %s", req, err)
		p.replyError(err, w, r)
	}
}
コード例 #3
0
ファイル: proxy.go プロジェクト: jbardin/vulcan
// Accepts requests, round trips it to the endpoint and writes backe the response.
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Record the request body so we can replay it on errors.
	body, err := netutils.NewBodyBuffer(r.Body)
	if err != nil || body == nil {
		log.Errorf("Request read error %s", err)
		p.replyError(errors.FromStatus(http.StatusBadRequest), w, r)
		return
	}
	defer body.Close()
	r.Body = body

	req := &request.BaseRequest{
		HttpRequest: r,
		Id:          atomic.AddInt64(&p.lastRequestId, 1),
		Body:        body,
	}

	err = p.proxyRequest(w, req)
	if err != nil {
		log.Errorf("%s failed: %s", req, err)
		p.replyError(err, w, r)
	}
}