From 63b5d1c4c885a0cf257b5977e4f019e9f9458137 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sat, 3 Dec 2016 22:04:35 +0100 Subject: [PATCH 1/3] Revert "Merge pull request #753 from gin-gonic/bug" This reverts commit 556287ff0856a5ad1f9a1b493c188cabeceba929, reversing changes made to 32cab500ecc71d2975f5699c8a65c6debb29cfbe. --- logger.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/logger.go b/logger.go index ad442d0c..b4743a7f 100644 --- a/logger.go +++ b/logger.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "os" - "runtime" "time" "golang.org/x/crypto/ssh/terminal" @@ -49,11 +48,8 @@ func Logger() HandlerFunc { // Example: os.Stdout, a file opened in write mode, a socket... func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { isTerm := true - - if runtime.GOOS != "appengine" && runtime.GOOS != "netbsd" && runtime.GOOS != "openbsd" { - if outFile, ok := out.(*os.File); ok { - isTerm = terminal.IsTerminal(int(outFile.Fd())) - } + if outFile, ok := out.(*os.File); ok { + isTerm = terminal.IsTerminal(int(outFile.Fd())) } var skip map[string]struct{} From 041ca04a4768ededad44dcc2748f3d47e4b59bde Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sat, 3 Dec 2016 22:10:08 +0100 Subject: [PATCH 2/3] Revert "Merge pull request #744 from aviddiviner/logger-fix" This reverts commit c3bfd69303d0fdaf2d43a7ff07cc8ee45ec7bb3f, reversing changes made to 9177f01c2843b91820780197f521ba48554b9df3. --- logger.go | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/logger.go b/logger.go index b4743a7f..d56bc628 100644 --- a/logger.go +++ b/logger.go @@ -7,10 +7,7 @@ package gin import ( "fmt" "io" - "os" "time" - - "golang.org/x/crypto/ssh/terminal" ) var ( @@ -47,11 +44,6 @@ func Logger() HandlerFunc { // LoggerWithWriter instance a Logger middleware with the specified writter buffer. // Example: os.Stdout, a file opened in write mode, a socket... func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { - isTerm := true - if outFile, ok := out.(*os.File); ok { - isTerm = terminal.IsTerminal(int(outFile.Fd())) - } - var skip map[string]struct{} if length := len(notlogged); length > 0 { @@ -79,11 +71,8 @@ func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { clientIP := c.ClientIP() method := c.Request.Method statusCode := c.Writer.Status() - var statusColor, methodColor string - if isTerm { - statusColor = colorForStatus(statusCode) - methodColor = colorForMethod(method) - } + statusColor := colorForStatus(statusCode) + methodColor := colorForMethod(method) comment := c.Errors.ByType(ErrorTypePrivate).String() fmt.Fprintf(out, "[GIN] %v |%s %3d %s| %13v | %s |%s %s %-7s %s\n%s", From dcc16a8f7bf1795bd6830bcb05e8cc4e93bb9b67 Mon Sep 17 00:00:00 2001 From: Harindu Perera Date: Fri, 17 Feb 2017 21:17:54 +0100 Subject: [PATCH 3/3] Added support for MessagePack binding and rendering --- Godeps/Godeps.json | 6 +++++- binding/binding.go | 5 +++++ binding/binding_test.go | 45 +++++++++++++++++++++++++++++++++++++++-- binding/msgpack.go | 28 +++++++++++++++++++++++++ render/msgpack.go | 27 +++++++++++++++++++++++++ render/render.go | 2 ++ render/render_test.go | 23 +++++++++++++++++++++ 7 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 binding/msgpack.go create mode 100644 render/msgpack.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index a9c828a2..1728f789 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -31,6 +31,10 @@ "ImportPath": "gopkg.in/go-playground/validator.v8", "Comment": "v8.15.1", "Rev": "c193cecd124b5cc722d7ee5538e945bdb3348435" + }, + { + "ImportPath": "github.com/ugorji/go/codec", + "Rev": "c88ee250d0221a57af388746f5cf03768c21d6e2" } ] -} +} \ No newline at end of file diff --git a/binding/binding.go b/binding/binding.go index dc7397f1..d3a2c97e 100644 --- a/binding/binding.go +++ b/binding/binding.go @@ -15,6 +15,8 @@ const ( MIMEPOSTForm = "application/x-www-form-urlencoded" MIMEMultipartPOSTForm = "multipart/form-data" MIMEPROTOBUF = "application/x-protobuf" + MIMEMSGPACK = "application/x-msgpack" + MIMEMSGPACK2 = "application/msgpack" ) type Binding interface { @@ -40,6 +42,7 @@ var ( FormPost = formPostBinding{} FormMultipart = formMultipartBinding{} ProtoBuf = protobufBinding{} + MsgPack = msgpackBinding{} ) func Default(method, contentType string) Binding { @@ -53,6 +56,8 @@ func Default(method, contentType string) Binding { return XML case MIMEPROTOBUF: return ProtoBuf + case MIMEMSGPACK, MIMEMSGPACK2: + return MsgPack default: //case MIMEPOSTForm, MIMEMultipartPOSTForm: return Form } diff --git a/binding/binding_test.go b/binding/binding_test.go index 72f60152..cf005948 100644 --- a/binding/binding_test.go +++ b/binding/binding_test.go @@ -12,17 +12,18 @@ import ( "github.com/gin-gonic/gin/binding/example" "github.com/golang/protobuf/proto" + "github.com/ugorji/go/codec" "github.com/stretchr/testify/assert" ) type FooStruct struct { - Foo string `json:"foo" form:"foo" xml:"foo" binding:"required"` + Foo string `msgpack:"foo" json:"foo" form:"foo" xml:"foo" binding:"required"` } type FooBarStruct struct { FooStruct - Bar string `json:"bar" form:"bar" xml:"bar" binding:"required"` + Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"` } func TestBindingDefault(t *testing.T) { @@ -43,6 +44,9 @@ func TestBindingDefault(t *testing.T) { assert.Equal(t, Default("POST", MIMEPROTOBUF), ProtoBuf) assert.Equal(t, Default("PUT", MIMEPROTOBUF), ProtoBuf) + + assert.Equal(t, Default("POST", MIMEMSGPACK), MsgPack) + assert.Equal(t, Default("PUT", MIMEMSGPACK2), MsgPack) } func TestBindingJSON(t *testing.T) { @@ -121,6 +125,26 @@ func TestBindingProtoBuf(t *testing.T) { string(data), string(data[1:])) } +func TestBindingMsgPack(t *testing.T) { + test := FooStruct{ + Foo: "bar", + } + + h := new(codec.MsgpackHandle) + assert.NotNil(t, h) + buf := bytes.NewBuffer([]byte{}) + assert.NotNil(t, buf) + err := codec.NewEncoder(buf, h).Encode(test) + assert.NoError(t, err) + + data := buf.Bytes() + + testMsgPackBodyBinding(t, + MsgPack, "msgpack", + "/", "/", + string(data), string(data[1:])) +} + func TestValidationFails(t *testing.T) { var obj FooStruct req := requestWithBody("POST", "/", `{"bar": "foo"}`) @@ -213,6 +237,23 @@ func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, ba assert.Error(t, err) } +func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { + assert.Equal(t, b.Name(), name) + + obj := FooStruct{} + req := requestWithBody("POST", path, body) + req.Header.Add("Content-Type", MIMEMSGPACK) + err := b.Bind(req, &obj) + assert.NoError(t, err) + assert.Equal(t, obj.Foo, "bar") + + obj = FooStruct{} + req = requestWithBody("POST", badPath, badBody) + req.Header.Add("Content-Type", MIMEMSGPACK) + err = MsgPack.Bind(req, &obj) + assert.Error(t, err) +} + func requestWithBody(method, path, body string) (req *http.Request) { req, _ = http.NewRequest(method, path, bytes.NewBufferString(body)) return diff --git a/binding/msgpack.go b/binding/msgpack.go new file mode 100644 index 00000000..ee3b18b7 --- /dev/null +++ b/binding/msgpack.go @@ -0,0 +1,28 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package binding + +import ( + "github.com/ugorji/go/codec" + + "net/http" +) + +type msgpackBinding struct{} + +func (msgpackBinding) Name() string { + return "msgpack" +} + +func (msgpackBinding) Bind(req *http.Request, obj interface{}) error { + + if err := codec.NewDecoder(req.Body, new(codec.MsgpackHandle)).Decode(&obj); err != nil { + //var decoder *codec.Decoder = codec.NewDecoder(req.Body, &codec.MsgpackHandle) + //if err := decoder.Decode(&obj); err != nil { + return err + } + return validate(obj) + +} diff --git a/render/msgpack.go b/render/msgpack.go new file mode 100644 index 00000000..666747c1 --- /dev/null +++ b/render/msgpack.go @@ -0,0 +1,27 @@ +// Copyright 2014 Manu Martinez-Almeida. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package render + +import ( + "net/http" + + "github.com/ugorji/go/codec" +) + +type MsgPack struct { + Data interface{} +} + +var msgpackContentType = []string{"application/msgpack; charset=utf-8"} + +func (r MsgPack) Render(w http.ResponseWriter) error { + return WriteMsgPack(w, r.Data) +} + +func WriteMsgPack(w http.ResponseWriter, obj interface{}) error { + writeContentType(w, msgpackContentType) + var h codec.Handle = new(codec.MsgpackHandle) + return codec.NewEncoder(w, h).Encode(obj) +} diff --git a/render/render.go b/render/render.go index 3808666a..6660ed6a 100644 --- a/render/render.go +++ b/render/render.go @@ -21,6 +21,8 @@ var ( _ HTMLRender = HTMLDebug{} _ HTMLRender = HTMLProduction{} _ Render = YAML{} + _ Render = MsgPack{} + _ Render = MsgPack{} ) func writeContentType(w http.ResponseWriter, value []string) { diff --git a/render/render_test.go b/render/render_test.go index 7a6ffb7d..c597e894 100644 --- a/render/render_test.go +++ b/render/render_test.go @@ -5,17 +5,40 @@ package render import ( + "bytes" "encoding/xml" "html/template" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" + "github.com/ugorji/go/codec" ) // TODO unit tests // test errors +func TestRenderMsgPack(t *testing.T) { + w := httptest.NewRecorder() + data := map[string]interface{}{ + "foo": "bar", + } + + err := (MsgPack{data}).Render(w) + + assert.NoError(t, err) + + h := new(codec.MsgpackHandle) + assert.NotNil(t, h) + buf := bytes.NewBuffer([]byte{}) + assert.NotNil(t, buf) + err = codec.NewEncoder(buf, h).Encode(data) + + assert.NoError(t, err) + assert.Equal(t, w.Body.String(), string(buf.Bytes())) + assert.Equal(t, w.Header().Get("Content-Type"), "application/msgpack; charset=utf-8") +} + func TestRenderJSON(t *testing.T) { w := httptest.NewRecorder() data := map[string]interface{}{