Esempio n. 1
0
func (s *Splitter) handleRequest(ctx context.Context, reqresp *httputils.RequestResponse) {
	log.Println("got request to split:", reqresp)
	if s.Config.WaitForResponse {
		log.Println("waiting for response")
		select {
		case <-ctx.Done():
			return
		case <-reqresp.Done():
		}
		log.Println("done waiting for response")
	}

	sinkResponses := make(chan *httputils.RequestResponse, len(s.Config.Sinks))
	responsesDone := make(chan struct{})
	wg := sync.WaitGroup{}

	ctx, _ = context.WithTimeout(ctx, time.Second*time.Duration(s.Config.SinkRequestTimeout))
	for _, sink := range s.Config.Sinks {
		wg.Add(1)
		req, err := httputils.CopyRequest(reqresp.Request)
		if err != nil {
			log.Println("failed to copy request:", err)
		}
		go func(sink config.Sink, req *http.Request) {
			defer wg.Done()
			sinkResponse, err := s.performSinkRequest(ctx, req, sink)
			if err != nil {
				log.Println("error performing request to", sink, "-", err)
				return
			}
			sinkResponses <- sinkResponse
		}(sink, req)
	}
	go func() {
		wg.Wait()
		close(responsesDone)
		close(sinkResponses)
	}()

	responses := []*httputils.RequestResponse{}
	select {
	case <-ctx.Done():
		log.Println("handleRequest: got cancellation signal")
	case <-responsesDone:
	}
	for response := range sinkResponses {
		responses = append(responses, response)
		log.Println("status:", response.Response.StatusCode())
	}

	// TODO(tmc): compare responses, record information
	log.Println(len(responses), "shadow requests performed")
}
Esempio n. 2
0
// ServeHTTP satisfies the net/http.Handler interface
func (s *Splitter) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
	teeRW := httputils.NewTeeResponseWriter(rw)

	r2, err := httputils.CopyRequest(r)

	// on request copy error attempt and early exit (which may be invalid, unfortunately)
	if err != nil {
		log.Println("splitter: error copying request:", err)
		s.upstreamProxy.ServeHTTP(teeRW, r)
		return
	}

	reqresp := httputils.NewRequestResponse(r2, teeRW)
	defer reqresp.MarkDone()

	select {
	case s.requests <- reqresp:
	default:
		log.Println("splitter: dropped request on the floor")
	}
	s.upstreamProxy.ServeHTTP(teeRW, r)
}