func (u *Upstream) FilterRequest(request *falcore.Request) (res *http.Response) { var err error req := request.HttpRequest if u.Name != "" { request.CurrentStage.Name = fmt.Sprintf("%s[%s]", request.CurrentStage.Name, u.Name) } // Throttle // Wait for an opening, then increment in flight counter u.throttleC.L.Lock() u.throttleQueue += 1 for u.throttleMax > 0 && u.throttleInFlight >= u.throttleMax { u.throttleC.Wait() } u.throttleQueue -= 1 u.throttleInFlight += 1 u.throttleC.L.Unlock() // Decrement and signal when done defer func() { u.throttleC.L.Lock() u.throttleInFlight -= 1 u.throttleC.Signal() u.throttleC.L.Unlock() }() // 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") var upstrRes *http.Response upstrRes, err = u.Transport.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.StringResponse(req, upstrRes.StatusCode, nil, "") if upstrRes.ContentLength > 0 { res.ContentLength = upstrRes.ContentLength res.Body = upstrRes.Body } else if res.ContentLength == -1 { res.Body = upstrRes.Body res.ContentLength = -1 res.TransferEncoding = []string{"chunked"} } else { // 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 { // There was an error reading the body upstrRes.Body.Close() res.ContentLength = 0 res.Body = nil } } // 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 [%s] Upstream Timeout error: %v", request.ID, u.Name, err) res = falcore.StringResponse(req, 504, nil, "Gateway Timeout\n") request.CurrentStage.Status = 2 // Fail } else { falcore.Error("%s [%s] Upstream error: %v", request.ID, u.Name, err) res = falcore.StringResponse(req, 502, nil, "Bad Gateway\n") request.CurrentStage.Status = 2 // Fail } } falcore.Debug("%s %s [%s] [%s] %s s=%d Time=%.4f", request.ID, u.Name, req.Method, u.Transport.host, req.URL, res.StatusCode, diff) return }
log.Fatal("could not read response when adding push service provider for apple push notifications: " + string(uniqushError.Error())) } else if uniqushResponseBody[0:30] != "[AddPushServiceProvider][Info]" { log.Fatal("invalid response when adding push service provider for apple push notifications: " + uniqushResponseBody) } else { fmt.Println("added push service provider for apple push notifications. usingSandbox:" + usingSandbox + ", uniqush response:" + uniqushResponseBody) } } } // print detailed stats about the request to the log and push stats data to graphite. // runs as separate goroutine, based on falcore.request.go:Trace() // falcore docs say this is a big hit on performance and should only be used for debugging or development. var completionCallback = func(falcoreRequest *falcore.Request, response *http.Response) { go func() { Statsd, statsdError := g2s.Dial("udp", "localhost:8125") requestTimeDiff := falcore.TimeDiff(falcoreRequest.StartTime, falcoreRequest.EndTime) httpRequest := falcoreRequest.HttpRequest // stats for the whole request falcore.Trace("%s [%s] %s%s S=%v Sig=%s Tot=%.4fs", falcoreRequest.ID, httpRequest.Method, httpRequest.Host, httpRequest.URL, response.StatusCode, falcoreRequest.Signature(), requestTimeDiff) if statsdError == nil { Statsd.Timing(1.0, "api.request-time", falcoreRequest.EndTime.Sub(falcoreRequest.StartTime)) } // stats for each pipeline stage stages := falcoreRequest.PipelineStageStats for stage := stages.Front(); stage != nil; stage = stage.Next() { pipelineStageStats, _ := stage.Value.(*falcore.PipelineStageStat) stageTimeDiff := falcore.TimeDiff(pipelineStageStats.StartTime, pipelineStageStats.EndTime) falcore.Trace("%s [%s]%-30s S=%2d Tot=%.4fs %%=%.2f", falcoreRequest.ID, pipelineStageStats.Type, pipelineStageStats.Name, pipelineStageStats.Status, stageTimeDiff, stageTimeDiff/(requestTimeDiff*100.0))