From 73e5fcd8554f42d935f2b79a5e9ce29eefa9c889 Mon Sep 17 00:00:00 2001 From: Javier Provecho Date: Wed, 29 Mar 2017 14:32:12 +0000 Subject: [PATCH 01/40] feat(context): add idiomatic binding functions for clear err managment --- context.go | 18 +++++++++++++----- deprecated.go | 15 ++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/context.go b/context.go index f638e62..1873269 100644 --- a/context.go +++ b/context.go @@ -344,14 +344,22 @@ func (c *Context) BindJSON(obj interface{}) error { return c.BindWith(obj, binding.JSON) } -// BindWith binds the passed struct pointer using the specified binding engine. +// MustBindWith binds the passed struct pointer using the specified binding +// engine. It will abort the request with HTTP 400 if any error ocurrs. // See the binding package. -func (c *Context) BindWith(obj interface{}, b binding.Binding) error { - if err := b.Bind(c.Request, obj); err != nil { +func (c *Context) MustBindWith(obj interface{}, b binding.Binding) (err error) { + if err = c.ShouldBindWith(obj, b); err != nil { c.AbortWithError(400, err).SetType(ErrorTypeBind) - return err } - return nil + + return +} + +// ShouldBindWith binds the passed struct pointer using the specified binding +// engine. +// See the binding package. +func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error { + return b.Bind(c.Request, obj) } // ClientIP implements a best effort algorithm to return the real client IP, it parses diff --git a/deprecated.go b/deprecated.go index 0488a9b..27e8f55 100644 --- a/deprecated.go +++ b/deprecated.go @@ -4,9 +4,22 @@ package gin -import "log" +import ( + "github.com/gin-gonic/gin/binding" + "log" +) func (c *Context) GetCookie(name string) (string, error) { log.Println("GetCookie() method is deprecated. Use Cookie() instead.") return c.Cookie(name) } + +// BindWith binds the passed struct pointer using the specified binding engine. +// See the binding package. +func (c *Context) BindWith(obj interface{}, b binding.Binding) error { + log.Println(`BindWith(\"interface{}, binding.Binding\") error is going to + be deprecated, please check issue #662 and either use MustBindWith() if you + want HTTP 400 to be automatically returned if any error occur, of use + ShouldBindWith() if you need to manage the error.`) + return c.MustBindWith(obj, b) +} From d5b353c5d5a560322e6d96121c814115562501f7 Mon Sep 17 00:00:00 2001 From: Manu MA Date: Fri, 28 Apr 2017 12:59:23 +0200 Subject: [PATCH 02/40] Update README.md Github does not render README correctly, missing whitespaces --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 82ea6a5..dc9c9e3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ -#Gin Web Framework +# Gin Web Framework + [![Build Status](https://travis-ci.org/gin-gonic/gin.svg)](https://travis-ci.org/gin-gonic/gin) -[![codecov](https://codecov.io/gh/gin-gonic/gin/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-gonic/gin) -[![Go Report Card](https://goreportcard.com/badge/github.com/gin-gonic/gin)](https://goreportcard.com/report/github.com/gin-gonic/gin) -[![GoDoc](https://godoc.org/github.com/gin-gonic/gin?status.svg)](https://godoc.org/github.com/gin-gonic/gin) -[![Join the chat at https://gitter.im/gin-gonic/gin](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gin-gonic/gin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + [![codecov](https://codecov.io/gh/gin-gonic/gin/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-gonic/gin) + [![Go Report Card](https://goreportcard.com/badge/github.com/gin-gonic/gin)](https://goreportcard.com/report/github.com/gin-gonic/gin) + [![GoDoc](https://godoc.org/github.com/gin-gonic/gin?status.svg)](https://godoc.org/github.com/gin-gonic/gin) + [![Join the chat at https://gitter.im/gin-gonic/gin](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gin-gonic/gin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Gin is a web framework written in Go (Golang). It features a martini-like API with much better performance, up to 40 times faster thanks to [httprouter](https://github.com/julienschmidt/httprouter). If you need performance and good productivity, you will love Gin. From 214a746b1d531cdacdcc0aa4039da119d4002837 Mon Sep 17 00:00:00 2001 From: Eason Lin Date: Wed, 24 May 2017 17:39:05 +0800 Subject: [PATCH 03/40] Improve cookie tests code coverage (#918) --- context_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/context_test.go b/context_test.go index 0feeca8..fccca47 100644 --- a/context_test.go +++ b/context_test.go @@ -384,12 +384,21 @@ func TestContextSetCookie(t *testing.T) { assert.Equal(t, c.Writer.Header().Get("Set-Cookie"), "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure") } +func TestContextSetCookiePathEmpty(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.SetCookie("user", "gin", 1, "", "localhost", true, true) + assert.Equal(t, c.Writer.Header().Get("Set-Cookie"), "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure") +} + func TestContextGetCookie(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) c.Request, _ = http.NewRequest("GET", "/get", nil) c.Request.Header.Set("Cookie", "user=gin") cookie, _ := c.Cookie("user") assert.Equal(t, cookie, "gin") + + _, err := c.Cookie("nokey") + assert.Error(t, err) } func TestContextBodyAllowedForStatus(t *testing.T) { From 8295db44ed904572ad133d974cad381eb961cdab Mon Sep 17 00:00:00 2001 From: Eason Lin Date: Mon, 29 May 2017 14:28:38 +0800 Subject: [PATCH 04/40] Add content negotiation tests code coverage (#921) --- context_test.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/context_test.go b/context_test.go index fccca47..131d891 100644 --- a/context_test.go +++ b/context_test.go @@ -746,6 +746,68 @@ func TestContextRenderRedirectAll(t *testing.T) { assert.NotPanics(t, func() { c.Redirect(308, "/resource") }) } +func TestContextNegotiationWithJSON(t *testing.T) { + w := httptest.NewRecorder() + c, _ := CreateTestContext(w) + c.Request, _ = http.NewRequest("POST", "", nil) + + c.Negotiate(200, Negotiate{ + Offered: []string{MIMEJSON, MIMEXML}, + Data: H{"foo": "bar"}, + }) + + assert.Equal(t, 200, w.Code) + assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) + assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type")) +} + +func TestContextNegotiationWithXML(t *testing.T) { + w := httptest.NewRecorder() + c, _ := CreateTestContext(w) + c.Request, _ = http.NewRequest("POST", "", nil) + + c.Negotiate(200, Negotiate{ + Offered: []string{MIMEXML, MIMEJSON}, + Data: H{"foo": "bar"}, + }) + + assert.Equal(t, 200, w.Code) + assert.Equal(t, "bar", w.Body.String()) + assert.Equal(t, "application/xml; charset=utf-8", w.HeaderMap.Get("Content-Type")) +} + +func TestContextNegotiationWithHTML(t *testing.T) { + w := httptest.NewRecorder() + c, router := CreateTestContext(w) + c.Request, _ = http.NewRequest("POST", "", nil) + templ := template.Must(template.New("t").Parse(`Hello {{.name}}`)) + router.SetHTMLTemplate(templ) + + c.Negotiate(200, Negotiate{ + Offered: []string{MIMEHTML}, + Data: H{"name": "gin"}, + HTMLName: "t", + }) + + assert.Equal(t, 200, w.Code) + assert.Equal(t, "Hello gin", w.Body.String()) + assert.Equal(t, "text/html; charset=utf-8", w.HeaderMap.Get("Content-Type")) +} + +func TestContextNegotiationNotSupport(t *testing.T) { + w := httptest.NewRecorder() + c, _ := CreateTestContext(w) + c.Request, _ = http.NewRequest("POST", "", nil) + + c.Negotiate(200, Negotiate{ + Offered: []string{MIMEPOSTForm}, + }) + + assert.Equal(t, 406, w.Code) + assert.Equal(t, c.index, abortIndex) + assert.True(t, c.IsAborted()) +} + func TestContextNegotiationFormat(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) c.Request, _ = http.NewRequest("POST", "", nil) From 35f5df63e6379d6db4bfd27f23b2ddff030b11a2 Mon Sep 17 00:00:00 2001 From: sope Date: Mon, 29 May 2017 16:03:49 +0800 Subject: [PATCH 05/40] add custom Delims support (#860) * Revert "Merge pull request #753 from gin-gonic/bug" This reverts commit 556287ff0856a5ad1f9a1b493c188cabeceba929, reversing changes made to 32cab500ecc71d2975f5699c8a65c6debb29cfbe. * Revert "Merge pull request #744 from aviddiviner/logger-fix" This reverts commit c3bfd69303d0fdaf2d43a7ff07cc8ee45ec7bb3f, reversing changes made to 9177f01c2843b91820780197f521ba48554b9df3. * add custom Delims support * add some test for Delims * remove the empty line for import native package * remove unuseful comments --- fixtures/basic/hello.tmpl | 1 + gin.go | 18 ++++++++---- gin_test.go | 60 ++++++++++++++++++++++++++++++++++++++- render/html.go | 15 +++++++--- 4 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 fixtures/basic/hello.tmpl diff --git a/fixtures/basic/hello.tmpl b/fixtures/basic/hello.tmpl new file mode 100644 index 0000000..0767ef3 --- /dev/null +++ b/fixtures/basic/hello.tmpl @@ -0,0 +1 @@ +

Hello {[{.name}]}

\ No newline at end of file diff --git a/gin.go b/gin.go index 6a8e193..dcca2b3 100644 --- a/gin.go +++ b/gin.go @@ -45,6 +45,7 @@ type ( // Create an instance of Engine, by using New() or Default() Engine struct { RouterGroup + delims render.Delims HTMLRender render.HTMLRender allNoRoute HandlersChain allNoMethod HandlersChain @@ -119,6 +120,7 @@ func New() *Engine { UseRawPath: false, UnescapePathValues: true, trees: make(methodTrees, 0, 9), + delims: render.Delims{"{{", "}}"}, } engine.RouterGroup.engine = engine engine.pool.New = func() interface{} { @@ -138,21 +140,26 @@ func (engine *Engine) allocateContext() *Context { return &Context{engine: engine} } +func (engine *Engine) Delims(left, right string) *Engine { + engine.delims = render.Delims{left, right} + return engine +} + func (engine *Engine) LoadHTMLGlob(pattern string) { if IsDebugging() { - debugPrintLoadTemplate(template.Must(template.ParseGlob(pattern))) - engine.HTMLRender = render.HTMLDebug{Glob: pattern} + debugPrintLoadTemplate(template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseGlob(pattern))) + engine.HTMLRender = render.HTMLDebug{Glob: pattern, Delims: engine.delims} } else { - templ := template.Must(template.ParseGlob(pattern)) + templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseGlob(pattern)) engine.SetHTMLTemplate(templ) } } func (engine *Engine) LoadHTMLFiles(files ...string) { if IsDebugging() { - engine.HTMLRender = render.HTMLDebug{Files: files} + engine.HTMLRender = render.HTMLDebug{Files: files, Delims: engine.delims} } else { - templ := template.Must(template.ParseFiles(files...)) + templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseFiles(files...)) engine.SetHTMLTemplate(templ) } } @@ -161,6 +168,7 @@ func (engine *Engine) SetHTMLTemplate(templ *template.Template) { if len(engine.trees) > 0 { debugPrintWARNINGSetHTMLTemplate() } + engine.HTMLRender = render.HTMLProduction{Template: templ} } diff --git a/gin_test.go b/gin_test.go index cc24bc9..3ab4697 100644 --- a/gin_test.go +++ b/gin_test.go @@ -5,14 +5,60 @@ package gin import ( + "fmt" + "io/ioutil" + "net/http" "reflect" "testing" + "time" "github.com/stretchr/testify/assert" ) +func setupHTMLFiles(t *testing.T) func() { + go func() { + router := New() + router.Delims("{[{", "}]}") + router.LoadHTMLFiles("./fixtures/basic/hello.tmpl") + router.GET("/test", func(c *Context) { + c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) + }) + router.Run(":8888") + }() + t.Log("waiting 1 second for server startup") + time.Sleep(1 * time.Second) + return func() {} +} + +func setupHTMLGlob(t *testing.T) func() { + go func() { + router := New() + router.Delims("{[{", "}]}") + router.LoadHTMLGlob("./fixtures/basic/*") + router.GET("/test", func(c *Context) { + c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) + }) + router.Run(":8888") + }() + t.Log("waiting 1 second for server startup") + time.Sleep(1 * time.Second) + return func() {} +} + //TODO -// func (engine *Engine) LoadHTMLGlob(pattern string) { +func TestLoadHTMLGlob(t *testing.T) { + td := setupHTMLGlob(t) + res, err := http.Get("http://127.0.0.1:8888/test") + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "

Hello world

", string(resp[:])) + + td() +} + // func (engine *Engine) LoadHTMLFiles(files ...string) { // func (engine *Engine) RunTLS(addr string, cert string, key string) error { @@ -42,6 +88,18 @@ func TestCreateEngine(t *testing.T) { // SetMode(TestMode) // } +func TestLoadHTMLFiles(t *testing.T) { + td := setupHTMLFiles(t) + res, err := http.Get("http://127.0.0.1:8888/test") + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "

Hello world

", string(resp[:])) + td() +} + func TestLoadHTMLReleaseMode(t *testing.T) { } diff --git a/render/html.go b/render/html.go index a3cbda6..3ea5e08 100644 --- a/render/html.go +++ b/render/html.go @@ -10,17 +10,24 @@ import ( ) type ( + Delims struct { + Left string + Right string + } + HTMLRender interface { Instance(string, interface{}) Render } HTMLProduction struct { Template *template.Template + Delims Delims } HTMLDebug struct { - Files []string - Glob string + Files []string + Glob string + Delims Delims } HTML struct { @@ -49,10 +56,10 @@ func (r HTMLDebug) Instance(name string, data interface{}) Render { } func (r HTMLDebug) loadTemplate() *template.Template { if len(r.Files) > 0 { - return template.Must(template.ParseFiles(r.Files...)) + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).ParseFiles(r.Files...)) } if len(r.Glob) > 0 { - return template.Must(template.ParseGlob(r.Glob)) + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).ParseGlob(r.Glob)) } panic("the HTML debug render was created without files or glob pattern") } From 5eea51b6c9517e44a033af6f8b1ce4c48b08f398 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Fri, 2 Jun 2017 03:00:04 +0200 Subject: [PATCH 06/40] feat(context): add cast helpers to c.Keys (#856) * feat(context): add cast helpers to c.Keys * Add tests for cast helpers to c.Keys --- context.go | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ context_test.go | 79 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/context.go b/context.go index 7b57150..16cffec 100644 --- a/context.go +++ b/context.go @@ -187,6 +187,94 @@ func (c *Context) MustGet(key string) interface{} { panic("Key \"" + key + "\" does not exist") } +// GetString returns the value associated with the key as a string. +func (c *Context) GetString(key string) (s string) { + if val, ok := c.Get(key); ok && val != nil { + s, _ = val.(string) + } + return +} + +// GetBool returns the value associated with the key as a boolean. +func (c *Context) GetBool(key string) (b bool) { + if val, ok := c.Get(key); ok && val != nil { + b, _ = val.(bool) + } + return +} + +// GetInt returns the value associated with the key as an integer. +func (c *Context) GetInt(key string) (i int) { + if val, ok := c.Get(key); ok && val != nil { + i, _ = val.(int) + } + return +} + +// GetInt64 returns the value associated with the key as an integer. +func (c *Context) GetInt64(key string) (i64 int64) { + if val, ok := c.Get(key); ok && val != nil { + i64, _ = val.(int64) + } + return +} + +// GetFloat64 returns the value associated with the key as a float64. +func (c *Context) GetFloat64(key string) (f64 float64) { + if val, ok := c.Get(key); ok && val != nil { + f64, _ = val.(float64) + } + return +} + +// GetTime returns the value associated with the key as time. +func (c *Context) GetTime(key string) (t time.Time) { + if val, ok := c.Get(key); ok && val != nil { + t, _ = val.(time.Time) + } + return +} + +// GetDuration returns the value associated with the key as a duration. +func (c *Context) GetDuration(key string) (d time.Duration) { + if val, ok := c.Get(key); ok && val != nil { + d, _ = val.(time.Duration) + } + return +} + +// GetStringSlice returns the value associated with the key as a slice of strings. +func (c *Context) GetStringSlice(key string) (ss []string) { + if val, ok := c.Get(key); ok && val != nil { + ss, _ = val.([]string) + } + return +} + +// GetStringMap returns the value associated with the key as a map of interfaces. +func (c *Context) GetStringMap(key string) (sm map[string]interface{}) { + if val, ok := c.Get(key); ok && val != nil { + sm, _ = val.(map[string]interface{}) + } + return +} + +// GetStringMapString returns the value associated with the key as a map of strings. +func (c *Context) GetStringMapString(key string) (sms map[string]string) { + if val, ok := c.Get(key); ok && val != nil { + sms, _ = val.(map[string]string) + } + return +} + +// GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. +func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string) { + if val, ok := c.Get(key); ok && val != nil { + smss, _ = val.(map[string][]string) + } + return +} + /************************************/ /************ INPUT DATA ************/ /************************************/ diff --git a/context_test.go b/context_test.go index 131d891..7923a4b 100644 --- a/context_test.go +++ b/context_test.go @@ -168,6 +168,85 @@ func TestContextSetGetValues(t *testing.T) { } +func TestContextGetString(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.Set("string", "this is a string") + assert.Equal(t, "this is a string", c.GetString("string")) +} + +func TestContextSetGetBool(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.Set("bool", true) + assert.Equal(t, true, c.GetBool("bool")) +} + +func TestContextGetInt(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.Set("int", 1) + assert.Equal(t, 1, c.GetInt("int")) +} + +func TestContextGetInt64(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.Set("int64", int64(42424242424242)) + assert.Equal(t, int64(42424242424242), c.GetInt64("int64")) +} + +func TestContextGetFloat64(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.Set("float64", 4.2) + assert.Equal(t, 4.2, c.GetFloat64("float64")) +} + +func TestContextGetTime(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + t1, _ := time.Parse("1/2/2006 15:04:05", "01/01/2017 12:00:00") + c.Set("time", t1) + assert.Equal(t, t1, c.GetTime("time")) +} + +func TestContextGetDuration(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.Set("duration", time.Second) + assert.Equal(t, time.Second, c.GetDuration("duration")) +} + +func TestContextGetStringSlice(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.Set("slice", []string{"foo"}) + assert.Equal(t, []string{"foo"}, c.GetStringSlice("slice")) +} + +func TestContextGetStringMap(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + var m = make(map[string]interface{}) + m["foo"] = 1 + c.Set("map", m) + + assert.Equal(t, m, c.GetStringMap("map")) + assert.Equal(t, 1, c.GetStringMap("map")["foo"]) +} + +func TestContextGetStringMapString(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + var m = make(map[string]string) + m["foo"] = "bar" + c.Set("map", m) + + assert.Equal(t, m, c.GetStringMapString("map")) + assert.Equal(t, "bar", c.GetStringMapString("map")["foo"]) +} + +func TestContextGetStringMapStringSlice(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + var m = make(map[string][]string) + m["foo"] = []string{"foo"} + c.Set("map", m) + + assert.Equal(t, m, c.GetStringMapStringSlice("map")) + assert.Equal(t, []string{"foo"}, c.GetStringMapStringSlice("map")["foo"]) +} + func TestContextCopy(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) c.index = 2 From 3f95933c3d8ab010c1454b35b6dd8b534948f928 Mon Sep 17 00:00:00 2001 From: collinmsn <4130944@qq.com> Date: Fri, 2 Jun 2017 16:00:55 +0800 Subject: [PATCH 07/40] Add method to return main handler (#930) Fix #928 Method to get main handler is desired --- context.go | 5 +++++ context_test.go | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/context.go b/context.go index 16cffec..971675d 100644 --- a/context.go +++ b/context.go @@ -85,6 +85,11 @@ func (c *Context) HandlerName() string { return nameOfFunction(c.handlers.Last()) } +// Handler returns the main handler. +func (c *Context) Handler() HandlerFunc { + return c.handlers.Last() +} + /************************************/ /*********** FLOW CONTROL ***********/ /************************************/ diff --git a/context_test.go b/context_test.go index 7923a4b..66a55cd 100644 --- a/context_test.go +++ b/context_test.go @@ -12,6 +12,7 @@ import ( "mime/multipart" "net/http" "net/http/httptest" + "reflect" "strings" "testing" "time" @@ -277,6 +278,18 @@ func handlerNameTest(c *Context) { } +var handlerTest HandlerFunc = func(c *Context) { + +} + +func TestContextHandler(t *testing.T) { + c, _ := CreateTestContext(httptest.NewRecorder()) + c.handlers = HandlersChain{func(c *Context) {}, handlerTest} + + assert.Equal(t, reflect.ValueOf(handlerTest).Pointer(), reflect.ValueOf(c.Handler()).Pointer()) +} + + func TestContextQuery(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil) From 53295a75a40173538e28ef9c9a8b696b2a5f8117 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Tue, 6 Jun 2017 20:35:07 -0500 Subject: [PATCH 08/40] refactor: update protobuf version (#936) --- vendor/vendor.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/vendor.json b/vendor/vendor.json index 2bc5e19..cf9c860 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -16,10 +16,10 @@ "revisionTime": "2014-06-27T04:00:55Z" }, { - "checksumSHA1": "kBeNcaKk56FguvPSUCEaH6AxpRc=", + "checksumSHA1": "qlPUeFabwF4RKAOF1H+yBFU1Veg=", "path": "github.com/golang/protobuf/proto", - "revision": "8ee79997227bf9b34611aee7946ae64735e6fd93", - "revisionTime": "2016-11-17T03:31:26Z" + "revision": "5a0f697c9ed9d68fef0116532c6e05cfeae00e55", + "revisionTime": "2017-06-01T23:02:30Z" }, { "checksumSHA1": "9if9IBLsxkarJ804NPWAzgskIAk=", From d922143bc562320340be6caf2be6bd3d4da64d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Mon, 12 Jun 2017 10:40:15 +0800 Subject: [PATCH 09/40] lint code for import (#939) --- binding/binding_test.go | 3 +-- binding/json.go | 1 - binding/protobuf.go | 4 ++-- examples/app-engine/hello.go | 3 ++- gin_integration_test.go | 2 +- middleware_test.go | 1 - 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/binding/binding_test.go b/binding/binding_test.go index cf00594..d7cdf77 100644 --- a/binding/binding_test.go +++ b/binding/binding_test.go @@ -12,9 +12,8 @@ import ( "github.com/gin-gonic/gin/binding/example" "github.com/golang/protobuf/proto" - "github.com/ugorji/go/codec" - "github.com/stretchr/testify/assert" + "github.com/ugorji/go/codec" ) type FooStruct struct { diff --git a/binding/json.go b/binding/json.go index 6e53244..486b973 100644 --- a/binding/json.go +++ b/binding/json.go @@ -6,7 +6,6 @@ package binding import ( "encoding/json" - "net/http" ) diff --git a/binding/protobuf.go b/binding/protobuf.go index 9f95622..c7eb84e 100644 --- a/binding/protobuf.go +++ b/binding/protobuf.go @@ -5,10 +5,10 @@ package binding import ( - "github.com/golang/protobuf/proto" - "io/ioutil" "net/http" + + "github.com/golang/protobuf/proto" ) type protobufBinding struct{} diff --git a/examples/app-engine/hello.go b/examples/app-engine/hello.go index a5e1796..da7e4ae 100644 --- a/examples/app-engine/hello.go +++ b/examples/app-engine/hello.go @@ -1,8 +1,9 @@ package hello import ( - "github.com/gin-gonic/gin" "net/http" + + "github.com/gin-gonic/gin" ) // This function's name is a must. App Engine uses it to drive the requests properly. diff --git a/gin_integration_test.go b/gin_integration_test.go index b4bde1a..2674a61 100644 --- a/gin_integration_test.go +++ b/gin_integration_test.go @@ -6,12 +6,12 @@ import ( "io/ioutil" "net" "net/http" + "net/http/httptest" "os" "testing" "time" "github.com/stretchr/testify/assert" - "net/http/httptest" ) func testRequest(t *testing.T, url string) { diff --git a/middleware_test.go b/middleware_test.go index c77f827..0c56f4e 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -7,7 +7,6 @@ package gin import ( "errors" "strings" - "testing" "github.com/stretchr/testify/assert" From 4ad3baf44e2e00c9982b0ce24fb2283e2184105f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Mon, 12 Jun 2017 14:04:52 +0800 Subject: [PATCH 10/40] Add license for some files (#940) --- benchmarks_test.go | 4 ++++ binding/default_validator.go | 4 ++++ context_appengine.go | 4 ++++ fs.go | 4 ++++ gin_integration_test.go | 4 ++++ test_helpers.go | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/benchmarks_test.go b/benchmarks_test.go index ebe9804..a2c62ba 100644 --- a/benchmarks_test.go +++ b/benchmarks_test.go @@ -1,3 +1,7 @@ +// Copyright 2017 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 gin import ( diff --git a/binding/default_validator.go b/binding/default_validator.go index 760728b..19885f1 100644 --- a/binding/default_validator.go +++ b/binding/default_validator.go @@ -1,3 +1,7 @@ +// Copyright 2017 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 ( diff --git a/context_appengine.go b/context_appengine.go index d9cb22f..38c189a 100644 --- a/context_appengine.go +++ b/context_appengine.go @@ -1,5 +1,9 @@ // +build appengine +// Copyright 2017 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 gin func init() { diff --git a/fs.go b/fs.go index 320fea6..1264582 100644 --- a/fs.go +++ b/fs.go @@ -1,3 +1,7 @@ +// Copyright 2017 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 gin import ( diff --git a/gin_integration_test.go b/gin_integration_test.go index 2674a61..0a6351d 100644 --- a/gin_integration_test.go +++ b/gin_integration_test.go @@ -1,3 +1,7 @@ +// Copyright 2017 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 gin import ( diff --git a/test_helpers.go b/test_helpers.go index 5bb3fa7..e7dd55f 100644 --- a/test_helpers.go +++ b/test_helpers.go @@ -1,3 +1,7 @@ +// Copyright 2017 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 gin import ( From 53799774f45a119234a89f791565e53aa26b4482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Mon, 12 Jun 2017 17:01:09 +0800 Subject: [PATCH 11/40] unify license (#942) --- path.go | 7 +++---- path_test.go | 7 +++---- tree.go | 6 +++--- tree_test.go | 6 +++--- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/path.go b/path.go index 43cdd04..7478a43 100644 --- a/path.go +++ b/path.go @@ -1,7 +1,6 @@ -// Copyright 2013 Julien Schmidt. All rights reserved. -// Based on the path package, Copyright 2009 The Go Authors. -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// Copyright 2017 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 gin diff --git a/path_test.go b/path_test.go index 01cb758..0f2616c 100644 --- a/path_test.go +++ b/path_test.go @@ -1,7 +1,6 @@ -// Copyright 2013 Julien Schmidt. All rights reserved. -// Based on the path package, Copyright 2009 The Go Authors. -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// Copyright 2017 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 gin diff --git a/tree.go b/tree.go index eee6bab..98bb9cd 100644 --- a/tree.go +++ b/tree.go @@ -1,6 +1,6 @@ -// Copyright 2013 Julien Schmidt. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// Copyright 2017 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 gin diff --git a/tree_test.go b/tree_test.go index 22f0131..f70d6e3 100644 --- a/tree_test.go +++ b/tree_test.go @@ -1,6 +1,6 @@ -// Copyright 2013 Julien Schmidt. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// Copyright 2017 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 gin From 4a2b55037f082f5473a4881f72e6c4f27009b182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Tue, 13 Jun 2017 10:36:37 +0800 Subject: [PATCH 12/40] delete else keyword (#945) --- binding/binding.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/binding/binding.go b/binding/binding.go index d3a2c97..1dbf246 100644 --- a/binding/binding.go +++ b/binding/binding.go @@ -48,19 +48,19 @@ var ( func Default(method, contentType string) Binding { if method == "GET" { return Form - } else { - switch contentType { - case MIMEJSON: - return JSON - case MIMEXML, MIMEXML2: - return XML - case MIMEPROTOBUF: - return ProtoBuf - case MIMEMSGPACK, MIMEMSGPACK2: - return MsgPack - default: //case MIMEPOSTForm, MIMEMultipartPOSTForm: - return Form - } + } + + switch contentType { + case MIMEJSON: + return JSON + case MIMEXML, MIMEXML2: + return XML + case MIMEPROTOBUF: + return ProtoBuf + case MIMEMSGPACK, MIMEMSGPACK2: + return MsgPack + default: //case MIMEPOSTForm, MIMEMultipartPOSTForm: + return Form } } From 9ff8786b3d2746baca7dedd853fe1b5f27c0ab7c Mon Sep 17 00:00:00 2001 From: Eason Lin Date: Tue, 13 Jun 2017 10:37:20 +0800 Subject: [PATCH 13/40] Improve errors code coverage (#944) --- errors_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/errors_test.go b/errors_test.go index c9a3407..1aa0cdd 100644 --- a/errors_test.go +++ b/errors_test.go @@ -54,6 +54,13 @@ func TestError(t *testing.T) { "status": "200", "data": "some data", }) + + type customError struct { + status string + data string + } + err.SetMeta(customError{status: "200", data: "other data"}) + assert.Equal(t, err.JSON(), customError{status: "200", data: "other data"}) } func TestErrorSlice(t *testing.T) { From 1e1e4fc867b1729f600cf0e3ce096b815503e969 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 12 Jun 2017 21:50:42 -0500 Subject: [PATCH 14/40] Add Makefile to check the following thing (#947) * Add Makefile to check the following thing. * vet check * fmt check * embedmd check * misspell check Signed-off-by: Bo-Yi Wu * remove unused variable. Signed-off-by: Bo-Yi Wu --- .travis.yml | 11 ++++---- Makefile | 61 +++++++++++++++++++++++++++++++++++++++++ binding/form_mapping.go | 2 +- context.go | 2 +- context_test.go | 7 ++--- errors.go | 2 +- gin_integration_test.go | 2 +- 7 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 Makefile diff --git a/.travis.yml b/.travis.yml index 644a178..6532a33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,13 +10,14 @@ git: depth: 3 install: - - go get -v github.com/kardianos/govendor - - govendor sync - - go get -u github.com/campoy/embedmd + - make install script: - - embedmd -d README.md - - go test -v -covermode=count -coverprofile=coverage.out + - make vet + - make fmt-check + - make embedmd + - make misspell-check + - make test after_success: - bash <(curl -s https://codecov.io/bash) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9ba475a --- /dev/null +++ b/Makefile @@ -0,0 +1,61 @@ +GOFMT ?= gofmt "-s" +PACKAGES ?= $(shell go list ./... | grep -v /vendor/) +GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*") + +all: build + +install: deps + govendor sync + +.PHONY: test +test: + go test -v -covermode=count -coverprofile=coverage.out + +.PHONY: fmt +fmt: + $(GOFMT) -w $(GOFILES) + +.PHONY: fmt-check +fmt-check: + # get all go files and run go fmt on them + @diff=$$($(GOFMT) -d $(GOFILES)); \ + if [ -n "$$diff" ]; then \ + echo "Please run 'make fmt' and commit the result:"; \ + echo "$${diff}"; \ + exit 1; \ + fi; + +vet: + go vet $(PACKAGES) + +deps: + @hash govendor > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/kardianos/govendor; \ + fi + @hash embedmd > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/campoy/embedmd; \ + fi + +embedmd: + embedmd -d *.md + +.PHONY: lint +lint: + @hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/golang/lint/golint; \ + fi + for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done; + +.PHONY: misspell-check +misspell-check: + @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/client9/misspell/cmd/misspell; \ + fi + misspell -error $(GOFILES) + +.PHONY: misspell +misspell: + @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + go get -u github.com/client9/misspell/cmd/misspell; \ + fi + misspell -w $(GOFILES) diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 1af8165..34f1267 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -152,7 +152,7 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val if timeFormat == "" { return errors.New("Blank time format") } - + if val == "" { value.Set(reflect.ValueOf(time.Time{})) return nil diff --git a/context.go b/context.go index 971675d..c5ff793 100644 --- a/context.go +++ b/context.go @@ -87,7 +87,7 @@ func (c *Context) HandlerName() string { // Handler returns the main handler. func (c *Context) Handler() HandlerFunc { - return c.handlers.Last() + return c.handlers.Last() } /************************************/ diff --git a/context_test.go b/context_test.go index 66a55cd..e8cea05 100644 --- a/context_test.go +++ b/context_test.go @@ -283,13 +283,12 @@ var handlerTest HandlerFunc = func(c *Context) { } func TestContextHandler(t *testing.T) { - c, _ := CreateTestContext(httptest.NewRecorder()) - c.handlers = HandlersChain{func(c *Context) {}, handlerTest} + c, _ := CreateTestContext(httptest.NewRecorder()) + c.handlers = HandlersChain{func(c *Context) {}, handlerTest} - assert.Equal(t, reflect.ValueOf(handlerTest).Pointer(), reflect.ValueOf(c.Handler()).Pointer()) + assert.Equal(t, reflect.ValueOf(handlerTest).Pointer(), reflect.ValueOf(c.Handler()).Pointer()) } - func TestContextQuery(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil) diff --git a/errors.go b/errors.go index 694b428..896af6f 100644 --- a/errors.go +++ b/errors.go @@ -80,7 +80,7 @@ func (msg *Error) IsType(flags ErrorType) bool { return (msg.Type & flags) > 0 } -// Returns a readonly copy filterd the byte. +// Returns a readonly copy filtered the byte. // ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic func (a errorMsgs) ByType(typ ErrorType) errorMsgs { if len(a) == 0 { diff --git a/gin_integration_test.go b/gin_integration_test.go index 0a6351d..f45dd6c 100644 --- a/gin_integration_test.go +++ b/gin_integration_test.go @@ -20,8 +20,8 @@ import ( func testRequest(t *testing.T, url string) { resp, err := http.Get(url) - defer resp.Body.Close() assert.NoError(t, err) + defer resp.Body.Close() body, ioerr := ioutil.ReadAll(resp.Body) assert.NoError(t, ioerr) From 9ee5afff482e1bade5ff6061cfbdf3e74f2089d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Tue, 13 Jun 2017 11:35:10 +0800 Subject: [PATCH 15/40] fix markdown render style (#943) --- ginS/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ginS/README.md b/ginS/README.md index ac563a2..ef9225e 100644 --- a/ginS/README.md +++ b/ginS/README.md @@ -1,4 +1,4 @@ -#Gin Default Server +# Gin Default Server This is API experiment for Gin. From 6dac8c8a486dab63a4198e8421a2ae6a263129b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Tue, 13 Jun 2017 11:36:05 +0800 Subject: [PATCH 16/40] delete else keyword (#948) --- gin.go | 4 ++-- tree.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gin.go b/gin.go index dcca2b3..992d2f1 100644 --- a/gin.go +++ b/gin.go @@ -326,8 +326,8 @@ func (engine *Engine) handleHTTPRequest(context *Context) { context.Next() context.writermem.WriteHeaderNow() return - - } else if httpMethod != "CONNECT" && path != "/" { + } + if httpMethod != "CONNECT" && path != "/" { if tsr && engine.RedirectTrailingSlash { redirectTrailingSlash(context) return diff --git a/tree.go b/tree.go index 98bb9cd..d8aa312 100644 --- a/tree.go +++ b/tree.go @@ -432,7 +432,8 @@ walk: // Outer loop for walking the tree if handlers = n.handlers; handlers != nil { return - } else if len(n.children) == 1 { + } + if len(n.children) == 1 { // No handle found. Check if a handle for this path + a // trailing slash exists for TSR recommendation n = n.children[0] From 1a627c24494bc5b50712234e1718b88e1e441b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Thu, 15 Jun 2017 10:14:25 +0800 Subject: [PATCH 17/40] fmt code style (#950) --- examples/realtime-advanced/routes.go | 1 - examples/realtime-advanced/stats.go | 12 +++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/realtime-advanced/routes.go b/examples/realtime-advanced/routes.go index b187756..86da9be 100644 --- a/examples/realtime-advanced/routes.go +++ b/examples/realtime-advanced/routes.go @@ -11,7 +11,6 @@ import ( ) func rateLimit(c *gin.Context) { - ip := c.ClientIP() value := int(ips.Add(ip, 1)) if value%50 == 0 { diff --git a/examples/realtime-advanced/stats.go b/examples/realtime-advanced/stats.go index 554ab86..4bca3ae 100644 --- a/examples/realtime-advanced/stats.go +++ b/examples/realtime-advanced/stats.go @@ -8,11 +8,13 @@ import ( "github.com/manucorporat/stats" ) -var ips = stats.New() -var messages = stats.New() -var users = stats.New() -var mutexStats sync.RWMutex -var savedStats map[string]uint64 +var ( + ips = stats.New() + messages = stats.New() + users = stats.New() + mutexStats sync.RWMutex + savedStats map[string]uint64 +) func statsWorker() { c := time.Tick(1 * time.Second) From 0681715dda0cb0df85cbaf9d877a53fe01c7b674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Fri, 16 Jun 2017 09:07:42 +0800 Subject: [PATCH 18/40] add Makefile for example (#951) --- examples/realtime-advanced/Makefile | 10 ++++++++++ examples/realtime-chat/Makefile | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 examples/realtime-advanced/Makefile create mode 100644 examples/realtime-chat/Makefile diff --git a/examples/realtime-advanced/Makefile b/examples/realtime-advanced/Makefile new file mode 100644 index 0000000..104ce80 --- /dev/null +++ b/examples/realtime-advanced/Makefile @@ -0,0 +1,10 @@ +all: deps build + +.PHONY: deps +deps: + go get -d -v github.com/dustin/go-broadcast/... + go get -d -v github.com/manucorporat/stats/... + +.PHONY: build +build: deps + go build -o realtime-advanced main.go rooms.go routes.go stats.go diff --git a/examples/realtime-chat/Makefile b/examples/realtime-chat/Makefile new file mode 100644 index 0000000..dea583d --- /dev/null +++ b/examples/realtime-chat/Makefile @@ -0,0 +1,9 @@ +all: deps build + +.PHONY: deps +deps: + go get -d -v github.com/dustin/go-broadcast/... + +.PHONY: build +build: deps + go build -o realtime-chat main.go rooms.go template.go From 3b8150c83c5304be4dd6b49f212cda6fe3aeed10 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Tue, 27 Jun 2017 22:54:42 +0200 Subject: [PATCH 19/40] Revert "unify license (#942)" This reverts commit 53799774f45a119234a89f791565e53aa26b4482. --- path.go | 7 ++++--- path_test.go | 7 ++++--- tree.go | 6 +++--- tree_test.go | 6 +++--- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/path.go b/path.go index 7478a43..43cdd04 100644 --- a/path.go +++ b/path.go @@ -1,6 +1,7 @@ -// Copyright 2017 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. +// Copyright 2013 Julien Schmidt. All rights reserved. +// Based on the path package, Copyright 2009 The Go Authors. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. package gin diff --git a/path_test.go b/path_test.go index 0f2616c..01cb758 100644 --- a/path_test.go +++ b/path_test.go @@ -1,6 +1,7 @@ -// Copyright 2017 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. +// Copyright 2013 Julien Schmidt. All rights reserved. +// Based on the path package, Copyright 2009 The Go Authors. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. package gin diff --git a/tree.go b/tree.go index d8aa312..ec9dd14 100644 --- a/tree.go +++ b/tree.go @@ -1,6 +1,6 @@ -// Copyright 2017 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. +// Copyright 2013 Julien Schmidt. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. package gin diff --git a/tree_test.go b/tree_test.go index f70d6e3..22f0131 100644 --- a/tree_test.go +++ b/tree_test.go @@ -1,6 +1,6 @@ -// Copyright 2017 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. +// Copyright 2013 Julien Schmidt. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. package gin From 80942e67a8fabde099edd7307245e69b42f52f2c Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Tue, 27 Jun 2017 22:58:49 +0200 Subject: [PATCH 20/40] docs(license): add julienschmidt/httprouter license URL --- path.go | 2 +- path_test.go | 2 +- tree.go | 2 +- tree_test.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/path.go b/path.go index 43cdd04..d7e7458 100644 --- a/path.go +++ b/path.go @@ -1,7 +1,7 @@ // Copyright 2013 Julien Schmidt. All rights reserved. // Based on the path package, Copyright 2009 The Go Authors. // Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// at https://github.com/julienschmidt/httprouter/blob/master/LICENSE. package gin diff --git a/path_test.go b/path_test.go index 01cb758..bf2e5f6 100644 --- a/path_test.go +++ b/path_test.go @@ -1,7 +1,7 @@ // Copyright 2013 Julien Schmidt. All rights reserved. // Based on the path package, Copyright 2009 The Go Authors. // Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// at https://github.com/julienschmidt/httprouter/blob/master/LICENSE package gin diff --git a/tree.go b/tree.go index ec9dd14..a39f43b 100644 --- a/tree.go +++ b/tree.go @@ -1,6 +1,6 @@ // Copyright 2013 Julien Schmidt. All rights reserved. // Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// at https://github.com/julienschmidt/httprouter/blob/master/LICENSE package gin diff --git a/tree_test.go b/tree_test.go index 22f0131..c0edd42 100644 --- a/tree_test.go +++ b/tree_test.go @@ -1,6 +1,6 @@ // Copyright 2013 Julien Schmidt. All rights reserved. // Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. +// at https://github.com/julienschmidt/httprouter/blob/master/LICENSE package gin From 0b3f6d13be802e727ce8324bbeb934d45e867a93 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Tue, 27 Jun 2017 23:03:29 +0200 Subject: [PATCH 21/40] docs(readme): switch back import from gopkg to github --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6d3ead..7a0df31 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ $ cat test.go ```go package main -import "gopkg.in/gin-gonic/gin.v1" +import "github.com/gin-gonic/gin" func main() { r := gin.Default() From dc016d0bcbaaae90af78e3038103fd77565d2959 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Tue, 27 Jun 2017 23:16:18 +0200 Subject: [PATCH 22/40] docs(readme): s/gopkg.in.../github.com.../ --- README.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7a0df31..7556d48 100644 --- a/README.md +++ b/README.md @@ -88,13 +88,13 @@ BenchmarkZeus_GithubAll | 2000 | 944234 | 300688 | 2648 1. Download and install it: ```sh -$ go get gopkg.in/gin-gonic/gin.v1 +$ go get github.com/gin-gonic/gin ``` 2. Import it in your code: ```go -import "gopkg.in/gin-gonic/gin.v1" +import "github.com/gin-gonic/gin" ``` 3. (Optional) Import `net/http`. This is required for example if using constants such as `http.StatusOK`. @@ -103,14 +103,6 @@ import "gopkg.in/gin-gonic/gin.v1" import "net/http" ``` -4. (Optional) Use latest changes (note: they may be broken and/or unstable): - -```sh -$ GIN_PATH=$GOPATH/src/gopkg.in/gin-gonic/gin.v1 -$ git -C $GIN_PATH checkout develop -$ git -C $GIN_PATH pull origin develop -``` - ## API Examples ### Using GET, POST, PUT, PATCH, DELETE and OPTIONS @@ -457,7 +449,7 @@ func startPage(c *gin.Context) { package main import ( - "gopkg.in/gin-gonic/gin.v1" + "github.com/gin-gonic/gin" ) type LoginForm struct { From 9a79e3f14410ede6073c587b31d72630444896d0 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Tue, 27 Jun 2017 23:17:02 +0200 Subject: [PATCH 23/40] fix(import): switch sse import from gopkg to github --- context.go | 2 +- context_test.go | 2 +- middleware_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/context.go b/context.go index c5ff793..7e86212 100644 --- a/context.go +++ b/context.go @@ -16,9 +16,9 @@ import ( "strings" "time" + "github.com/gin-contrib/sse" "github.com/gin-gonic/gin/binding" "github.com/gin-gonic/gin/render" - "gopkg.in/gin-contrib/sse.v0" ) // Content-Type MIME of the most common data formats diff --git a/context_test.go b/context_test.go index e8cea05..9a294c5 100644 --- a/context_test.go +++ b/context_test.go @@ -17,9 +17,9 @@ import ( "testing" "time" + "github.com/gin-contrib/sse" "github.com/stretchr/testify/assert" "golang.org/x/net/context" - "gopkg.in/gin-contrib/sse.v0" ) var _ context.Context = &Context{} diff --git a/middleware_test.go b/middleware_test.go index 0c56f4e..5572e79 100644 --- a/middleware_test.go +++ b/middleware_test.go @@ -9,8 +9,8 @@ import ( "strings" "testing" + "github.com/gin-contrib/sse" "github.com/stretchr/testify/assert" - "gopkg.in/gin-contrib/sse.v0" ) func TestMiddlewareGeneralCase(t *testing.T) { From c8af2768650c3ee5eb43ab774aa9169bd836c5a8 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Tue, 27 Jun 2017 23:31:11 +0200 Subject: [PATCH 24/40] chore(vendor): update vendor.json --- vendor/vendor.json | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/vendor/vendor.json b/vendor/vendor.json index cf9c860..e520540 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1,5 +1,5 @@ { - "comment": "v1.1.4", + "comment": "v1.2", "ignore": "test", "package": [ { @@ -15,6 +15,18 @@ "revision": "3bdf6d4a7164a50bc19d5f230e2981d87d2584f1", "revisionTime": "2014-06-27T04:00:55Z" }, + { + "checksumSHA1": "QeKwBtN2df+j+4stw3bQJ6yO4EY=", + "path": "github.com/gin-contrib/sse", + "revision": "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae", + "revisionTime": "2017-01-09T09:34:21Z" + }, + { + "checksumSHA1": "FJKrZuFmeLJp8HDeJc6UkIDBPUw=", + "path": "github.com/gin-gonic/autotls", + "revision": "5b3297bdcee778ff3bbdc99ab7c41e1c2677d22d", + "revisionTime": "2017-04-16T09:39:34Z" + }, { "checksumSHA1": "qlPUeFabwF4RKAOF1H+yBFU1Veg=", "path": "github.com/golang/protobuf/proto", @@ -53,6 +65,18 @@ "revision": "c88ee250d0221a57af388746f5cf03768c21d6e2", "revisionTime": "2017-02-15T20:11:44Z" }, + { + "checksumSHA1": "W0j4I7QpxXlChjyhAojZmFjU6Bg=", + "path": "golang.org/x/crypto/acme", + "revision": "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d", + "revisionTime": "2017-06-19T06:03:41Z" + }, + { + "checksumSHA1": "TrKJW+flz7JulXU3sqnBJjGzgQc=", + "path": "golang.org/x/crypto/acme/autocert", + "revision": "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d", + "revisionTime": "2017-06-19T06:03:41Z" + }, { "checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=", "comment": "release-branch.go1.7", @@ -61,17 +85,11 @@ "revisionTime": "2016-10-18T08:54:36Z" }, { - "checksumSHA1": "/oZpHfYc+ZgOwYAhlvcMhmETYpw=", + "checksumSHA1": "TVEkpH3gq84iQ39I4R+mlDwjuVI=", "path": "golang.org/x/sys/unix", "revision": "99f16d856c9836c42d24e7ab64ea72916925fa97", "revisionTime": "2017-03-08T15:04:45Z" }, - { - "checksumSHA1": "pyAPYrymvmZl0M/Mr4yfjOQjA8I=", - "path": "gopkg.in/gin-contrib/sse.v0", - "revision": "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae", - "revisionTime": "2017-01-09T09:34:21Z" - }, { "checksumSHA1": "39V1idWER42Lmcmg2Uy40wMzOlo=", "comment": "v8.18.1", From cbf414d6002e3e088ad433efb288433513a48319 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Wed, 28 Jun 2017 00:44:33 +0200 Subject: [PATCH 25/40] docs(readme): add example on custom delims #860 --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 7556d48..3397d6b 100644 --- a/README.md +++ b/README.md @@ -620,6 +620,14 @@ func main() { } ``` +You may use custom delims + +```go + r := gin.Default() + r.Delims("{[{", "}]}") + r.LoadHTMLGlob("/path/to/templates")) +``` + ### Multitemplate Gin allow by default use only one html.Template. Check [a multitemplate render](https://github.com/gin-contrib/multitemplate) for using features like go 1.6 `block template`. From 68aa2c38da9582aa37b3ee3b099251e5bfee3598 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Wed, 28 Jun 2017 00:46:35 +0200 Subject: [PATCH 26/40] fix(context): switch deprecated bindwith for mustbindwith --- context.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/context.go b/context.go index f7c4f17..5c4d27d 100644 --- a/context.go +++ b/context.go @@ -430,12 +430,12 @@ func (c *Context) MultipartForm() (*multipart.Form, error) { // Like ParseBody() but this method also writes a 400 error if the json is not valid. func (c *Context) Bind(obj interface{}) error { b := binding.Default(c.Request.Method, c.ContentType()) - return c.BindWith(obj, b) + return c.MustBindWith(obj, b) } -// BindJSON is a shortcut for c.BindWith(obj, binding.JSON) +// BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON) func (c *Context) BindJSON(obj interface{}) error { - return c.BindWith(obj, binding.JSON) + return c.MustBindWith(obj, binding.JSON) } // MustBindWith binds the passed struct pointer using the specified binding From 544b8b4dc815f0ff2f409e311bf8bf9c38eca163 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Wed, 28 Jun 2017 00:53:28 +0200 Subject: [PATCH 27/40] docs(readme): switch deprecated bindwith for mustbindwith --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3397d6b..1276c2e 100644 --- a/README.md +++ b/README.md @@ -461,7 +461,7 @@ func main() { router := gin.Default() router.POST("/login", func(c *gin.Context) { // you can bind multipart form with explicit binding declaration: - // c.BindWith(&form, binding.Form) + // c.MustBindWith(&form, binding.Form) // or you can simply use autobinding with Bind method: var form LoginForm // in this case proper binding will be automatically selected From 470fe6263724af05ac10a0d6d23e27494a53646e Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Wed, 28 Jun 2017 00:53:53 +0200 Subject: [PATCH 28/40] docs(changelog): update v1.2 changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 441df24..aba6417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,20 @@ - [NEW] Add support for Let's Encrypt via gin-gonic/autotls - [NEW] Improve README examples and add extra at examples folder - [NEW] Improved support with App Engine +- [NEW] Add custom template delimiters, see #860 +- [NEW] Add \*context.Handler(), see #928 - [NEW] Add \*context.GetRawData() - [NEW] Add \*context.GetHeader() (request) - [NEW] Add \*context.AbortWithStatusJSON() (JSON content type) +- [NEW] Add \*context.Keys type cast helpers +- [NEW] Add \*context.ShouldBindWith() +- [NEW] Add \*context.MustBindWith() +- [DEPRECATE] On next release: \*context.BindWith(), see #855 - [FIX] Refactor render - [FIX] Reworked tests - [FIX] logger now supports cygwin - [FIX] Use X-Forwarded-For before X-Real-Ip +- [FIX] time.Time binding (#904) ### Gin 1.1.4 From e38c36ee0d6d2131b263b571a8a7e2e8e2a708dc Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Fri, 30 Jun 2017 21:22:40 +0200 Subject: [PATCH 29/40] Made funMaps for the templates configurable and hot-reloadable --- gin.go | 18 ++++++++++++------ render/html.go | 14 +++++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/gin.go b/gin.go index 992d2f1..c4118a4 100644 --- a/gin.go +++ b/gin.go @@ -47,6 +47,7 @@ type ( RouterGroup delims render.Delims HTMLRender render.HTMLRender + FuncMap template.FuncMap allNoRoute HandlersChain allNoMethod HandlersChain noRoute HandlersChain @@ -112,6 +113,7 @@ func New() *Engine { basePath: "/", root: true, }, + FuncMap: template.FuncMap{}, RedirectTrailingSlash: true, RedirectFixedPath: false, HandleMethodNotAllowed: false, @@ -147,19 +149,19 @@ func (engine *Engine) Delims(left, right string) *Engine { func (engine *Engine) LoadHTMLGlob(pattern string) { if IsDebugging() { - debugPrintLoadTemplate(template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseGlob(pattern))) - engine.HTMLRender = render.HTMLDebug{Glob: pattern, Delims: engine.delims} + debugPrintLoadTemplate(template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseGlob(pattern))) + engine.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: engine.FuncMap, Delims: engine.delims} } else { - templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseGlob(pattern)) + templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseGlob(pattern)) engine.SetHTMLTemplate(templ) } } func (engine *Engine) LoadHTMLFiles(files ...string) { if IsDebugging() { - engine.HTMLRender = render.HTMLDebug{Files: files, Delims: engine.delims} + engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims} } else { - templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseFiles(files...)) + templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseFiles(files...)) engine.SetHTMLTemplate(templ) } } @@ -169,7 +171,11 @@ func (engine *Engine) SetHTMLTemplate(templ *template.Template) { debugPrintWARNINGSetHTMLTemplate() } - engine.HTMLRender = render.HTMLProduction{Template: templ} + engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)} +} + +func (engine *Engine) SetFuncMap(funcMap template.FuncMap) { + engine.FuncMap = funcMap } // NoRoute adds handlers for NoRoute. It return a 404 code by default. diff --git a/render/html.go b/render/html.go index 3ea5e08..cf91219 100644 --- a/render/html.go +++ b/render/html.go @@ -25,9 +25,10 @@ type ( } HTMLDebug struct { - Files []string - Glob string - Delims Delims + Files []string + Glob string + Delims Delims + FuncMap template.FuncMap } HTML struct { @@ -55,11 +56,14 @@ func (r HTMLDebug) Instance(name string, data interface{}) Render { } } func (r HTMLDebug) loadTemplate() *template.Template { + if r.FuncMap == nil { + r.FuncMap = template.FuncMap{} + } if len(r.Files) > 0 { - return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).ParseFiles(r.Files...)) + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseFiles(r.Files...)) } if len(r.Glob) > 0 { - return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).ParseGlob(r.Glob)) + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseGlob(r.Glob)) } panic("the HTML debug render was created without files or glob pattern") } From a40699e07f71b33c3c4a064af3468c09d333688c Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sun, 2 Jul 2017 12:38:05 +0800 Subject: [PATCH 30/40] add FuncMap testing Signed-off-by: Bo-Yi Wu --- fixtures/basic/raw.tmpl | 1 + gin_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 fixtures/basic/raw.tmpl diff --git a/fixtures/basic/raw.tmpl b/fixtures/basic/raw.tmpl new file mode 100644 index 0000000..8bc7570 --- /dev/null +++ b/fixtures/basic/raw.tmpl @@ -0,0 +1 @@ +Date: {[{.now | formatAsDate}]} diff --git a/gin_test.go b/gin_test.go index 3ab4697..3cd134c 100644 --- a/gin_test.go +++ b/gin_test.go @@ -6,6 +6,7 @@ package gin import ( "fmt" + "html/template" "io/ioutil" "net/http" "reflect" @@ -15,6 +16,11 @@ import ( "github.com/stretchr/testify/assert" ) +func formatAsDate(t time.Time) string { + year, month, day := t.Date() + return fmt.Sprintf("%d/%02d/%02d", year, month, day) +} + func setupHTMLFiles(t *testing.T) func() { go func() { router := New() @@ -32,12 +38,21 @@ func setupHTMLFiles(t *testing.T) func() { func setupHTMLGlob(t *testing.T) func() { go func() { + SetMode(DebugMode) router := New() router.Delims("{[{", "}]}") + router.SetFuncMap(template.FuncMap{ + "formatAsDate": formatAsDate, + }) router.LoadHTMLGlob("./fixtures/basic/*") router.GET("/test", func(c *Context) { c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) }) + router.GET("/raw", func(c *Context) { + c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{ + "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), + }) + }) router.Run(":8888") }() t.Log("waiting 1 second for server startup") @@ -59,6 +74,20 @@ func TestLoadHTMLGlob(t *testing.T) { td() } +func TestLoadHTMLFromFuncMap(t *testing.T) { + time.Now() + td := setupHTMLGlob(t) + res, err := http.Get("http://127.0.0.1:8888/raw") + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "Date: 2017/07/01\n", string(resp[:])) + + td() +} + // func (engine *Engine) LoadHTMLFiles(files ...string) { // func (engine *Engine) RunTLS(addr string, cert string, key string) error { From 6d071c1d360141168de629c4b686175df2efa61f Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sun, 2 Jul 2017 13:06:43 +0800 Subject: [PATCH 31/40] Add load html file and func map. Signed-off-by: Bo-Yi Wu --- gin_test.go | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/gin_test.go b/gin_test.go index 3cd134c..bdf5a9a 100644 --- a/gin_test.go +++ b/gin_test.go @@ -23,12 +23,21 @@ func formatAsDate(t time.Time) string { func setupHTMLFiles(t *testing.T) func() { go func() { + SetMode(TestMode) router := New() router.Delims("{[{", "}]}") - router.LoadHTMLFiles("./fixtures/basic/hello.tmpl") + router.SetFuncMap(template.FuncMap{ + "formatAsDate": formatAsDate, + }) + router.LoadHTMLFiles("./fixtures/basic/hello.tmpl", "./fixtures/basic/raw.tmpl") router.GET("/test", func(c *Context) { c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) }) + router.GET("/raw", func(c *Context) { + c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{ + "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), + }) + }) router.Run(":8888") }() t.Log("waiting 1 second for server startup") @@ -74,7 +83,7 @@ func TestLoadHTMLGlob(t *testing.T) { td() } -func TestLoadHTMLFromFuncMap(t *testing.T) { +func TestLoadHTMLGlobFromFuncMap(t *testing.T) { time.Now() td := setupHTMLGlob(t) res, err := http.Get("http://127.0.0.1:8888/raw") @@ -129,6 +138,20 @@ func TestLoadHTMLFiles(t *testing.T) { td() } +func TestLoadHTMLFilesFuncMap(t *testing.T) { + time.Now() + td := setupHTMLFiles(t) + res, err := http.Get("http://127.0.0.1:8888/raw") + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "Date: 2017/07/01\n", string(resp[:])) + + td() +} + func TestLoadHTMLReleaseMode(t *testing.T) { } From 76a63b257d9989ec4eb365c6b984246944f0305a Mon Sep 17 00:00:00 2001 From: Eason Lin Date: Sun, 2 Jul 2017 15:29:29 +0800 Subject: [PATCH 32/40] Improve debug code coverage (#963) * Improve debug.go code coverage * lint code --- debug_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/debug_test.go b/debug_test.go index deceaa6..a402ba7 100644 --- a/debug_test.go +++ b/debug_test.go @@ -7,6 +7,7 @@ package gin import ( "bytes" "errors" + "html/template" "io" "log" "os" @@ -66,6 +67,25 @@ func TestDebugPrintRoutes(t *testing.T) { assert.Regexp(t, `^\[GIN-debug\] GET /path/to/route/:param --> (.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest \(2 handlers\)\n$`, w.String()) } +func TestDebugPrintLoadTemplate(t *testing.T) { + var w bytes.Buffer + setup(&w) + defer teardown() + + templ := template.Must(template.New("").Delims("{[{", "}]}").ParseGlob("./fixtures/basic/*")) + debugPrintLoadTemplate(templ) + assert.Equal(t, w.String(), "[GIN-debug] Loaded HTML Templates (2): \n\t- \n\t- hello.tmpl\n\n") +} + +func TestDebugPrintWARNINGSetHTMLTemplate(t *testing.T) { + var w bytes.Buffer + setup(&w) + defer teardown() + + debugPrintWARNINGSetHTMLTemplate() + assert.Equal(t, w.String(), "[GIN-debug] [WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called\nat initialization. ie. before any route is registered or the router is listening in a socket:\n\n\trouter := gin.Default()\n\trouter.SetHTMLTemplate(template) // << good place\n\n") +} + func setup(w io.Writer) { SetMode(DebugMode) log.SetOutput(w) From bea012a17ffee4cc1f16352cf567e7791f226530 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sun, 2 Jul 2017 10:55:39 +0200 Subject: [PATCH 33/40] docs(changelog): add #962 template func maps --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aba6417..ee485ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - [NEW] Improve README examples and add extra at examples folder - [NEW] Improved support with App Engine - [NEW] Add custom template delimiters, see #860 +- [NEW] Add Template Func Maps, see #962 - [NEW] Add \*context.Handler(), see #928 - [NEW] Add \*context.GetRawData() - [NEW] Add \*context.GetHeader() (request) @@ -14,6 +15,7 @@ - [NEW] Add \*context.Keys type cast helpers - [NEW] Add \*context.ShouldBindWith() - [NEW] Add \*context.MustBindWith() +- [NEW] Add \*engine.SetFuncMap() - [DEPRECATE] On next release: \*context.BindWith(), see #855 - [FIX] Refactor render - [FIX] Reworked tests From 2535b46bab759cf0a43a7e0b9c6e6621e89eca4b Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sun, 2 Jul 2017 11:07:22 +0200 Subject: [PATCH 34/40] docs(readme): add template func maps example copied from gin_test.go @appleboy commit --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index 1276c2e..029606b 100644 --- a/README.md +++ b/README.md @@ -628,6 +628,46 @@ You may use custom delims r.LoadHTMLGlob("/path/to/templates")) ``` +#### Add custom template funcs + +main.go + +```go + ... + + func formatAsDate(t time.Time) string { + year, month, day := t.Date() + return fmt.Sprintf("%d/%02d/%02d", year, month, day) + } + + ... + + router.SetFuncMap(template.FuncMap{ + "formatAsDate": formatAsDate, + }) + + ... + + router.GET("/raw", func(c *Context) { + c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{ + "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), + }) + }) + + ... +``` + +raw.tmpl + +```html +Date: {[{.now | formatAsDate}]} +``` + +Result: +``` +Date: 2017/07/01 +``` + ### Multitemplate Gin allow by default use only one html.Template. Check [a multitemplate render](https://github.com/gin-contrib/multitemplate) for using features like go 1.6 `block template`. From a8ea89ea385b2e11f0147006147649d432919121 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sun, 2 Jul 2017 11:17:42 +0200 Subject: [PATCH 35/40] fix(test): remove wildcard loadtemplate --- debug_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug_test.go b/debug_test.go index a402ba7..c30081c 100644 --- a/debug_test.go +++ b/debug_test.go @@ -72,7 +72,7 @@ func TestDebugPrintLoadTemplate(t *testing.T) { setup(&w) defer teardown() - templ := template.Must(template.New("").Delims("{[{", "}]}").ParseGlob("./fixtures/basic/*")) + templ := template.Must(template.New("").Delims("{[{", "}]}").ParseGlob("./fixtures/basic/hello.tmpl")) debugPrintLoadTemplate(templ) assert.Equal(t, w.String(), "[GIN-debug] Loaded HTML Templates (2): \n\t- \n\t- hello.tmpl\n\n") } From 0cbf0f48aaa3573141922d9dbdc57a15ea3aa626 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sun, 2 Jul 2017 11:58:19 +0200 Subject: [PATCH 36/40] docs(readme): update contribution guide - change new prs base branch from develop to master --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 029606b..76ec40d 100644 --- a/README.md +++ b/README.md @@ -963,7 +963,7 @@ func main() { - Please provide source code and commit sha if you found a bug. - Review existing issues and provide feedback or react to them. - With pull requests: - - Open your pull request against develop + - Open your pull request against master - Your pull request should have no more than two commits, if not you should squash them. - It should pass all tests in the available continuous integrations systems such as TravisCI. - You should add/modify tests to cover your proposed code changes. From 55dd6364cbdf2a4db3c2edbabc5377a708d5d282 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sun, 2 Jul 2017 12:23:54 +0200 Subject: [PATCH 37/40] docs(readme): update to color logo --- README.md | 2 +- logo.jpg | Bin 12200 -> 0 bytes logo.png | Bin 0 -> 16831 bytes 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 logo.jpg create mode 100644 logo.png diff --git a/README.md b/README.md index 76ec40d..e35c2f9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Gin Web Framework - + [![Build Status](https://travis-ci.org/gin-gonic/gin.svg)](https://travis-ci.org/gin-gonic/gin) [![codecov](https://codecov.io/gh/gin-gonic/gin/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-gonic/gin) diff --git a/logo.jpg b/logo.jpg deleted file mode 100644 index bb51852e49aa24ab09ff7826b1f6c3dfdc99b16f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12200 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 Date: Sun, 2 Jul 2017 12:27:38 +0200 Subject: [PATCH 38/40] docs(readme): make logo smaller as before --- logo.png | Bin 16831 -> 21516 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/logo.png b/logo.png index c58c79864852b50763c2aab9106dd9ebd2290cf9..5f4888c4ba851dbfbae9dd1eb77da5e153b39048 100644 GIT binary patch literal 21516 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 DV^9bK literal 16831 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 Date: Sun, 2 Jul 2017 12:29:50 +0200 Subject: [PATCH 39/40] docs(readme): compress logo size --- logo.png | Bin 21516 -> 7987 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/logo.png b/logo.png index 5f4888c4ba851dbfbae9dd1eb77da5e153b39048..20b4fd6b5615c2d39231e7ad991abd5ce67ebcc8 100644 GIT binary patch literal 7987 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 literal 21516 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 DV^9bK From 5ce686113b29d5b275bcf3a46d5896a26ec23595 Mon Sep 17 00:00:00 2001 From: Javier Provecho Fernandez Date: Sun, 2 Jul 2017 12:46:36 +0200 Subject: [PATCH 40/40] docs(readme): add example on using vendor tool for version lock --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.md b/README.md index e35c2f9..494cc8b 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,38 @@ import "github.com/gin-gonic/gin" import "net/http" ``` +### Use a vendor tool like [Govendor](https://github.com/kardianos/govendor) + +1. `go get` govendor + +```sh +$ go get github.com/kardianos/govendor +``` +2. Create your project folder and `cd` inside + +```sh +$ mkdir -p ~/go/src/github.com/myusername/project && cd "$_" +``` + +3. Vendor init your project and add gin + +```sh +$ govendor init +$ govendor add github.com/gin-gonic/gin@v1.2 +``` + +4. Copy a starting template inside your project + +```sh +$ cp ~/go/src/github.com/gin-gonic/gin/examples/basic/* . +``` + +5. Run your project + +```sh +$ go run main.go +``` + ## API Examples ### Using GET, POST, PUT, PATCH, DELETE and OPTIONS