// Proxy the request to the given endpoint, execute observers and middlewares chains func (l *HttpLocation) proxyToEndpoint(tr *http.Transport, o *Options, endpoint endpoint.Endpoint, req request.Request) (*http.Response, error) { a := &request.BaseAttempt{Endpoint: endpoint} l.observerChain.ObserveRequest(req) defer l.observerChain.ObserveResponse(req, a) defer req.AddAttempt(a) it := l.middlewareChain.GetIter() defer l.unwindIter(it, req, a) for v := it.Next(); v != nil; v = it.Next() { a.Response, a.Error = v.ProcessRequest(req) if a.Response != nil || a.Error != nil { // Move the iterator forward to count it again once we unwind the chain it.Next() log.Errorf("Midleware intercepted request with response=%v, error=%v", a.Response, a.Error) return a.Response, a.Error } } // Forward the request and mirror the response start := o.TimeProvider.UtcNow() re, err := tr.RoundTrip(req.GetHttpRequest()) // Read the response as soon as we can, this will allow to release a connection to the pool a.Response, a.Error = readResponse(&o.Limits, re, err) a.Duration = o.TimeProvider.UtcNow().Sub(start) return a.Response, a.Error }