2015-01-21 19:07:45 +00:00
|
|
|
// Copyright 2013 The Prometheus Authors
|
2013-06-28 08:19:16 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2015-05-28 19:11:48 +00:00
|
|
|
package httputil
|
2013-06-28 08:19:16 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
2023-05-30 15:42:38 +00:00
|
|
|
|
|
|
|
"github.com/klauspost/compress/gzhttp"
|
|
|
|
"github.com/klauspost/compress/zlib"
|
2013-06-28 08:19:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
acceptEncodingHeader = "Accept-Encoding"
|
|
|
|
contentEncodingHeader = "Content-Encoding"
|
|
|
|
gzipEncoding = "gzip"
|
|
|
|
deflateEncoding = "deflate"
|
|
|
|
)
|
|
|
|
|
2023-05-30 15:42:38 +00:00
|
|
|
// Wrapper around http.ResponseWriter which adds deflate compression
|
|
|
|
type deflatedResponseWriter struct {
|
2013-06-28 08:19:16 +00:00
|
|
|
http.ResponseWriter
|
2023-05-30 15:42:38 +00:00
|
|
|
writer *zlib.Writer
|
2013-06-28 08:19:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Writes HTTP response content data.
|
2023-05-30 15:42:38 +00:00
|
|
|
func (c *deflatedResponseWriter) Write(p []byte) (int, error) {
|
2013-06-28 08:19:16 +00:00
|
|
|
return c.writer.Write(p)
|
|
|
|
}
|
|
|
|
|
2023-05-30 15:42:38 +00:00
|
|
|
// Close Closes the deflatedResponseWriter and ensures to flush all data before.
|
|
|
|
func (c *deflatedResponseWriter) Close() {
|
|
|
|
c.writer.Close()
|
2013-06-28 08:19:16 +00:00
|
|
|
}
|
|
|
|
|
2023-05-30 15:42:38 +00:00
|
|
|
// Constructs a new deflatedResponseWriter to compress the original writer using 'deflate' compression.
|
|
|
|
func newDeflateResponseWriter(writer http.ResponseWriter) *deflatedResponseWriter {
|
|
|
|
return &deflatedResponseWriter{
|
2013-06-28 08:19:16 +00:00
|
|
|
ResponseWriter: writer,
|
2023-05-30 15:42:38 +00:00
|
|
|
writer: zlib.NewWriter(writer),
|
2013-06-28 08:19:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-10 15:16:49 +00:00
|
|
|
// CompressionHandler is a wrapper around http.Handler which adds suitable
|
|
|
|
// response compression based on the client's Accept-Encoding headers.
|
2013-10-22 18:31:52 +00:00
|
|
|
type CompressionHandler struct {
|
|
|
|
Handler http.Handler
|
2013-06-28 08:19:16 +00:00
|
|
|
}
|
|
|
|
|
2014-12-10 15:16:49 +00:00
|
|
|
// ServeHTTP adds compression to the original http.Handler's ServeHTTP() method.
|
2013-10-22 18:31:52 +00:00
|
|
|
func (c CompressionHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
|
2023-05-30 15:42:38 +00:00
|
|
|
encodings := strings.Split(req.Header.Get(acceptEncodingHeader), ",")
|
|
|
|
for _, encoding := range encodings {
|
|
|
|
switch strings.TrimSpace(encoding) {
|
|
|
|
case gzipEncoding:
|
|
|
|
gzhttp.GzipHandler(c.Handler).ServeHTTP(writer, req)
|
|
|
|
return
|
|
|
|
case deflateEncoding:
|
|
|
|
compWriter := newDeflateResponseWriter(writer)
|
|
|
|
writer.Header().Set(contentEncodingHeader, deflateEncoding)
|
|
|
|
c.Handler.ServeHTTP(compWriter, req)
|
|
|
|
compWriter.Close()
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
c.Handler.ServeHTTP(writer, req)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2013-06-28 08:19:16 +00:00
|
|
|
}
|