gin

package module
v1.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 3, 2016 License: MIT Imports: 31 Imported by: 0

README ¶

#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)

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. If you need performance and good productivity, you will love Gin.

Gin console logger

$ cat test.go
package main

import "gopkg.in/gin-gonic/gin.v1"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // listen and serve on 0.0.0.0:8080
}

Benchmarks

Gin uses a custom version of HttpRouter

See all benchmarks

Benchmark name (1) (2) (3) (4)
BenchmarkAce_GithubAll 10000 109482 13792 167
BenchmarkBear_GithubAll 10000 287490 79952 943
BenchmarkBeego_GithubAll 3000 562184 146272 2092
BenchmarkBone_GithubAll 500 2578716 648016 8119
BenchmarkDenco_GithubAll 20000 94955 20224 167
BenchmarkEcho_GithubAll 30000 58705 0 0
BenchmarkGin_GithubAll 30000 50991 0 0
BenchmarkGocraftWeb_GithubAll 5000 449648 133280 1889
BenchmarkGoji_GithubAll 2000 689748 56113 334
BenchmarkGoJsonRest_GithubAll 5000 537769 135995 2940
BenchmarkGoRestful_GithubAll 100 18410628 797236 7725
BenchmarkGorillaMux_GithubAll 200 8036360 153137 1791
BenchmarkHttpRouter_GithubAll 20000 63506 13792 167
BenchmarkHttpTreeMux_GithubAll 10000 165927 56112 334
BenchmarkKocha_GithubAll 10000 171362 23304 843
BenchmarkMacaron_GithubAll 2000 817008 224960 2315
BenchmarkMartini_GithubAll 100 12609209 237952 2686
BenchmarkPat_GithubAll 300 4830398 1504101 32222
BenchmarkPossum_GithubAll 10000 301716 97440 812
BenchmarkR2router_GithubAll 10000 270691 77328 1182
BenchmarkRevel_GithubAll 1000 1491919 345553 5918
BenchmarkRivet_GithubAll 10000 283860 84272 1079
BenchmarkTango_GithubAll 5000 473821 87078 2470
BenchmarkTigerTonic_GithubAll 2000 1120131 241088 6052
BenchmarkTraffic_GithubAll 200 8708979 2664762 22390
BenchmarkVulcan_GithubAll 5000 353392 19894 609
BenchmarkZeus_GithubAll 2000 944234 300688 2648

(1): Total Repetitions
(2): Single Repetition Duration (ns/op)
(3): Heap Memory (B/op)
(4): Average Allocations per Repetition (allocs/op)

Gin v1. stable

  • Zero allocation router.
  • Still the fastest http router and framework. From routing to writing.
  • Complete suite of unit tests
  • Battle tested
  • API frozen, new releases will not break your code.

Start using it

  1. Download and install it:

    $ go get gopkg.in/gin-gonic/gin.v1
    
  2. Import it in your code:

    import "gopkg.in/gin-gonic/gin.v1"
    
  3. (Optional) Import net/http. This is required for example if using constants such as http.StatusOK.

    import "net/http"
    

API Examples

Using GET, POST, PUT, PATCH, DELETE and OPTIONS
func main() {
	// Creates a gin router with default middleware:
	// logger and recovery (crash-free) middleware
	router := gin.Default()

	router.GET("/someGet", getting)
	router.POST("/somePost", posting)
	router.PUT("/somePut", putting)
	router.DELETE("/someDelete", deleting)
	router.PATCH("/somePatch", patching)
	router.HEAD("/someHead", head)
	router.OPTIONS("/someOptions", options)

	// By default it serves on :8080 unless a
	// PORT environment variable was defined.
	router.Run()
	// router.Run(":3000") for a hard coded port
}
Parameters in path
func main() {
	router := gin.Default()

	// This handler will match /user/john but will not match neither /user/ or /user
	router.GET("/user/:name", func(c *gin.Context) {
		name := c.Param("name")
		c.String(http.StatusOK, "Hello %s", name)
	})

	// However, this one will match /user/john/ and also /user/john/send
	// If no other routers match /user/john, it will redirect to /user/john/
	router.GET("/user/:name/*action", func(c *gin.Context) {
		name := c.Param("name")
		action := c.Param("action")
		message := name + " is " + action
		c.String(http.StatusOK, message)
	})

	router.Run(":8080")
}
Querystring parameters
func main() {
	router := gin.Default()

	// Query string parameters are parsed using the existing underlying request object.
	// The request responds to a url matching:  /welcome?firstname=Jane&lastname=Doe
	router.GET("/welcome", func(c *gin.Context) {
		firstname := c.DefaultQuery("firstname", "Guest")
		lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")

		c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
	})
	router.Run(":8080")
}

Multipart/Urlencoded Form

func main() {
	router := gin.Default()

	router.POST("/form_post", func(c *gin.Context) {
		message := c.PostForm("message")
		nick := c.DefaultPostForm("nick", "anonymous")

		c.JSON(200, gin.H{
			"status":  "posted",
			"message": message,
			"nick":    nick,
		})
	})
	router.Run(":8080")
}

Another example: query + post form

POST /post?id=1234&page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=manu&message=this_is_great
func main() {
	router := gin.Default()

	router.POST("/post", func(c *gin.Context) {

		id := c.Query("id")
		page := c.DefaultQuery("page", "0")
		name := c.PostForm("name")
		message := c.PostForm("message")

		fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message)
	})
	router.Run(":8080")
}
id: 1234; page: 1; name: manu; message: this_is_great

Another example: upload file

References issue #548.

func main() {
	router := gin.Default()

	router.POST("/upload", func(c *gin.Context) {

	        file, header , err := c.Request.FormFile("upload")
	        filename := header.Filename
	        fmt.Println(header.Filename)
	        out, err := os.Create("./tmp/"+filename+".png")
	        if err != nil {
	            log.Fatal(err)
	        }
	        defer out.Close()
	        _, err = io.Copy(out, file)
	        if err != nil {
	            log.Fatal(err)
	        }   
	})
	router.Run(":8080")
}
Grouping routes
func main() {
	router := gin.Default()

	// Simple group: v1
	v1 := router.Group("/v1")
	{
		v1.POST("/login", loginEndpoint)
		v1.POST("/submit", submitEndpoint)
		v1.POST("/read", readEndpoint)
	}

	// Simple group: v2
	v2 := router.Group("/v2")
	{
		v2.POST("/login", loginEndpoint)
		v2.POST("/submit", submitEndpoint)
		v2.POST("/read", readEndpoint)
	}

	router.Run(":8080")
}
Blank Gin without middleware by default

Use

r := gin.New()

instead of

r := gin.Default()
Using middleware
func main() {
	// Creates a router without any middleware by default
	r := gin.New()

	// Global middleware
	r.Use(gin.Logger())
	r.Use(gin.Recovery())

	// Per route middleware, you can add as many as you desire.
	r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

	// Authorization group
	// authorized := r.Group("/", AuthRequired())
	// exactly the same as:
	authorized := r.Group("/")
	// per group middleware! in this case we use the custom created
	// AuthRequired() middleware just in the "authorized" group.
	authorized.Use(AuthRequired())
	{
		authorized.POST("/login", loginEndpoint)
		authorized.POST("/submit", submitEndpoint)
		authorized.POST("/read", readEndpoint)

		// nested group
		testing := authorized.Group("testing")
		testing.GET("/analytics", analyticsEndpoint)
	}

	// Listen and serve on 0.0.0.0:8080
	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).

Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set json:"fieldname".

When using the Bind-method, Gin tries to infer the binder depending on the Content-Type header. If you are sure what you are binding, you can use BindWith.

You can also specify that specific fields are required. If a field is decorated with binding:"required" and has a empty value when binding, the current request will fail with an error.

// Binding from JSON
type Login struct {
	User     string `form:"user" json:"user" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

func main() {
	router := gin.Default()

	// Example for binding JSON ({"user": "manu", "password": "123"})
	router.POST("/loginJSON", func(c *gin.Context) {
		var json Login
		if c.BindJSON(&json) == nil {
			if json.User == "manu" && json.Password == "123" {
				c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
			} else {
				c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
			}
		}
	})

	// Example for binding a HTML form (user=manu&password=123)
	router.POST("/loginForm", func(c *gin.Context) {
		var form Login
		// This will infer what binder to use depending on the content-type header.
		if c.Bind(&form) == nil {
			if form.User == "manu" && form.Password == "123" {
				c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
			} else {
				c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
			}
		}
	})

	// Listen and serve on 0.0.0.0:8080
	router.Run(":8080")
}

###Multipart/Urlencoded binding

package main

import (
	"gopkg.in/gin-gonic/gin.v1"
)

type LoginForm struct {
	User     string `form:"user" binding:"required"`
	Password string `form:"password" binding:"required"`
}

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)
		// or you can simply use autobinding with Bind method:
		var form LoginForm
		// in this case proper binding will be automatically selected
		if c.Bind(&form) == nil {
			if form.User == "user" && form.Password == "password" {
				c.JSON(200, gin.H{"status": "you are logged in"})
			} else {
				c.JSON(401, gin.H{"status": "unauthorized"})
			}
		}
	})
	router.Run(":8080")
}

Test it with:

$ curl -v --form user=user --form password=password http://localhost:8080/login
XML, JSON and YAML rendering
func main() {
	r := gin.Default()

	// gin.H is a shortcut for map[string]interface{}
	r.GET("/someJSON", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	r.GET("/moreJSON", func(c *gin.Context) {
		// You also can use a struct
		var msg struct {
			Name    string `json:"user"`
			Message string
			Number  int
		}
		msg.Name = "Lena"
		msg.Message = "hey"
		msg.Number = 123
		// Note that msg.Name becomes "user" in the JSON
		// Will output  :   {"user": "Lena", "Message": "hey", "Number": 123}
		c.JSON(http.StatusOK, msg)
	})

	r.GET("/someXML", func(c *gin.Context) {
		c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	r.GET("/someYAML", func(c *gin.Context) {
		c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	// Listen and serve on 0.0.0.0:8080
	r.Run(":8080")
}

####Serving static files

func main() {
	router := gin.Default()
	router.Static("/assets", "./assets")
	router.StaticFS("/more_static", http.Dir("my_file_system"))
	router.StaticFile("/favicon.ico", "./resources/favicon.ico")

	// Listen and serve on 0.0.0.0:8080
	router.Run(":8080")
}

####HTML rendering

Using LoadHTMLTemplates()

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("templates/*")
	//router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
	router.GET("/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"title": "Main website",
		})
	})
	router.Run(":8080")
}

templates/index.tmpl

<html>
	<h1>
		{{ .title }}
	</h1>
</html>

Using templates with same name in different directories

func main() {
	router := gin.Default()
	router.LoadHTMLGlob("templates/**/*")
	router.GET("/posts/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
			"title": "Posts",
		})
	})
	router.GET("/users/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
			"title": "Users",
		})
	})
	router.Run(":8080")
}

templates/posts/index.tmpl

{{ define "posts/index.tmpl" }}
<html><h1>
	{{ .title }}
</h1>
<p>Using posts/index.tmpl</p>
</html>
{{ end }}

templates/users/index.tmpl

{{ define "users/index.tmpl" }}
<html><h1>
	{{ .title }}
</h1>
<p>Using users/index.tmpl</p>
</html>
{{ end }}

You can also use your own html template render

import "html/template"

func main() {
	router := gin.Default()
	html := template.Must(template.ParseFiles("file1", "file2"))
	router.SetHTMLTemplate(html)
	router.Run(":8080")
}
Redirects

Issuing a HTTP redirect is easy:

r.GET("/test", func(c *gin.Context) {
	c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")
})

Both internal and external locations are supported.

Custom Middleware
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()

		// Set example variable
		c.Set("example", "12345")

		// before request

		c.Next()

		// after request
		latency := time.Since(t)
		log.Print(latency)

		// access the status we are sending
		status := c.Writer.Status()
		log.Println(status)
	}
}

func main() {
	r := gin.New()
	r.Use(Logger())

	r.GET("/test", func(c *gin.Context) {
		example := c.MustGet("example").(string)

		// it would print: "12345"
		log.Println(example)
	})

	// Listen and serve on 0.0.0.0:8080
	r.Run(":8080")
}
Using BasicAuth() middleware
// simulate some private data
var secrets = gin.H{
	"foo":    gin.H{"email": "foo@bar.com", "phone": "123433"},
	"austin": gin.H{"email": "austin@example.com", "phone": "666"},
	"lena":   gin.H{"email": "lena@guapa.com", "phone": "523443"},
}

func main() {
	r := gin.Default()

	// Group using gin.BasicAuth() middleware
	// gin.Accounts is a shortcut for map[string]string
	authorized := r.Group("/admin", gin.BasicAuth(gin.Accounts{
		"foo":    "bar",
		"austin": "1234",
		"lena":   "hello2",
		"manu":   "4321",
	}))

	// /admin/secrets endpoint
	// hit "localhost:8080/admin/secrets
	authorized.GET("/secrets", func(c *gin.Context) {
		// get user, it was set by the BasicAuth middleware
		user := c.MustGet(gin.AuthUserKey).(string)
		if secret, ok := secrets[user]; ok {
			c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret})
		} else {
			c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("})
		}
	})

	// Listen and serve on 0.0.0.0:8080
	r.Run(":8080")
}
Goroutines inside a middleware

When starting inside a middleware or handler, you SHOULD NOT use the original context inside it, you have to use a read-only copy.

func main() {
	r := gin.Default()

	r.GET("/long_async", func(c *gin.Context) {
		// create copy to be used inside the goroutine
		cCp := c.Copy()
		go func() {
			// simulate a long task with time.Sleep(). 5 seconds
			time.Sleep(5 * time.Second)

			// note that you are using the copied context "cCp", IMPORTANT
			log.Println("Done! in path " + cCp.Request.URL.Path)
		}()
	})

	r.GET("/long_sync", func(c *gin.Context) {
		// simulate a long task with time.Sleep(). 5 seconds
		time.Sleep(5 * time.Second)

		// since we are NOT using a goroutine, we do not have to copy the context
		log.Println("Done! in path " + c.Request.URL.Path)
	})

	// Listen and serve on 0.0.0.0:8080
	r.Run(":8080")
}
Custom HTTP configuration

Use http.ListenAndServe() directly, like this:

func main() {
	router := gin.Default()
	http.ListenAndServe(":8080", router)
}

or

func main() {
	router := gin.Default()

	s := &http.Server{
		Addr:           ":8080",
		Handler:        router,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	s.ListenAndServe()
}
Graceful restart or stop

Do you want to graceful restart or stop your web server? There are some ways this can be done.

We can use fvbock/endless to replace the default ListenAndServe. Refer issue #296 for more details.

router := gin.Default()
router.GET("/", handler)
// [...]
endless.ListenAndServe(":4242", router)

An alternative to endless:

  • manners: A polite Go HTTP server that shuts down gracefully.

Contributing

  • With issues:
    • Use the search tool before opening a new issue.
    • 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
    • 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.
    • If your pull request contains a new feature, please document it on the README.

Example

Awesome project lists using Gin web framework.

  • drone: Drone is a Continuous Delivery platform built on Docker, written in Go
  • gorush: A push notification server written in Go.

Documentation ¶

Index ¶

Constants ¶

View Source
const (
	MIMEJSON              = binding.MIMEJSON
	MIMEHTML              = binding.MIMEHTML
	MIMEXML               = binding.MIMEXML
	MIMEXML2              = binding.MIMEXML2
	MIMEPlain             = binding.MIMEPlain
	MIMEPOSTForm          = binding.MIMEPOSTForm
	MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
)

Content-Type MIME of the most common data formats

View Source
const (
	DebugMode   string = "debug"
	ReleaseMode string = "release"
	TestMode    string = "test"
)
View Source
const AuthUserKey = "user"
View Source
const BindKey = "_gin-gonic/gin/bindkey"
View Source
const ENV_GIN_MODE = "GIN_MODE"
View Source
const Version = "v1.0rc2"

Version is Framework's version

Variables ¶

View Source
var DefaultErrorWriter io.Writer = os.Stderr
View Source
var DefaultWriter io.Writer = os.Stdout

DefaultWriter is the default io.Writer used the Gin for debug output and middleware output like Logger() or Recovery(). Note that both Logger and Recovery provides custom ways to configure their output io.Writer. To support coloring in Windows use:

import "github.com/mattn/go-colorable"
gin.DefaultWriter = colorable.NewColorableStdout()

Functions ¶

func Dir ¶

func Dir(root string, listDirectory bool) http.FileSystem

Dir returns a http.Filesystem that can be used by http.FileServer(). It is used interally in router.Static(). if listDirectory == true, then it works the same as http.Dir() otherwise it returns a filesystem that prevents http.FileServer() to list the directory files.

func DisableBindValidation ¶

func DisableBindValidation()

func IsDebugging ¶

func IsDebugging() bool

IsDebugging returns true if the framework is running in debug mode. Use SetMode(gin.Release) to switch to disable the debug mode.

func Mode ¶

func Mode() string

func SetMode ¶

func SetMode(value string)

Types ¶

type Accounts ¶

type Accounts map[string]string

type Context ¶

type Context struct {
	Request *http.Request
	Writer  ResponseWriter

	Params Params

	Keys     map[string]interface{}
	Errors   errorMsgs
	Accepted []string
	// contains filtered or unexported fields
}

Context is the most important part of gin. It allows us to pass variables between middleware, manage the flow, validate the JSON of a request and render a JSON response for example.

func (*Context) Abort ¶

func (c *Context) Abort()

Abort prevents pending handlers from being called. Note that this will not stop the current handler. Let's say you have an authorization middleware that validates that the current request is authorized. If the authorization fails (ex: the password does not match), call Abort to ensure the remaining handlers for this request are not called.

func (*Context) AbortWithError ¶

func (c *Context) AbortWithError(code int, err error) *Error

AbortWithError calls `AbortWithStatus()` and `Error()` internally. This method stops the chain, writes the status code and pushes the specified error to `c.Errors`. See Context.Error() for more details.

func (*Context) AbortWithStatus ¶

func (c *Context) AbortWithStatus(code int)

AbortWithStatus calls `Abort()` and writes the headers with the specified status code. For example, a failed attempt to authentificate a request could use: context.AbortWithStatus(401).

func (*Context) Bind ¶

func (c *Context) Bind(obj interface{}) error

Bind checks the Content-Type to select a binding engine automatically, Depending the "Content-Type" header different bindings are used:

"application/json" --> JSON binding
"application/xml"  --> XML binding

otherwise --> returns an error It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input. It decodes the json payload into the struct specified as a pointer. Like ParseBody() but this method also writes a 400 error if the json is not valid.

func (*Context) BindJSON ¶

func (c *Context) BindJSON(obj interface{}) error

BindJSON is a shortcut for c.BindWith(obj, binding.JSON)

func (*Context) BindWith ¶

func (c *Context) BindWith(obj interface{}, b binding.Binding) error

BindWith binds the passed struct pointer using the specified binding engine. See the binding package.

func (*Context) ClientIP ¶

func (c *Context) ClientIP() string

ClientIP implements a best effort algorithm to return the real client IP, it parses X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy.

func (*Context) ContentType ¶

func (c *Context) ContentType() string

ContentType returns the Content-Type header of the request.

func (*Context) Cookie ¶

func (c *Context) Cookie(name string) (string, error)

func (*Context) Copy ¶

func (c *Context) Copy() *Context

Copy returns a copy of the current context that can be safely used outside the request's scope. This have to be used then the context has to be passed to a goroutine.

func (*Context) Data ¶

func (c *Context) Data(code int, contentType string, data []byte)

Data writes some data into the body stream and updates the HTTP code.

func (*Context) Deadline ¶

func (c *Context) Deadline() (deadline time.Time, ok bool)

func (*Context) DefaultPostForm ¶

func (c *Context) DefaultPostForm(key, defaultValue string) string

DefaultPostForm returns the specified key from a POST urlencoded form or multipart form when it exists, otherwise it returns the specified defaultValue string. See: PostForm() and GetPostForm() for further information.

func (*Context) DefaultQuery ¶

func (c *Context) DefaultQuery(key, defaultValue string) string

DefaultQuery returns the keyed url query value if it exists, othewise it returns the specified defaultValue string. See: Query() and GetQuery() for further information.

GET /?name=Manu&lastname=
c.DefaultQuery("name", "unknown") == "Manu"
c.DefaultQuery("id", "none") == "none"
c.DefaultQuery("lastname", "none") == ""

func (*Context) Done ¶

func (c *Context) Done() <-chan struct{}

func (*Context) Err ¶

func (c *Context) Err() error

func (*Context) Error ¶

func (c *Context) Error(err error) *Error

Attaches an error to the current context. The error is pushed to a list of errors. It's a good idea to call Error for each error that occurred during the resolution of a request. A middleware can be used to collect all the errors and push them to a database together, print a log, or append it in the HTTP response.

func (*Context) File ¶

func (c *Context) File(filepath string)

File writes the specified file into the body stream in a efficient way.

func (*Context) Get ¶

func (c *Context) Get(key string) (value interface{}, exists bool)

Get returns the value for the given key, ie: (value, true). If the value does not exists it returns (nil, false)

func (*Context) GetCookie ¶

func (c *Context) GetCookie(name string) (string, error)

func (*Context) GetPostForm ¶

func (c *Context) GetPostForm(key string) (string, bool)

GetPostForm is like PostForm(key). It returns the specified key from a POST urlencoded form or multipart form when it exists `(value, true)` (even when the value is an empty string), otherwise it returns ("", false). For example, during a PATCH request to update the user's email:

email=mail@example.com  -->  ("mail@example.com", true) := GetPostForm("email") // set email to "mail@example.com"
email=  			  	-->  ("", true) := GetPostForm("email") // set email to ""
					 	-->  ("", false) := GetPostForm("email") // do nothing with email

func (*Context) GetPostFormArray ¶

func (c *Context) GetPostFormArray(key string) ([]string, bool)

GetPostFormArray returns a slice of strings for a given form key, plus a boolean value whether at least one value exists for the given key.

func (*Context) GetQuery ¶

func (c *Context) GetQuery(key string) (string, bool)

GetQuery is like Query(), it returns the keyed url query value if it exists `(value, true)` (even when the value is an empty string), othewise it returns `("", false)`. It is shortcut for `c.Request.URL.Query().Get(key)`

GET /?name=Manu&lastname=
("Manu", true) == c.GetQuery("name")
("", false) == c.GetQuery("id")
("", true) == c.GetQuery("lastname")

func (*Context) GetQueryArray ¶

func (c *Context) GetQueryArray(key string) ([]string, bool)

GetQueryArray returns a slice of strings for a given query key, plus a boolean value whether at least one value exists for the given key.

func (*Context) HTML ¶

func (c *Context) HTML(code int, name string, obj interface{})

HTML renders the HTTP template specified by its file name. It also updates the HTTP code and sets the Content-Type as "text/html". See http://golang.org/doc/articles/wiki/

func (*Context) HandlerName ¶

func (c *Context) HandlerName() string

HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()", this function will return "main.handleGetUsers"

func (*Context) Header ¶

func (c *Context) Header(key, value string)

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 (*Context) IndentedJSON ¶

func (c *Context) IndentedJSON(code int, obj interface{})

IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body. It also sets the Content-Type as "application/json". WARNING: we recommend to use this only for development propuses since printing pretty JSON is more CPU and bandwidth consuming. Use Context.JSON() instead.

func (*Context) IsAborted ¶

func (c *Context) IsAborted() bool

IsAborted returns true if the current context was aborted.

func (*Context) JSON ¶

func (c *Context) JSON(code int, obj interface{})

JSON serializes the given struct as JSON into the response body. It also sets the Content-Type as "application/json".

func (*Context) MustGet ¶

func (c *Context) MustGet(key string) interface{}

MustGet returns the value for the given key if it exists, otherwise it panics.

func (*Context) Negotiate ¶

func (c *Context) Negotiate(code int, config Negotiate)

func (*Context) NegotiateFormat ¶

func (c *Context) NegotiateFormat(offered ...string) string

func (*Context) Next ¶

func (c *Context) Next()

Next should be used only inside middleware. It executes the pending handlers in the chain inside the calling handler. See example in github.

func (*Context) Param ¶

func (c *Context) Param(key string) string

Param returns the value of the URL param. It is a shortcut for c.Params.ByName(key)

router.GET("/user/:id", func(c *gin.Context) {
	// a GET request to /user/john
	id := c.Param("id") // id == "john"
})

func (*Context) PostForm ¶

func (c *Context) PostForm(key string) string

PostForm returns the specified key from a POST urlencoded form or multipart form when it exists, otherwise it returns an empty string `("")`.

func (*Context) PostFormArray ¶

func (c *Context) PostFormArray(key string) []string

PostFormArray returns a slice of strings for a given form key. The length of the slice depends on the number of params with the given key.

func (*Context) Query ¶

func (c *Context) Query(key string) string

Query returns the keyed url query value if it exists, othewise it returns an empty string `("")`. It is shortcut for `c.Request.URL.Query().Get(key)`

GET /path?id=1234&name=Manu&value=
c.Query("id") == "1234"
c.Query("name") == "Manu"
c.Query("value") == ""
c.Query("wtf") == ""

func (*Context) QueryArray ¶

func (c *Context) QueryArray(key string) []string

QueryArray returns a slice of strings for a given query key. The length of the slice depends on the number of params with the given key.

func (*Context) Redirect ¶

func (c *Context) Redirect(code int, location string)

Redirect returns a HTTP redirect to the specific location.

func (*Context) Render ¶

func (c *Context) Render(code int, r render.Render)

func (*Context) SSEvent ¶

func (c *Context) SSEvent(name string, message interface{})

SSEvent writes a Server-Sent Event into the body stream.

func (*Context) Set ¶

func (c *Context) Set(key string, value interface{})

Set is used to store a new key/value pair exclusivelly for this context. It also lazy initializes c.Keys if it was not used previously.

func (*Context) SetAccepted ¶

func (c *Context) SetAccepted(formats ...string)

func (*Context) SetCookie ¶

func (c *Context) SetCookie(
	name string,
	value string,
	maxAge int,
	path string,
	domain string,
	secure bool,
	httpOnly bool,
)

func (*Context) Status ¶

func (c *Context) Status(code int)

func (*Context) Stream ¶

func (c *Context) Stream(step func(w io.Writer) bool)

func (*Context) String ¶

func (c *Context) String(code int, format string, values ...interface{})

String writes the given string into the response body.

func (*Context) Value ¶

func (c *Context) Value(key interface{}) interface{}

func (*Context) XML ¶

func (c *Context) XML(code int, obj interface{})

XML serializes the given struct as XML into the response body. It also sets the Content-Type as "application/xml".

func (*Context) YAML ¶

func (c *Context) YAML(code int, obj interface{})

YAML serializes the given struct as YAML into the response body.

type Engine ¶

type Engine struct {
	RouterGroup
	HTMLRender render.HTMLRender

	// Enables automatic redirection if the current route can't be matched but a
	// handler for the path with (without) the trailing slash exists.
	// For example if /foo/ is requested but a route only exists for /foo, the
	// client is redirected to /foo with http status code 301 for GET requests
	// and 307 for all other request methods.
	RedirectTrailingSlash bool

	// If enabled, the router tries to fix the current request path, if no
	// handle is registered for it.
	// First superfluous path elements like ../ or // are removed.
	// Afterwards the router does a case-insensitive lookup of the cleaned path.
	// If a handle can be found for this route, the router makes a redirection
	// to the corrected path with status code 301 for GET requests and 307 for
	// all other request methods.
	// For example /FOO and /..//Foo could be redirected to /foo.
	// RedirectTrailingSlash is independent of this option.
	RedirectFixedPath bool

	// If enabled, the router checks if another method is allowed for the
	// current route, if the current request can not be routed.
	// If this is the case, the request is answered with 'Method Not Allowed'
	// and HTTP status code 405.
	// If no other Method is allowed, the request is delegated to the NotFound
	// handler.
	HandleMethodNotAllowed bool
	ForwardedByClientIP    bool
	// contains filtered or unexported fields
}

Engine is the framework's instance, it contains the muxer, middleware and configuration settings. Create an instance of Engine, by using New() or Default()

func Default ¶

func Default() *Engine

Default returns an Engine instance with the Logger and Recovery middleware already attached.

func New ¶

func New() *Engine

New returns a new blank Engine instance without any middleware attached. By default the configuration is: - RedirectTrailingSlash: true - RedirectFixedPath: false - HandleMethodNotAllowed: false - ForwardedByClientIP: true

func (*Engine) LoadHTMLFiles ¶

func (engine *Engine) LoadHTMLFiles(files ...string)

func (*Engine) LoadHTMLGlob ¶

func (engine *Engine) LoadHTMLGlob(pattern string)

func (*Engine) NoMethod ¶

func (engine *Engine) NoMethod(handlers ...HandlerFunc)

NoMethod sets the handlers called when... TODO

func (*Engine) NoRoute ¶

func (engine *Engine) NoRoute(handlers ...HandlerFunc)

NoRoute adds handlers for NoRoute. It return a 404 code by default.

func (*Engine) Routes ¶

func (engine *Engine) Routes() (routes RoutesInfo)

Routes returns a slice of registered routes, including some useful information, such as: the http method, path and the handler name.

func (*Engine) Run ¶

func (engine *Engine) Run(addr ...string) (err error)

Run attaches the router to a http.Server and starts listening and serving HTTP requests. It is a shortcut for http.ListenAndServe(addr, router) Note: this method will block the calling goroutine indefinitely unless an error happens.

func (*Engine) RunTLS ¶

func (engine *Engine) RunTLS(addr string, certFile string, keyFile 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) RunUnix ¶

func (engine *Engine) RunUnix(file string) (err error)

RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests through the specified unix socket (ie. a file). Note: this method will block the calling goroutine indefinitely unless an error happens.

func (*Engine) ServeHTTP ¶

func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request)

Conforms to the http.Handler interface.

func (*Engine) SetHTMLTemplate ¶

func (engine *Engine) SetHTMLTemplate(templ *template.Template)

func (*Engine) Use ¶

func (engine *Engine) Use(middleware ...HandlerFunc) IRoutes

Use attachs a global middleware to the router. ie. the middleware attached though Use() will be included in the handlers chain for every single request. Even 404, 405, static files... For example, this is the right place for a logger or error management middleware.

type Error ¶

type Error struct {
	Err  error
	Type ErrorType
	Meta interface{}
}

func (*Error) Error ¶

func (msg *Error) Error() string

Implements the error interface

func (*Error) IsType ¶

func (msg *Error) IsType(flags ErrorType) bool

func (*Error) JSON ¶

func (msg *Error) JSON() interface{}

func (*Error) MarshalJSON ¶

func (msg *Error) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaller interface

func (*Error) SetMeta ¶

func (msg *Error) SetMeta(data interface{}) *Error

func (*Error) SetType ¶

func (msg *Error) SetType(flags ErrorType) *Error

type ErrorType ¶

type ErrorType uint64
const (
	ErrorTypeBind    ErrorType = 1 << 63 // used when c.Bind() fails
	ErrorTypeRender  ErrorType = 1 << 62 // used when c.Render() fails
	ErrorTypePrivate ErrorType = 1 << 0
	ErrorTypePublic  ErrorType = 1 << 1

	ErrorTypeAny ErrorType = 1<<64 - 1
	ErrorTypeNu            = 2
)

type H ¶

type H map[string]interface{}

func (H) MarshalXML ¶

func (h H) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML allows type H to be used with xml.Marshal

type HandlerFunc ¶

type HandlerFunc func(*Context)

func BasicAuth ¶

func BasicAuth(accounts Accounts) HandlerFunc

BasicAuth returns a Basic HTTP Authorization middleware. It takes as argument a map[string]string where the key is the user name and the value is the password.

func BasicAuthForRealm ¶

func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc

BasicAuthForRealm returns a Basic HTTP Authorization middleware. It takes as arguments a map[string]string where the key is the user name and the value is the password, as well as the name of the Realm. If the realm is empty, "Authorization Required" will be used by default. (see http://tools.ietf.org/html/rfc2617#section-1.2)

func Bind ¶

func Bind(val interface{}) HandlerFunc

func ErrorLogger ¶

func ErrorLogger() HandlerFunc

func ErrorLoggerT ¶

func ErrorLoggerT(typ ErrorType) HandlerFunc

func Logger ¶

func Logger() HandlerFunc

Logger instances a Logger middleware that will write the logs to gin.DefaultWriter By default gin.DefaultWriter = os.Stdout

func LoggerWithWriter ¶

func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc

LoggerWithWriter instance a Logger middleware with the specified writter buffer. Example: os.Stdout, a file opened in write mode, a socket...

func Recovery ¶

func Recovery() HandlerFunc

Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.

func RecoveryWithWriter ¶

func RecoveryWithWriter(out io.Writer) HandlerFunc

func WrapF ¶

func WrapF(f http.HandlerFunc) HandlerFunc

func WrapH ¶

func WrapH(h http.Handler) HandlerFunc

type HandlersChain ¶

type HandlersChain []HandlerFunc

func (HandlersChain) Last ¶

func (c HandlersChain) Last() HandlerFunc

Last returns the last handler in the chain. ie. the last handler is the main own.

type IRouter ¶

type IRouter interface {
	IRoutes
	Group(string, ...HandlerFunc) *RouterGroup
}

type IRoutes ¶

type IRoutes interface {
	Use(...HandlerFunc) IRoutes

	Handle(string, string, ...HandlerFunc) IRoutes
	Any(string, ...HandlerFunc) IRoutes
	GET(string, ...HandlerFunc) IRoutes
	POST(string, ...HandlerFunc) IRoutes
	DELETE(string, ...HandlerFunc) IRoutes
	PATCH(string, ...HandlerFunc) IRoutes
	PUT(string, ...HandlerFunc) IRoutes
	OPTIONS(string, ...HandlerFunc) IRoutes
	HEAD(string, ...HandlerFunc) IRoutes

	StaticFile(string, string) IRoutes
	Static(string, string) IRoutes
	StaticFS(string, http.FileSystem) IRoutes
}

type Negotiate ¶

type Negotiate struct {
	Offered  []string
	HTMLName string
	HTMLData interface{}
	JSONData interface{}
	XMLData  interface{}
	Data     interface{}
}

type Param ¶

type Param struct {
	Key   string
	Value string
}

Param is a single URL parameter, consisting of a key and a value.

type Params ¶

type Params []Param

Params is a Param-slice, as returned by the router. The slice is ordered, the first URL parameter is also the first slice value. It is therefore safe to read values by the index.

func (Params) ByName ¶

func (ps Params) ByName(name string) (va string)

ByName returns the value of the first Param which key matches the given name. If no matching Param is found, an empty string is returned.

func (Params) Get ¶

func (ps Params) Get(name string) (string, bool)

Get returns the value of the first Param which key matches the given name. If no matching Param is found, an empty string is returned.

type ResponseWriter ¶

type ResponseWriter interface {
	http.ResponseWriter
	http.Hijacker
	http.Flusher
	http.CloseNotifier

	// Returns the HTTP response status code of the current request.
	Status() int

	// Returns the number of bytes already written into the response http body.
	// See Written()
	Size() int

	// Writes the string into the response body.
	WriteString(string) (int, error)

	// Returns true if the response body was already written.
	Written() bool

	// Forces to write the http header (status code + headers).
	WriteHeaderNow()
}

type RouteInfo ¶

type RouteInfo struct {
	Method  string
	Path    string
	Handler string
}

type RouterGroup ¶

type RouterGroup struct {
	Handlers HandlersChain
	// contains filtered or unexported fields
}

RouterGroup is used internally to configure router, a RouterGroup is associated with a prefix and an array of handlers (middleware)

func (*RouterGroup) Any ¶

func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes

Any registers a route that matches all the HTTP methods. GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE

func (*RouterGroup) BasePath ¶

func (group *RouterGroup) BasePath() string

func (*RouterGroup) DELETE ¶

func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes

DELETE is a shortcut for router.Handle("DELETE", path, handle)

func (*RouterGroup) GET ¶

func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes

GET is a shortcut for router.Handle("GET", path, handle)

func (*RouterGroup) Group ¶

func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup

Group creates a new router group. You should add all the routes that have common middlwares or the same path prefix. For example, all the routes that use a common middlware for authorization could be grouped.

func (*RouterGroup) HEAD ¶

func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes

HEAD is a shortcut for router.Handle("HEAD", path, handle)

func (*RouterGroup) Handle ¶

func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes

Handle registers a new request handle and middleware with the given path and method. The last handler should be the real handler, the other ones should be middleware that can and should be shared among different routes. See the example code in github.

For GET, POST, PUT, PATCH and DELETE requests the respective shortcut functions can be used.

This function is intended for bulk loading and to allow the usage of less frequently used, non-standardized or custom methods (e.g. for internal communication with a proxy).

func (*RouterGroup) OPTIONS ¶

func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc) IRoutes

OPTIONS is a shortcut for router.Handle("OPTIONS", path, handle)

func (*RouterGroup) PATCH ¶

func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc) IRoutes

PATCH is a shortcut for router.Handle("PATCH", path, handle)

func (*RouterGroup) POST ¶

func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes

POST is a shortcut for router.Handle("POST", path, handle)

func (*RouterGroup) PUT ¶

func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes

PUT is a shortcut for router.Handle("PUT", path, handle)

func (*RouterGroup) Static ¶

func (group *RouterGroup) Static(relativePath, root string) IRoutes

Static serves files from the given file system root. Internally a http.FileServer is used, therefore http.NotFound is used instead of the Router's NotFound handler. To use the operating system's file system implementation, use :

router.Static("/static", "/var/www")

func (*RouterGroup) StaticFS ¶

func (group *RouterGroup) StaticFS(relativePath string, fs http.FileSystem) IRoutes

StaticFS works just like `Static()` but a custom `http.FileSystem` can be used instead. Gin by default user: gin.Dir()

func (*RouterGroup) StaticFile ¶

func (group *RouterGroup) StaticFile(relativePath, filepath string) IRoutes

StaticFile registers a single route in order to server a single file of the local filesystem. router.StaticFile("favicon.ico", "./resources/favicon.ico")

func (*RouterGroup) Use ¶

func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes

Use adds middleware to the group, see example code in github.

type RoutesInfo ¶

type RoutesInfo []RouteInfo

Source Files ¶

  • auth.go
  • context.go
  • debug.go
  • deprecated.go
  • errors.go
  • fs.go
  • gin.go
  • logger.go
  • mode.go
  • path.go
  • recovery.go
  • response_writer.go
  • routergroup.go
  • tree.go
  • utils.go

Directories ¶

Path Synopsis
example
Package example is a generated protocol buffer package.
Package example is a generated protocol buffer package.
examples
basic command
realtime-chat command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL