// Round trips the request to the selected location and writes back the response func (p *Proxy) proxyRequest(w http.ResponseWriter, r *http.Request) error { // Create a unique request with sequential ids that will be passed to all interfaces. req := request.NewBaseRequest(r, atomic.AddInt64(&p.lastRequestId, 1), nil) location, err := p.router.Route(req) if err != nil { return err } // Router could not find a matching location, we can do nothing else. if location == nil { log.Errorf("%s failed to route", req) return errors.FromStatus(http.StatusBadGateway) } response, err := location.RoundTrip(req) if response != nil { netutils.CopyHeaders(w.Header(), response.Header) w.WriteHeader(response.StatusCode) io.Copy(w, response.Body) response.Body.Close() return nil } else { return err } }
func makeRequest(o O) *request.BaseRequest { req := request.NewBaseRequest(&http.Request{URL: &url.URL{}}, o.id, nil) if o.noAttempts { return req } req.SetUserData(cbreakerMetrics, o.stats) req.Attempts = []request.Attempt{ &request.BaseAttempt{}, } return req }
// 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) } }