From 4b5ec517daa247f8f3bd0448f82ca55c0d14fa0a Mon Sep 17 00:00:00 2001 From: Eason Lin Date: Mon, 14 Aug 2017 11:02:31 +0800 Subject: [PATCH 01/14] fix(test): only check Location header (#1064) * fix(test): only check Location header * fix(test): rename field * fix(test): not export field --- routes_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/routes_test.go b/routes_test.go index 41693eed..b44b6431 100644 --- a/routes_test.go +++ b/routes_test.go @@ -356,25 +356,25 @@ func TestRouterNotFound(t *testing.T) { router.GET("/", func(c *Context) {}) testRoutes := []struct { - route string - code int - header string + route string + code int + location string }{ - {"/path/", 301, "map[Location:[/path]]"}, // TSR -/ - {"/dir", 301, "map[Location:[/dir/]]"}, // TSR +/ - {"", 301, "map[Location:[/]]"}, // TSR +/ - {"/PATH", 301, "map[Location:[/path]]"}, // Fixed Case - {"/DIR/", 301, "map[Location:[/dir/]]"}, // Fixed Case - {"/PATH/", 301, "map[Location:[/path]]"}, // Fixed Case -/ - {"/DIR", 301, "map[Location:[/dir/]]"}, // Fixed Case +/ - {"/../path", 301, "map[Location:[/path]]"}, // CleanPath - {"/nope", 404, ""}, // NotFound + {"/path/", 301, "/path"}, // TSR -/ + {"/dir", 301, "/dir/"}, // TSR +/ + {"", 301, "/"}, // TSR +/ + {"/PATH", 301, "/path"}, // Fixed Case + {"/DIR/", 301, "/dir/"}, // Fixed Case + {"/PATH/", 301, "/path"}, // Fixed Case -/ + {"/DIR", 301, "/dir/"}, // Fixed Case +/ + {"/../path", 301, "/path"}, // CleanPath + {"/nope", 404, ""}, // NotFound } for _, tr := range testRoutes { w := performRequest(router, "GET", tr.route) assert.Equal(t, w.Code, tr.code) if w.Code != 404 { - assert.Equal(t, fmt.Sprint(w.Header()), tr.header) + assert.Equal(t, fmt.Sprint(w.Header().Get("Location")), tr.location) } } From 25d20a4463a63083b85bb2d8ebb99c7f638920f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Mon, 14 Aug 2017 12:21:05 +0800 Subject: [PATCH 02/14] merge args if it have same type (#1059) --- gin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gin.go b/gin.go index 8347ce22..e2c0105d 100644 --- a/gin.go +++ b/gin.go @@ -268,7 +268,7 @@ func (engine *Engine) Run(addr ...string) (err error) { // RunTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. // It is a shortcut for http.ListenAndServeTLS(addr, certFile, keyFile, router) // Note: this method will block the calling goroutine indefinitely unless an error happens. -func (engine *Engine) RunTLS(addr string, certFile string, keyFile string) (err error) { +func (engine *Engine) RunTLS(addr, certFile, keyFile string) (err error) { debugPrint("Listening and serving HTTPS on %s\n", addr) defer func() { debugPrintError(err) }() From 52c2ed34b3256727a0aeac5e57129eb788bac045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Mon, 14 Aug 2017 14:34:29 +0800 Subject: [PATCH 03/14] log format (#1060) --- logger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logger.go b/logger.go index 470e4bb6..7edae415 100644 --- a/logger.go +++ b/logger.go @@ -102,7 +102,7 @@ func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { path = path + "?" + raw } - fmt.Fprintf(out, "[GIN] %v |%s %3d %s| %13v | %15s |%s %s %-7s %s\n%s", + fmt.Fprintf(out, "[GIN] %v |%s %3d %s| %13v | %15s |%s %-7s %s %s\n%s", end.Format("2006/01/02 - 15:04:05"), statusColor, statusCode, reset, latency, From ecae34c4e186d5190ca38ac225ce03e3894d99b7 Mon Sep 17 00:00:00 2001 From: keke <19yamashita15@gmail.com> Date: Wed, 16 Aug 2017 10:50:43 +0900 Subject: [PATCH 04/14] fix 200 to http.Status (#1067) --- examples/app-engine/hello.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/app-engine/hello.go b/examples/app-engine/hello.go index da7e4ae4..f569dadb 100644 --- a/examples/app-engine/hello.go +++ b/examples/app-engine/hello.go @@ -13,10 +13,10 @@ func init() { // Define your handlers r.GET("/", func(c *gin.Context) { - c.String(200, "Hello World!") + c.String(http.StatusOK, "Hello World!") }) r.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") + c.String(http.StatusOK, "pong") }) // Handle all requests using net/http From a8fa424ae529397d4a0f2a1f9fda8031851a3269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Wed, 16 Aug 2017 11:55:50 +0800 Subject: [PATCH 05/14] update comment (#1057) --- auth.go | 8 ++++---- context.go | 29 ++++++++++++++--------------- errors.go | 6 +++--- fs.go | 4 ++-- gin.go | 4 ++-- logger.go | 10 +++++----- path.go | 4 ++-- recovery.go | 2 +- render/data.go | 2 +- response_writer.go | 6 +++--- routergroup.go | 18 +++++++++--------- tree.go | 2 +- utils.go | 2 +- 13 files changed, 48 insertions(+), 49 deletions(-) diff --git a/auth.go b/auth.go index c214e213..e7c46bf6 100644 --- a/auth.go +++ b/auth.go @@ -10,10 +10,10 @@ import ( "strconv" ) -// AuthUserKey is the cookie name for user credential in basic auth +// AuthUserKey is the cookie name for user credential in basic auth. const AuthUserKey = "user" -// Accounts defines a key/value for user/pass list of authorized logins +// Accounts defines a key/value for user/pass list of authorized logins. type Accounts map[string]string type authPair struct { @@ -56,7 +56,7 @@ func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc { } // The user credentials was found, set user's id to key AuthUserKey in this context, the user's id can be read later using - // c.MustGet(gin.AuthUserKey) + // c.MustGet(gin.AuthUserKey). c.Set(AuthUserKey, user) } } @@ -90,6 +90,6 @@ func secureCompare(given, actual string) bool { if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 { return subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1 } - // Securely compare actual to itself to keep constant time, but always return false + // Securely compare actual to itself to keep constant time, but always return false. return subtle.ConstantTimeCompare([]byte(actual), []byte(actual)) == 1 && false } diff --git a/context.go b/context.go index 895ba7a1..497cbfd6 100644 --- a/context.go +++ b/context.go @@ -22,7 +22,7 @@ import ( "github.com/gin-gonic/gin/render" ) -// Content-Type MIME of the most common data formats +// Content-Type MIME of the most common data formats. const ( MIMEJSON = binding.MIMEJSON MIMEHTML = binding.MIMEHTML @@ -51,13 +51,13 @@ type Context struct { engine *Engine - // Keys is a key/value pair exclusively for the context of each request + // Keys is a key/value pair exclusively for the context of each request. Keys map[string]interface{} - // Errors is a list of errors attached to all the handlers/middlewares who used this context + // Errors is a list of errors attached to all the handlers/middlewares who used this context. Errors errorMsgs - // Accepted defines a list of manually accepted formats for content negotiation + // Accepted defines a list of manually accepted formats for content negotiation. Accepted []string } @@ -87,7 +87,7 @@ func (c *Context) Copy() *Context { } // HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()", -// this function will return "main.handleGetUsers" +// this function will return "main.handleGetUsers". func (c *Context) HandlerName() string { return nameOfFunction(c.handlers.Last()) } @@ -462,18 +462,18 @@ func (c *Context) Bind(obj interface{}) error { return c.MustBindWith(obj, b) } -// BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON) +// BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON). func (c *Context) BindJSON(obj interface{}) error { return c.MustBindWith(obj, binding.JSON) } -// BindQuery is a shortcut for c.MustBindWith(obj, binding.Query) +// BindQuery is a shortcut for c.MustBindWith(obj, binding.Query). func (c *Context) BindQuery(obj interface{}) error { return c.MustBindWith(obj, binding.Query) } -// MustBindWith binds the passed struct pointer using the specified binding -// engine. It will abort the request with HTTP 400 if any error ocurrs. +// 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) MustBindWith(obj interface{}, b binding.Binding) (err error) { if err = c.ShouldBindWith(obj, b); err != nil { @@ -483,8 +483,7 @@ func (c *Context) MustBindWith(obj interface{}, b binding.Binding) (err error) { return } -// ShouldBindWith binds the passed struct pointer using the specified binding -// engine. +// 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) @@ -548,7 +547,7 @@ func (c *Context) requestHeader(key string) string { /******** RESPONSE RENDERING ********/ /************************************/ -// bodyAllowedForStatus is a copy of http.bodyAllowedForStatus non-exported function +// bodyAllowedForStatus is a copy of http.bodyAllowedForStatus non-exported function. func bodyAllowedForStatus(status int) bool { switch { case status >= 100 && status <= 199: @@ -566,7 +565,7 @@ func (c *Context) Status(code int) { c.writermem.WriteHeader(code) } -// Header is a intelligent shortcut for c.Writer.Header().Set(key, value) +// Header is a intelligent shortcut for c.Writer.Header().Set(key, value). // It writes a header in the response. // If value == "", this method removes the header `c.Writer.Header().Del(key)` func (c *Context) Header(key, value string) { @@ -577,12 +576,12 @@ func (c *Context) Header(key, value string) { } } -// GetHeader returns value from request headers +// GetHeader returns value from request headers. func (c *Context) GetHeader(key string) string { return c.requestHeader(key) } -// GetRawData return stream data +// GetRawData return stream data. func (c *Context) GetRawData() ([]byte, error) { return ioutil.ReadAll(c.Request.Body) } diff --git a/errors.go b/errors.go index 19761106..6f3c9868 100644 --- a/errors.go +++ b/errors.go @@ -65,7 +65,7 @@ func (msg *Error) JSON() interface{} { return json } -// MarshalJSON implements the json.Marshaller interface +// MarshalJSON implements the json.Marshaller interface. func (msg *Error) MarshalJSON() ([]byte, error) { return json.Marshal(msg.JSON()) } @@ -80,7 +80,7 @@ func (msg *Error) IsType(flags ErrorType) bool { } // ByType returns a readonly copy filtered the byte. -// ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic +// ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic. func (a errorMsgs) ByType(typ ErrorType) errorMsgs { if len(a) == 0 { return nil @@ -98,7 +98,7 @@ func (a errorMsgs) ByType(typ ErrorType) errorMsgs { } // Last returns the last error in the slice. It returns nil if the array is empty. -// Shortcut for errors[len(errors)-1] +// Shortcut for errors[len(errors)-1]. func (a errorMsgs) Last() *Error { if length := len(a); length > 0 { return a[length-1] diff --git a/fs.go b/fs.go index 8570a9a9..7a6738a6 100644 --- a/fs.go +++ b/fs.go @@ -29,7 +29,7 @@ func Dir(root string, listDirectory bool) http.FileSystem { return &onlyfilesFS{fs} } -// Open conforms to http.Filesystem +// Open conforms to http.Filesystem. func (fs onlyfilesFS) Open(name string) (http.File, error) { f, err := fs.fs.Open(name) if err != nil { @@ -38,7 +38,7 @@ func (fs onlyfilesFS) Open(name string) (http.File, error) { return neuteredReaddirFile{f}, nil } -// Readdir overrides the http.File default implementation +// Readdir overrides the http.File default implementation. func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) { // this disables directory listing return nil, nil diff --git a/gin.go b/gin.go index e2c0105d..23853a97 100644 --- a/gin.go +++ b/gin.go @@ -14,7 +14,7 @@ import ( "github.com/gin-gonic/gin/render" ) -// Version is Framework's version +// Version is Framework's version. const Version = "v1.2" var default404Body = []byte("404 page not found") @@ -191,7 +191,7 @@ func (engine *Engine) NoRoute(handlers ...HandlerFunc) { engine.rebuild404Handlers() } -// NoMethod sets the handlers called when... TODO +// NoMethod sets the handlers called when... TODO. func (engine *Engine) NoMethod(handlers ...HandlerFunc) { engine.noMethod = handlers engine.rebuild405Handlers() diff --git a/logger.go b/logger.go index 7edae415..a6f7f140 100644 --- a/logger.go +++ b/logger.go @@ -25,17 +25,17 @@ var ( disableColor = false ) -// DisableConsoleColor disables color output in the console +// DisableConsoleColor disables color output in the console. func DisableConsoleColor() { disableColor = true } -// ErrorLogger returns a handlerfunc for any error type +// ErrorLogger returns a handlerfunc for any error type. func ErrorLogger() HandlerFunc { return ErrorLoggerT(ErrorTypeAny) } -// ErrorLoggerT returns a handlerfunc for a given error type +// ErrorLoggerT returns a handlerfunc for a given error type. func ErrorLoggerT(typ ErrorType) HandlerFunc { return func(c *Context) { c.Next() @@ -46,8 +46,8 @@ func ErrorLoggerT(typ ErrorType) HandlerFunc { } } -// Logger instances a Logger middleware that will write the logs to gin.DefaultWriter -// By default gin.DefaultWriter = os.Stdout +// Logger instances a Logger middleware that will write the logs to gin.DefaultWriter. +// By default gin.DefaultWriter = os.Stdout. func Logger() HandlerFunc { return LoggerWithWriter(DefaultWriter) } diff --git a/path.go b/path.go index e3424b13..ed63ad1a 100644 --- a/path.go +++ b/path.go @@ -17,7 +17,7 @@ package gin // 4. Eliminate .. elements that begin a rooted path: // that is, replace "/.." by "/" at the beginning of a path. // -// If the result of this process is an empty string, "/" is returned +// If the result of this process is an empty string, "/" is returned. func cleanPath(p string) string { // Turn empty string into "/" if p == "" { @@ -109,7 +109,7 @@ func cleanPath(p string) string { return string(buf[:w]) } -// internal helper to lazily create a buffer if necessary +// internal helper to lazily create a buffer if necessary. func bufApp(buf *[]byte, s string, w int, c byte) { if *buf == nil { if s[w] == c { diff --git a/recovery.go b/recovery.go index c502f355..7aff3d87 100644 --- a/recovery.go +++ b/recovery.go @@ -46,7 +46,7 @@ func RecoveryWithWriter(out io.Writer) HandlerFunc { } } -// stack returns a nicely formated stack frame, skipping skip frames +// stack returns a nicely formated stack frame, skipping skip frames. func stack(skip int) []byte { buf := new(bytes.Buffer) // the returned data // As we loop, we open files and read them. These variables record the currently diff --git a/render/data.go b/render/data.go index c296042c..33194913 100644 --- a/render/data.go +++ b/render/data.go @@ -11,7 +11,7 @@ type Data struct { Data []byte } -// Render (Data) writes data with custom ContentType +// Render (Data) writes data with custom ContentType. func (r Data) Render(w http.ResponseWriter) (err error) { r.WriteContentType(w) _, err = w.Write(r.Data) diff --git a/response_writer.go b/response_writer.go index 216165b9..232f00aa 100644 --- a/response_writer.go +++ b/response_writer.go @@ -95,7 +95,7 @@ func (w *responseWriter) Written() bool { return w.size != noWritten } -// Hijack implements the http.Hijacker interface +// Hijack implements the http.Hijacker interface. func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { if w.size < 0 { w.size = 0 @@ -103,12 +103,12 @@ func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return w.ResponseWriter.(http.Hijacker).Hijack() } -// CloseNotify implements the http.CloseNotify interface +// CloseNotify implements the http.CloseNotify interface. func (w *responseWriter) CloseNotify() <-chan bool { return w.ResponseWriter.(http.CloseNotifier).CloseNotify() } -// Flush implements the http.Flush interface +// Flush implements the http.Flush interface. func (w *responseWriter) Flush() { w.ResponseWriter.(http.Flusher).Flush() } diff --git a/routergroup.go b/routergroup.go index 89ec89aa..5e681c1c 100644 --- a/routergroup.go +++ b/routergroup.go @@ -35,7 +35,7 @@ type IRoutes interface { } // RouterGroup is used internally to configure router, a RouterGroup is associated with a prefix -// and an array of handlers (middleware) +// and an array of handlers (middleware). type RouterGroup struct { Handlers HandlersChain basePath string @@ -89,43 +89,43 @@ func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...Ha return group.handle(httpMethod, relativePath, handlers) } -// POST is a shortcut for router.Handle("POST", path, handle) +// POST is a shortcut for router.Handle("POST", path, handle). func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("POST", relativePath, handlers) } -// GET is a shortcut for router.Handle("GET", path, handle) +// GET is a shortcut for router.Handle("GET", path, handle). func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("GET", relativePath, handlers) } -// DELETE is a shortcut for router.Handle("DELETE", path, handle) +// DELETE is a shortcut for router.Handle("DELETE", path, handle). func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("DELETE", relativePath, handlers) } -// PATCH is a shortcut for router.Handle("PATCH", path, handle) +// PATCH is a shortcut for router.Handle("PATCH", path, handle). func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("PATCH", relativePath, handlers) } -// PUT is a shortcut for router.Handle("PUT", path, handle) +// PUT is a shortcut for router.Handle("PUT", path, handle). func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("PUT", relativePath, handlers) } -// OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle) +// OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle). func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("OPTIONS", relativePath, handlers) } -// HEAD is a shortcut for router.Handle("HEAD", path, handle) +// HEAD is a shortcut for router.Handle("HEAD", path, handle). func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle("HEAD", relativePath, handlers) } // Any registers a route that matches all the HTTP methods. -// GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE +// GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE. func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes { group.handle("GET", relativePath, handlers) group.handle("POST", relativePath, handlers) diff --git a/tree.go b/tree.go index 750ffae8..f67edd5d 100644 --- a/tree.go +++ b/tree.go @@ -96,7 +96,7 @@ type node struct { priority uint32 } -// increments priority of the given child and reorders if necessary +// increments priority of the given child and reorders if necessary. func (n *node) incrementChildPrio(pos int) int { n.children[pos].priority++ prio := n.children[pos].priority diff --git a/utils.go b/utils.go index 968570c7..ab06a759 100644 --- a/utils.go +++ b/utils.go @@ -47,7 +47,7 @@ func WrapH(h http.Handler) HandlerFunc { type H map[string]interface{} -// MarshalXML allows type H to be used with xml.Marshal +// MarshalXML allows type H to be used with xml.Marshal. func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error { start.Name = xml.Name{ Space: "", From 3856206bd07d1a5627eb951e345fff25f9b6209c Mon Sep 17 00:00:00 2001 From: Eason Lin Date: Thu, 17 Aug 2017 12:18:50 +0800 Subject: [PATCH 06/14] doc(readme): add additional middleware doc. (#1056) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b14c2a2a..dc3c8667 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,7 @@ r := gin.New() instead of ```go +// Default With the Logger and Recovery middleware already attached r := gin.Default() ``` @@ -380,7 +381,10 @@ func main() { r := gin.New() // Global middleware + // Logger middleware will write the logs to gin.DefaultWriter even you set with GIN_MODE=release. By default gin.DefaultWriter = os.Stdout r.Use(gin.Logger()) + + // Recovery middleware recovers from any panics and writes a 500 if there was one. r.Use(gin.Recovery()) // Per route middleware, you can add as many as you desire. From f4c9ac17a49e90c14ffe08b9e50aa4ee6abf6490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Tue, 22 Aug 2017 10:27:28 +0800 Subject: [PATCH 07/14] not display color when set disableColor (#1072) --- logger.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/logger.go b/logger.go index a6f7f140..c679c787 100644 --- a/logger.go +++ b/logger.go @@ -91,10 +91,11 @@ func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { clientIP := c.ClientIP() method := c.Request.Method statusCode := c.Writer.Status() - var statusColor, methodColor string + var statusColor, methodColor, resetColor string if isTerm { statusColor = colorForStatus(statusCode) methodColor = colorForMethod(method) + resetColor = reset } comment := c.Errors.ByType(ErrorTypePrivate).String() @@ -104,10 +105,10 @@ func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc { fmt.Fprintf(out, "[GIN] %v |%s %3d %s| %13v | %15s |%s %-7s %s %s\n%s", end.Format("2006/01/02 - 15:04:05"), - statusColor, statusCode, reset, + statusColor, statusCode, resetColor, latency, clientIP, - methodColor, method, reset, + methodColor, method, resetColor, path, comment, ) From 8be30bd382890156e7e813beec9f18b2c65522a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Tue, 22 Aug 2017 13:55:32 +0800 Subject: [PATCH 08/14] Update readme for showing output log to file (#1073) * Update readme for showing output log to file * update indent --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dc3c8667..776ae8b8 100644 --- a/README.md +++ b/README.md @@ -381,7 +381,8 @@ func main() { r := gin.New() // Global middleware - // Logger middleware will write the logs to gin.DefaultWriter even you set with GIN_MODE=release. By default gin.DefaultWriter = os.Stdout + // Logger middleware will write the logs to gin.DefaultWriter even you set with GIN_MODE=release. + // By default gin.DefaultWriter = os.Stdout r.Use(gin.Logger()) // Recovery middleware recovers from any panics and writes a 500 if there was one. @@ -412,6 +413,27 @@ func main() { } ``` +### Output log to file +```go +func main() { + // Disable Console Color, because not need color when output log to file + gin.DisableConsoleColor() + // Create one file to save logs + f, _ := os.Create("gin.log") + // Reset gin.DefaultWriter + gin.DefaultWriter = io.MultiWriter(f) + // If need to output log to file and console at a time, please use the following code: + // gin.DefaultWriter = io.MultiWriter(f, os.Stdout) + + router := gin.Default() + router.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + r.Run(":8080") +} +``` + ### Model binding and validation To bind a request body into a type, use model binding. We currently support binding of JSON, XML and standard form values (foo=bar&boo=baz). From 80152ac82c413e82275e828fdde8892c458715f7 Mon Sep 17 00:00:00 2001 From: Eason Lin Date: Thu, 24 Aug 2017 10:50:31 +0800 Subject: [PATCH 09/14] doc(readme): update writing logs section wording. (#1074) * doc(readme): update writing logs section wording. * doc(readme): update writing logs section wording. * doc(readme): fix word formatting --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 776ae8b8..b5644464 100644 --- a/README.md +++ b/README.md @@ -413,16 +413,17 @@ func main() { } ``` -### Output log to file +### How to write log file ```go func main() { - // Disable Console Color, because not need color when output log to file + // Disable Console Color, you don't need console color when writing the logs to file. gin.DisableConsoleColor() - // Create one file to save logs + + // Logging to a file. f, _ := os.Create("gin.log") - // Reset gin.DefaultWriter gin.DefaultWriter = io.MultiWriter(f) - // If need to output log to file and console at a time, please use the following code: + + // Use the following code if you need to write the logs to file and console at the same time. // gin.DefaultWriter = io.MultiWriter(f, os.Stdout) router := gin.Default() From c25254f563fc3685e22901edf2fd289902a76cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Fri, 25 Aug 2017 09:00:49 +0800 Subject: [PATCH 10/14] reduce go cyclo (#1076) * reduce go cyclo * use := var --- gin.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gin.go b/gin.go index 23853a97..ee39c9aa 100644 --- a/gin.go +++ b/gin.go @@ -316,14 +316,11 @@ func (engine *Engine) HandleContext(c *Context) { func (engine *Engine) handleHTTPRequest(context *Context) { httpMethod := context.Request.Method - var path string - var unescape bool + path := context.Request.URL.Path + unescape := false if engine.UseRawPath && len(context.Request.URL.RawPath) > 0 { path = context.Request.URL.RawPath unescape = engine.UnescapePathValues - } else { - path = context.Request.URL.Path - unescape = false } // Find root of the tree for the given HTTP method From bc538849ebc41f2600338d9f65fad2c3008c95b2 Mon Sep 17 00:00:00 2001 From: stackerzzq Date: Fri, 25 Aug 2017 09:06:13 +0800 Subject: [PATCH 11/14] Update readme for adding tag example of binding time field (#1080) --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b5644464..879d77b4 100644 --- a/README.md +++ b/README.md @@ -532,10 +532,12 @@ package main import "log" import "github.com/gin-gonic/gin" +import "time" type Person struct { - Name string `form:"name"` - Address string `form:"address"` + Name string `form:"name"` + Address string `form:"address"` + Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"` } func main() { @@ -552,12 +554,18 @@ func startPage(c *gin.Context) { if c.Bind(&person) == nil { log.Println(person.Name) log.Println(person.Address) + log.Println(person.Birthday) } c.String(200, "Success") } ``` +Test it with: +```sh +$ curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15" +``` + ### Bind HTML checkboxes See the [detail information](https://github.com/gin-gonic/gin/issues/129#issuecomment-124260092) From 18b7c0892df51ba799473e57fd3d65f91c1c3aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Fri, 25 Aug 2017 09:13:53 +0800 Subject: [PATCH 12/14] not use dot when import package (#1077) --- ginS/gins.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ginS/gins.go b/ginS/gins.go index d40d1c3a..d238fcae 100644 --- a/ginS/gins.go +++ b/ginS/gins.go @@ -9,15 +9,15 @@ import ( "net/http" "sync" - . "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin" ) var once sync.Once -var internalEngine *Engine +var internalEngine *gin.Engine -func engine() *Engine { +func engine() *gin.Engine { once.Do(func() { - internalEngine = Default() + internalEngine = gin.Default() }) return internalEngine } From b9686e91fa271d2fe5da3108a2ea4087c0b0ad68 Mon Sep 17 00:00:00 2001 From: Dan Markham Date: Fri, 25 Aug 2017 21:53:27 -0700 Subject: [PATCH 13/14] Use standard library for retrieving header (#1081) --- context.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/context.go b/context.go index 497cbfd6..6f2b0053 100644 --- a/context.go +++ b/context.go @@ -537,10 +537,7 @@ func (c *Context) IsWebsocket() bool { } func (c *Context) requestHeader(key string) string { - if values, _ := c.Request.Header[key]; len(values) > 0 { - return values[0] - } - return "" + return c.Request.Header.Get(key) } /************************************/ From fa391a4864cb2e249b4e82fd1d71261a1496f0f4 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sat, 26 Aug 2017 03:48:56 -0500 Subject: [PATCH 14/14] chore(ci): add go 1.9 version (#1082) Signed-off-by: Bo-Yi Wu --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 821ce8df..ec12cad6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ go: - 1.6.x - 1.7.x - 1.8.x + - 1.9.x - master git: