Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / emicklei / go-restful / compress.go
1 package restful
2
3 // Copyright 2013 Ernest Micklei. All rights reserved.
4 // Use of this source code is governed by a license
5 // that can be found in the LICENSE file.
6
7 import (
8         "bufio"
9         "compress/gzip"
10         "compress/zlib"
11         "errors"
12         "io"
13         "net"
14         "net/http"
15         "strings"
16 )
17
18 // OBSOLETE : use restful.DefaultContainer.EnableContentEncoding(true) to change this setting.
19 var EnableContentEncoding = false
20
21 // CompressingResponseWriter is a http.ResponseWriter that can perform content encoding (gzip and zlib)
22 type CompressingResponseWriter struct {
23         writer     http.ResponseWriter
24         compressor io.WriteCloser
25         encoding   string
26 }
27
28 // Header is part of http.ResponseWriter interface
29 func (c *CompressingResponseWriter) Header() http.Header {
30         return c.writer.Header()
31 }
32
33 // WriteHeader is part of http.ResponseWriter interface
34 func (c *CompressingResponseWriter) WriteHeader(status int) {
35         c.writer.WriteHeader(status)
36 }
37
38 // Write is part of http.ResponseWriter interface
39 // It is passed through the compressor
40 func (c *CompressingResponseWriter) Write(bytes []byte) (int, error) {
41         if c.isCompressorClosed() {
42                 return -1, errors.New("Compressing error: tried to write data using closed compressor")
43         }
44         return c.compressor.Write(bytes)
45 }
46
47 // CloseNotify is part of http.CloseNotifier interface
48 func (c *CompressingResponseWriter) CloseNotify() <-chan bool {
49         return c.writer.(http.CloseNotifier).CloseNotify()
50 }
51
52 // Close the underlying compressor
53 func (c *CompressingResponseWriter) Close() error {
54         if c.isCompressorClosed() {
55                 return errors.New("Compressing error: tried to close already closed compressor")
56         }
57
58         c.compressor.Close()
59         if ENCODING_GZIP == c.encoding {
60                 currentCompressorProvider.ReleaseGzipWriter(c.compressor.(*gzip.Writer))
61         }
62         if ENCODING_DEFLATE == c.encoding {
63                 currentCompressorProvider.ReleaseZlibWriter(c.compressor.(*zlib.Writer))
64         }
65         // gc hint needed?
66         c.compressor = nil
67         return nil
68 }
69
70 func (c *CompressingResponseWriter) isCompressorClosed() bool {
71         return nil == c.compressor
72 }
73
74 // Hijack implements the Hijacker interface
75 // This is especially useful when combining Container.EnabledContentEncoding
76 // in combination with websockets (for instance gorilla/websocket)
77 func (c *CompressingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
78         hijacker, ok := c.writer.(http.Hijacker)
79         if !ok {
80                 return nil, nil, errors.New("ResponseWriter doesn't support Hijacker interface")
81         }
82         return hijacker.Hijack()
83 }
84
85 // WantsCompressedResponse reads the Accept-Encoding header to see if and which encoding is requested.
86 func wantsCompressedResponse(httpRequest *http.Request) (bool, string) {
87         header := httpRequest.Header.Get(HEADER_AcceptEncoding)
88         gi := strings.Index(header, ENCODING_GZIP)
89         zi := strings.Index(header, ENCODING_DEFLATE)
90         // use in order of appearance
91         if gi == -1 {
92                 return zi != -1, ENCODING_DEFLATE
93         } else if zi == -1 {
94                 return gi != -1, ENCODING_GZIP
95         } else {
96                 if gi < zi {
97                         return true, ENCODING_GZIP
98                 }
99                 return true, ENCODING_DEFLATE
100         }
101 }
102
103 // NewCompressingResponseWriter create a CompressingResponseWriter for a known encoding = {gzip,deflate}
104 func NewCompressingResponseWriter(httpWriter http.ResponseWriter, encoding string) (*CompressingResponseWriter, error) {
105         httpWriter.Header().Set(HEADER_ContentEncoding, encoding)
106         c := new(CompressingResponseWriter)
107         c.writer = httpWriter
108         var err error
109         if ENCODING_GZIP == encoding {
110                 w := currentCompressorProvider.AcquireGzipWriter()
111                 w.Reset(httpWriter)
112                 c.compressor = w
113                 c.encoding = ENCODING_GZIP
114         } else if ENCODING_DEFLATE == encoding {
115                 w := currentCompressorProvider.AcquireZlibWriter()
116                 w.Reset(httpWriter)
117                 c.compressor = w
118                 c.encoding = ENCODING_DEFLATE
119         } else {
120                 return nil, errors.New("Unknown encoding:" + encoding)
121         }
122         return c, err
123 }