Exemple #1
0
// RequestHandle servers the purge page.
func (ph *Handler) RequestHandle(ctx context.Context, w http.ResponseWriter, r *http.Request) {
	//!TODO authentication
	if r.Method != "POST" {
		httputils.Error(w, http.StatusMethodNotAllowed)
		return
	}

	var pr = new(purgeRequest)
	if err := json.NewDecoder(r.Body).Decode(pr); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		ph.logger.Errorf("[%p] error on parsing request %s", ph, err)
		return
	}

	var app, ok = contexts.GetApp(ctx)
	if !ok {
		httputils.Error(w, http.StatusInternalServerError)
		ph.logger.Errorf("[%p] no app in context", ph)
		return
	}
	var res, err = ph.purgeAll(app, *pr)
	if err != nil {
		httputils.Error(w, http.StatusInternalServerError)
		// previosly logged
		return
	}
	if err := json.NewEncoder(w).Encode(res); err != nil {
		ph.logger.Errorf(
			"[%p] error while encoding response %s", ph, err)
	}
}
func (p *ReverseProxy) ServeHTTP(ctx context.Context, rw http.ResponseWriter, req *http.Request) {
	var upstream = p.defaultUpstream
	res, err := p.doRequestFor(rw, req, upstream)
	if err != nil {
		p.Logger.Logf("[%p] Proxy error: %v", req, err)
		httputils.Error(rw, http.StatusInternalServerError)
		return
	}
	if newUpstream, ok := p.CodesToRetry[res.StatusCode]; ok {
		upstream = getUpstreamFromContext(ctx, newUpstream)
		if upstream != nil {
			if err = res.Body.Close(); err != nil {
				p.Logger.Logf("[%p] Proxy error on closing response which will be retried: %v", req, err)
			}

			res, err = p.doRequestFor(rw, req, upstream)
			if err != nil {
				p.Logger.Logf("[%p] Proxy error: %v", req, err)
				httputils.Error(rw, http.StatusInternalServerError)
				return
			}
		} else {
			p.Logger.Errorf("[%p] Proxy was configured to retry on code %d with upstream %s but no such upstream exist",
				req, res.StatusCode, newUpstream)
		}
	}

	for _, h := range hopHeaders {
		res.Header.Del(h)
	}

	httputils.CopyHeaders(res.Header, rw.Header())

	// The "Trailer" header isn't included in the Transport's response,
	// at least for *http.Transport. Build it up from Trailer.
	if len(res.Trailer) > 0 {
		var trailerKeys []string
		for k := range res.Trailer {
			trailerKeys = append(trailerKeys, k)
		}
		rw.Header().Add("Trailer", strings.Join(trailerKeys, ", "))
	}

	rw.WriteHeader(res.StatusCode)
	if len(res.Trailer) > 0 {
		// Force chunking if we saw a response trailer.
		// This prevents net/http from calculating the length for short
		// bodies and adding a Content-Length.
		if fl, ok := rw.(http.Flusher); ok {
			fl.Flush()
		}
	}
	if _, err := io.Copy(rw, res.Body); err != nil {
		p.Logger.Logf("[%p] Proxy error during copying: %v", req, err)
	}

	// Close now, instead of defer, to populate res.Trailer
	if err := res.Body.Close(); err != nil {
		p.Logger.Errorf("[%p] Proxy error during response close: %v", req, err)
	}
	httputils.CopyHeaders(res.Trailer, rw.Header())
}