Documentation ¶
Index ¶
- Constants
- func CompressAllContentTypeFilter(ct string) bool
- func CompressionLevel(level int) option
- func ContentTypeFilter(compress func(ct string) bool) option
- func ContentTypes(types []string) option
- func DefaultContentTypeFilter(ct string) bool
- func DropETag() option
- func ExceptContentTypes(types []string) option
- func GzipHandler(h http.Handler) http.HandlerFunc
- func Implementation(writer writer.GzipWriterFactory) option
- func KeepAcceptRanges() option
- func MinSize(size int) option
- func NewWrapper(opts ...option) (func(http.Handler) http.HandlerFunc, error)
- func RandomJitter(n, buffer int, paranoid bool) option
- func SetContentType(b bool) option
- func SuffixETag(suffix string) option
- func Transport(parent http.RoundTripper, opts ...transportOption) http.RoundTripper
- func TransportCustomEval(fn func(header http.Header) bool) transportOption
- func TransportEnableGzip(b bool) transportOption
- func TransportEnableZstd(b bool) transportOption
- type GzipResponseWriter
- func (w *GzipResponseWriter) Close() error
- func (w *GzipResponseWriter) Flush()
- func (w *GzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)
- func (w *GzipResponseWriter) Unwrap() http.ResponseWriter
- func (w *GzipResponseWriter) Write(b []byte) (int, error)
- func (w *GzipResponseWriter) WriteHeader(code int)
- type GzipResponseWriterWithCloseNotify
- type NoGzipResponseWriter
- func (n *NoGzipResponseWriter) CloseNotify() <-chan bool
- func (n *NoGzipResponseWriter) Flush()
- func (n *NoGzipResponseWriter) Header() http.Header
- func (n *NoGzipResponseWriter) Unwrap() http.ResponseWriter
- func (n *NoGzipResponseWriter) Write(bytes []byte) (int, error)
- func (n *NoGzipResponseWriter) WriteHeader(statusCode int)
Examples ¶
Constants ¶
const ( // DefaultQValue is the default qvalue to assign to an encoding if no explicit qvalue is set. // This is actually kind of ambiguous in RFC 2616, so hopefully it's correct. // The examples seem to indicate that it is. DefaultQValue = 1.0 // DefaultMinSize is the default minimum size until we enable gzip compression. // 1500 bytes is the MTU size for the internet since that is the largest size allowed at the network layer. // If you take a file that is 1300 bytes and compress it to 800 bytes, it’s still transmitted in that same 1500 byte packet regardless, so you’ve gained nothing. // That being the case, you should restrict the gzip compression to files with a size (plus header) greater than a single packet, // 1024 bytes (1KB) is therefore default. DefaultMinSize = 1024 )
const ( // HeaderNoCompression can be used to disable compression. // Any header value will disable compression. // The Header is always removed from output. HeaderNoCompression = "No-Gzip-Compression" )
Variables ¶
This section is empty.
Functions ¶
func CompressAllContentTypeFilter ¶
CompressAllContentTypeFilter will compress all mime types.
func CompressionLevel ¶
func CompressionLevel(level int) option
CompressionLevel sets the compression level
func ContentTypeFilter ¶
ContentTypeFilter allows adding a custom content type filter.
The supplied function must return true/false to indicate if content should be compressed.
When called no parsing of the content type 'ct' has been done. It may have been set or auto-detected.
Setting this will override default and any previous Content Type settings.
func ContentTypes ¶
func ContentTypes(types []string) option
ContentTypes specifies a list of content types to compare the Content-Type header to before compressing. If none match, the response will be returned as-is.
Content types are compared in a case-insensitive, whitespace-ignored manner.
A MIME type without any other directive will match a content type that has the same MIME type, regardless of that content type's other directives. I.e., "text/html" will match both "text/html" and "text/html; charset=utf-8".
A MIME type with any other directive will only match a content type that has the same MIME type and other directives. I.e., "text/html; charset=utf-8" will only match "text/html; charset=utf-8".
By default common compressed audio, video and archive formats, see DefaultContentTypeFilter.
Setting this will override default and any previous Content Type settings.
func DefaultContentTypeFilter ¶
DefaultContentTypeFilter excludes common compressed audio, video and archive formats.
func DropETag ¶
func DropETag() option
DropETag removes the ETag of responses which are compressed. If DropETag is specified in conjunction with SuffixETag, this option will take precedence and the ETag will be dropped.
Per [RFC 7232 Section 2.3.3](https://www.rfc-editor.org/rfc/rfc7232#section-2.3.3), the ETag of a compressed response must differ from it's uncompressed version.
This workaround eliminates ETag conflicts between the compressed and uncompressed versions by removing the ETag from the compressed version.
func ExceptContentTypes ¶
func ExceptContentTypes(types []string) option
ExceptContentTypes specifies a list of content types to compare the Content-Type header to before compressing. If none match, the response will be compressed.
Content types are compared in a case-insensitive, whitespace-ignored manner.
A MIME type without any other directive will match a content type that has the same MIME type, regardless of that content type's other directives. I.e., "text/html" will match both "text/html" and "text/html; charset=utf-8".
A MIME type with any other directive will only match a content type that has the same MIME type and other directives. I.e., "text/html; charset=utf-8" will only match "text/html; charset=utf-8".
By default common compressed audio, video and archive formats, see DefaultContentTypeFilter.
Setting this will override default and any previous Content Type settings.
func GzipHandler ¶
func GzipHandler(h http.Handler) http.HandlerFunc
GzipHandler allows to easily wrap an http handler with default settings.
func Implementation ¶
func Implementation(writer writer.GzipWriterFactory) option
Implementation changes the implementation of GzipWriter
The default implementation is backed by github.com/klauspost/compress To support RandomJitter, the GzipWriterExt must also be supported by the returned writers.
func KeepAcceptRanges ¶
func KeepAcceptRanges() option
KeepAcceptRanges will keep Accept-Ranges header on gzipped responses. This will likely break ranged requests since that cannot be transparently handled by the filter.
func NewWrapper ¶
func NewWrapper(opts ...option) (func(http.Handler) http.HandlerFunc, error)
NewWrapper returns a reusable wrapper with the supplied options.
Example ¶
package main import ( "fmt" "io" "io/ioutil" "log" "net/http" "net/http/httptest" "github.com/Memexurer/compress/gzhttp" "github.com/Memexurer/compress/gzip" ) func main() { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") io.WriteString(w, "Hello, World, Welcome to the jungle...") }) handler2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello, Another World.................") }) // Create a reusable wrapper with custom options. wrapper, err := gzhttp.NewWrapper(gzhttp.MinSize(20), gzhttp.CompressionLevel(gzip.BestSpeed)) if err != nil { log.Fatalln(err) } server := http.NewServeMux() server.Handle("/a", wrapper(handler)) server.Handle("/b", wrapper(handler2)) test := httptest.NewServer(server) defer test.Close() resp, err := http.Get(test.URL + "/a") if err != nil { log.Fatalln(err) } content, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(content)) resp, err = http.Get(test.URL + "/b") if err != nil { log.Fatalln(err) } content, _ = ioutil.ReadAll(resp.Body) fmt.Println(string(content)) }
Output: Hello, World, Welcome to the jungle... Hello, Another World.................
func RandomJitter ¶
RandomJitter adds 1->n random bytes to output based on checksum of payload. Specify the amount of input to buffer before applying jitter. This should cover the sensitive part of your response. This can be used to obfuscate the exact compressed size. Specifying 0 will use a buffer size of 64KB. 'paranoid' will use a slower hashing function, that MAY provide more safety. See README.md for more information. If a negative buffer is given, the amount of jitter will not be content dependent. This provides *less* security than applying content based jitter.
func SetContentType ¶
func SetContentType(b bool) option
SetContentType sets the content type before returning requests, if unset before returning, and it was detected. Default: true.
func SuffixETag ¶
func SuffixETag(suffix string) option
SuffixETag adds the specified suffix to the ETag header (if it exists) of responses which are compressed.
Per [RFC 7232 Section 2.3.3](https://www.rfc-editor.org/rfc/rfc7232#section-2.3.3), the ETag of a compressed response must differ from it's uncompressed version.
A suffix such as "-gzip" is sometimes used as a workaround for generating a unique new ETag (see https://bz.apache.org/bugzilla/show_bug.cgi?id=39727).
func Transport ¶
func Transport(parent http.RoundTripper, opts ...transportOption) http.RoundTripper
Transport will wrap an HTTP transport with a custom handler that will request gzip and automatically decompress it. Using this is significantly faster than using the default transport.
Example ¶
package main import ( "fmt" "io/ioutil" "net/http" "github.com/Memexurer/compress/gzhttp" ) func main() { // Get a client. client := http.Client{ // Wrap the transport: Transport: gzhttp.Transport(http.DefaultTransport), } resp, err := client.Get("https://google.com") if err != nil { fmt.Println(err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println("body:", string(body)) }
Output:
func TransportCustomEval ¶
TransportCustomEval will send the header of a response to a custom function. If the function returns false, the response will be returned as-is, Otherwise it will be decompressed based on Content-Encoding field, regardless of whether the transport added the encoding.
func TransportEnableGzip ¶
func TransportEnableGzip(b bool) transportOption
TransportEnableGzip will send Gzip as a compression option to the server. Enabled by default.
func TransportEnableZstd ¶
func TransportEnableZstd(b bool) transportOption
TransportEnableZstd will send Zstandard as a compression option to the server. Enabled by default, but may be disabled if future problems arise.
Types ¶
type GzipResponseWriter ¶
type GzipResponseWriter struct { http.ResponseWriter // contains filtered or unexported fields }
GzipResponseWriter provides an http.ResponseWriter interface, which gzips bytes before writing them to the underlying response. This doesn't close the writers, so don't forget to do that. It can be configured to skip response smaller than minSize.
func (*GzipResponseWriter) Close ¶
func (w *GzipResponseWriter) Close() error
Close will close the gzip.Writer and will put it back in the gzipWriterPool.
func (*GzipResponseWriter) Flush ¶
func (w *GzipResponseWriter) Flush()
Flush flushes the underlying *gzip.Writer and then the underlying http.ResponseWriter if it is an http.Flusher. This makes GzipResponseWriter an http.Flusher. If not enough bytes has been written to determine if we have reached minimum size, this will be ignored. If nothing has been written yet, nothing will be flushed.
func (*GzipResponseWriter) Hijack ¶
func (w *GzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)
Hijack implements http.Hijacker. If the underlying ResponseWriter is a Hijacker, its Hijack method is returned. Otherwise an error is returned.
func (*GzipResponseWriter) Unwrap ¶
func (w *GzipResponseWriter) Unwrap() http.ResponseWriter
func (*GzipResponseWriter) Write ¶
func (w *GzipResponseWriter) Write(b []byte) (int, error)
Write appends data to the gzip writer.
func (*GzipResponseWriter) WriteHeader ¶
func (w *GzipResponseWriter) WriteHeader(code int)
WriteHeader just saves the response code until close or GZIP effective writes. In the specific case of 1xx status codes, WriteHeader is directly calling the wrapped ResponseWriter.
type GzipResponseWriterWithCloseNotify ¶
type GzipResponseWriterWithCloseNotify struct {
*GzipResponseWriter
}
func (GzipResponseWriterWithCloseNotify) CloseNotify ¶
func (w GzipResponseWriterWithCloseNotify) CloseNotify() <-chan bool
type NoGzipResponseWriter ¶
type NoGzipResponseWriter struct { http.ResponseWriter // contains filtered or unexported fields }
NoGzipResponseWriter filters out HeaderNoCompression.
func (*NoGzipResponseWriter) CloseNotify ¶
func (n *NoGzipResponseWriter) CloseNotify() <-chan bool
func (*NoGzipResponseWriter) Flush ¶
func (n *NoGzipResponseWriter) Flush()
func (*NoGzipResponseWriter) Header ¶
func (n *NoGzipResponseWriter) Header() http.Header
func (*NoGzipResponseWriter) Unwrap ¶
func (n *NoGzipResponseWriter) Unwrap() http.ResponseWriter
func (*NoGzipResponseWriter) Write ¶
func (n *NoGzipResponseWriter) Write(bytes []byte) (int, error)
func (*NoGzipResponseWriter) WriteHeader ¶
func (n *NoGzipResponseWriter) WriteHeader(statusCode int)