diff --git a/chan.go b/chan.go index 2b6fb36..6d82ce6 100644 --- a/chan.go +++ b/chan.go @@ -181,6 +181,8 @@ func (re *chanResponseEmitter) SetLength(l uint64) { } } +func (re *chanResponseEmitter) SetEncodingType(encType EncodingType) {} + func (re *chanResponseEmitter) CloseWithError(err error) error { re.wl.Lock() defer re.wl.Unlock() diff --git a/cli/responseemitter.go b/cli/responseemitter.go index 0e69e7f..0b86d4c 100644 --- a/cli/responseemitter.go +++ b/cli/responseemitter.go @@ -59,6 +59,10 @@ func (re *responseEmitter) SetLength(l uint64) { re.length = l } +func (re *responseEmitter) SetEncodingType(encType cmds.EncodingType) { + re.encType = encType +} + func (re *responseEmitter) isClosed() bool { re.l.Lock() defer re.l.Unlock() diff --git a/command_test.go b/command_test.go index 5e83412..e97749d 100644 --- a/command_test.go +++ b/command_test.go @@ -344,6 +344,8 @@ func (s *testEmitterWithError) Close() error { return nil } +func (s *testEmitterWithError) SetEncodingType(EncodingType) {} + func (s *testEmitterWithError) SetLength(_ uint64) {} func (s *testEmitterWithError) CloseWithError(err error) error { diff --git a/encoding.go b/encoding.go index 61209f0..a4b14ba 100644 --- a/encoding.go +++ b/encoding.go @@ -35,6 +35,7 @@ const ( Protobuf = "protobuf" Text = "text" TextNewline = "textnl" + Gzip = "gzip" // PostRunTypes CLI = "cli" @@ -56,6 +57,9 @@ var Encoders = EncoderMap{ XML: func(req *Request) func(io.Writer) Encoder { return func(w io.Writer) Encoder { return xml.NewEncoder(w) } }, + Gzip: func(req *Request) func(io.Writer) Encoder { + return func(w io.Writer) Encoder { return TextEncoder{w: w} } + }, JSON: func(req *Request) func(io.Writer) Encoder { return func(w io.Writer) Encoder { return json.NewEncoder(w) } }, diff --git a/helpers_test.go b/helpers_test.go index 3c976f2..04e7f92 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -17,6 +17,9 @@ func (s *testEmitter) Close() error { } func (s *testEmitter) SetLength(_ uint64) {} + +func (s *testEmitter) SetEncodingType(EncodingType) {} + func (s *testEmitter) CloseWithError(err error) error { if err != nil { (*testing.T)(s).Error(err) diff --git a/http/parse.go b/http/parse.go index b19c3a5..c23bd88 100644 --- a/http/parse.go +++ b/http/parse.go @@ -201,7 +201,7 @@ func parseResponse(httpRes *http.Response, req *cmds.Request) (cmds.Response, er makeDec, ok := cmds.Decoders[encType] if ok { res.dec = makeDec(res.rr) - } else if encType != "text" { + } else if encType != "text" && encType != "gzip" { log.Errorf("could not find decoder for encoding %q", encType) } // else we have an io.Reader, which is okay } else { diff --git a/http/response.go b/http/response.go index e29287f..a739072 100644 --- a/http/response.go +++ b/http/response.go @@ -12,9 +12,10 @@ import ( var ( MIMEEncodings = map[string]cmds.EncodingType{ - "application/json": cmds.JSON, - "application/xml": cmds.XML, - "text/plain": cmds.Text, + "application/json": cmds.JSON, + "application/x-gzip": cmds.Gzip, + "application/xml": cmds.XML, + "text/plain": cmds.Text, } ) diff --git a/http/responseemitter.go b/http/responseemitter.go index e5d424e..3f2edab 100644 --- a/http/responseemitter.go +++ b/http/responseemitter.go @@ -22,6 +22,7 @@ var ( cmds.JSON: "application/json", cmds.XML: "application/xml", cmds.Text: "text/plain", + cmds.Gzip: "application/x-gzip; charset=binary", } ) @@ -143,6 +144,13 @@ func (re *responseEmitter) Emit(value interface{}) error { return err } +func (re *responseEmitter) SetEncodingType(encType cmds.EncodingType) { + re.l.Lock() + defer re.l.Unlock() + + re.encType = encType +} + func (re *responseEmitter) SetLength(l uint64) { re.l.Lock() defer re.l.Unlock() @@ -252,10 +260,7 @@ func (re *responseEmitter) sendErr(err *cmds.Error) { } func (re *responseEmitter) doPreamble(value interface{}) { - var ( - h = re.w.Header() - mime string - ) + h := re.w.Header() // Common Headers @@ -283,6 +288,8 @@ func (re *responseEmitter) doPreamble(value interface{}) { } } + var mime string + switch v := value.(type) { case *cmds.Error: re.sendErr(v) @@ -293,7 +300,10 @@ func (re *responseEmitter) doPreamble(value interface{}) { h.Set(streamHeader, "1") re.streaming = true - mime = "text/plain" + if re.encType == cmds.JSON { + mime = "text/plain" + } + case cmds.Single: // don't set stream/channel header default: @@ -302,7 +312,6 @@ func (re *responseEmitter) doPreamble(value interface{}) { if mime == "" { var ok bool - // lookup mime type from map mime, ok = mimeTypes[re.encType] if !ok { diff --git a/responseemitter.go b/responseemitter.go index 97d4438..753e1b1 100644 --- a/responseemitter.go +++ b/responseemitter.go @@ -43,6 +43,9 @@ type ResponseEmitter interface { // SetLength sets the length of the output SetLength(length uint64) + // SetEncodingType sets the encoding type of the output. + SetEncodingType(encType EncodingType) + // Emit sends a value. // If value is io.Reader we just copy that to the connection // other values are marshalled. diff --git a/writer.go b/writer.go index 23b2460..9ead8fe 100644 --- a/writer.go +++ b/writer.go @@ -135,6 +135,8 @@ func (re *writerResponseEmitter) SetLength(length uint64) { re.length = &length } +func (re *writerResponseEmitter) SetEncodingType(encType EncodingType) {} + func (re *writerResponseEmitter) Close() error { if re.closed { return ErrClosingClosedEmitter