// ServeHTTP implements the middleware.Handler interface. func (rd Redirect) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { for _, rule := range rd.Rules { if rule.From == "/" || r.URL.Path == rule.From { to := middleware.NewReplacer(r, nil, "").Replace(rule.To) if rule.Meta { safeTo := html.EscapeString(to) fmt.Fprintf(w, metaRedir, safeTo, safeTo) } else { http.Redirect(w, r, to, rule.Code) } return 0, nil } } return rd.Next.ServeHTTP(w, r) }
func (l Logger) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { for _, rule := range l.Rules { if middleware.Path(r.URL.Path).Matches(rule.PathScope) { responseRecorder := middleware.NewResponseRecorder(w) status, err := l.Next.ServeHTTP(responseRecorder, r) if status >= 400 { // There was an error up the chain, but no response has been written yet. // The error must be handled here so the log entry will record the response size. if l.ErrorFunc != nil { l.ErrorFunc(responseRecorder, r, status) } else { // Default failover error handler responseRecorder.WriteHeader(status) fmt.Fprintf(responseRecorder, "%d %s", status, http.StatusText(status)) } status = 0 } rep := middleware.NewReplacer(r, responseRecorder, CommonLogEmptyValue) rule.Log.Println(rep.Replace(rule.Format)) return status, err } } return l.Next.ServeHTTP(w, r) }
// ServeHTTP satisfies the middleware.Handler interface. func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { for _, upstream := range p.Upstreams { if middleware.Path(r.URL.Path).Matches(upstream.From()) { var replacer middleware.Replacer start := time.Now() requestHost := r.Host // Since Select() should give us "up" hosts, keep retrying // hosts until timeout (or until we get a nil host). for time.Now().Sub(start) < (60 * time.Second) { host := upstream.Select() if host == nil { return http.StatusBadGateway, errUnreachable } proxy := host.ReverseProxy r.Host = host.Name if baseURL, err := url.Parse(host.Name); err == nil { r.Host = baseURL.Host if proxy == nil { proxy = NewSingleHostReverseProxy(baseURL, host.WithoutPathPrefix) } } else if proxy == nil { return http.StatusInternalServerError, err } var extraHeaders http.Header if host.ExtraHeaders != nil { extraHeaders = make(http.Header) if replacer == nil { rHost := r.Host r.Host = requestHost replacer = middleware.NewReplacer(r, nil, "") r.Host = rHost } for header, values := range host.ExtraHeaders { for _, value := range values { extraHeaders.Add(header, replacer.Replace(value)) if header == "Host" { r.Host = replacer.Replace(value) } } } } atomic.AddInt64(&host.Conns, 1) backendErr := proxy.ServeHTTP(w, r, extraHeaders) atomic.AddInt64(&host.Conns, -1) if backendErr == nil { return 0, nil } timeout := host.FailTimeout if timeout == 0 { timeout = 10 * time.Second } atomic.AddInt32(&host.Fails, 1) go func(host *UpstreamHost, timeout time.Duration) { time.Sleep(timeout) atomic.AddInt32(&host.Fails, -1) }(host, timeout) } return http.StatusBadGateway, errUnreachable } } return p.Next.ServeHTTP(w, r) }