func (m *Middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { start := time.Now() next(rw, r) res := negroni.NewResponseWriter(rw) m.reqs.WithLabelValues(http.StatusText(res.Status()), r.Method, r.URL.Path).Inc() m.latency.WithLabelValues(http.StatusText(res.Status()), r.Method, r.URL.Path).Observe(float64(time.Since(start).Nanoseconds()) / 1000000) }
// ServeHTTP wraps the http.ResponseWriter with a gzip.Writer. func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { // Skip compression if the client doesn't accept gzip encoding. if !strings.Contains(r.Header.Get(headerAcceptEncoding), encodingGzip) { next(w, r) return } // Skip compression if client attempt WebSocket connection if len(r.Header.Get(headerSecWebSocketKey)) > 0 { next(w, r) return } // Skip compression if already compressed if w.Header().Get(headerContentEncoding) == encodingGzip { next(w, r) return } // Retrieve gzip writer from the pool. Reset it to use the ResponseWriter. // This allows us to re-use an already allocated buffer rather than // allocating a new buffer for every request. // We defer g.pool.Put here so that the gz writer is returned to the // pool if any thing after here fails for some reason (functions in // next could potentially panic, etc) gz := h.pool.Get().(*gzip.Writer) defer h.pool.Put(gz) gz.Reset(w) // Set the appropriate gzip headers. headers := w.Header() headers.Set(headerContentEncoding, encodingGzip) headers.Set(headerVary, headerAcceptEncoding) // Wrap the original http.ResponseWriter with negroni.ResponseWriter // and create the gzipResponseWriter. nrw := negroni.NewResponseWriter(w) grw := gzipResponseWriter{ gz, nrw, } // Call the next handler supplying the gzipResponseWriter instead of // the original. next(grw, r) // Delete the content length after we know we have been written to. grw.Header().Del(headerContentLength) gz.Close() }