func (u *Upstream) FilterRequest(request *falcore.Request) (res *http.Response) { var err error req := request.HttpRequest // Force the upstream to use http if u.ForceHttp || req.URL.Scheme == "" { req.URL.Scheme = "http" req.URL.Host = req.Host } before := time.Now() req.Header.Set("Connection", "Keep-Alive") if u.tcpconn != nil { u.tcpconn.SetDeadline(time.Now().Add(u.Timeout)) } res, err = u.transport.RoundTrip(req) diff := falcore.TimeDiff(before, time.Now()) if err != nil { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { falcore.Error("%s Upstream Timeout error: %v", request.ID, err) res = falcore.SimpleResponse(req, 504, nil, "Gateway Timeout\n") request.CurrentStage.Status = 2 // Fail } else { falcore.Error("%s Upstream error: %v", request.ID, err) res = falcore.SimpleResponse(req, 502, nil, "Bad Gateway\n") request.CurrentStage.Status = 2 // Fail } } falcore.Debug("%s [%s] [%s] %s s=%d Time=%.4f", request.ID, req.Method, u.host, req.URL, res.StatusCode, diff) return }
func (u *Upstream) FilterRequest(request *falcore.Request) (res *http.Response) { var err error req := request.HttpRequest // Force the upstream to use http if u.ForceHttp || req.URL.Scheme == "" { req.URL.Scheme = "http" req.URL.Host = req.Host } before := time.Now() req.Header.Set("Connection", "Keep-Alive") if u.tcpconn != nil { u.tcpconn.SetDeadline(time.Now().Add(u.Timeout)) } var upstrRes *http.Response upstrRes, err = u.transport.RoundTrip(req) diff := falcore.TimeDiff(before, time.Now()) if err == nil { // Copy response over to new record. Remove connection noise. Add some sanity. res = falcore.SimpleResponse(req, upstrRes.StatusCode, nil, "") if upstrRes.ContentLength > 0 && upstrRes.Body != nil { res.ContentLength = upstrRes.ContentLength res.Body = upstrRes.Body } else if upstrRes.ContentLength == 0 && upstrRes.Body != nil { // Any bytes? var testBuf [1]byte n, _ := io.ReadFull(upstrRes.Body, testBuf[:]) if n == 1 { // Yes there are. Chunked it is. res.TransferEncoding = []string{"chunked"} res.ContentLength = -1 rc := &passThruReadCloser{ io.MultiReader(bytes.NewBuffer(testBuf[:]), upstrRes.Body), upstrRes.Body, } res.Body = rc } } else if upstrRes.Body != nil { res.Body = upstrRes.Body res.ContentLength = -1 res.TransferEncoding = []string{"chunked"} } // Copy over headers with a few exceptions res.Header = make(http.Header) for hn, hv := range upstrRes.Header { switch hn { case "Content-Length": case "Connection": case "Transfer-Encoding": default: res.Header[hn] = hv } } } else { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { falcore.Error("%s Upstream Timeout error: %v", request.ID, err) res = falcore.SimpleResponse(req, 504, nil, "Gateway Timeout\n") request.CurrentStage.Status = 2 // Fail } else { falcore.Error("%s Upstream error: %v", request.ID, err) res = falcore.SimpleResponse(req, 502, nil, "Bad Gateway\n") request.CurrentStage.Status = 2 // Fail } } falcore.Debug("%s [%s] [%s] %s s=%d Time=%.4f", request.ID, req.Method, u.host, req.URL, res.StatusCode, diff) return }