Esempio n. 1
0
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
}
Esempio n. 2
0
			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))