// 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()) }