Code Monkey home page Code Monkey logo

gin's Introduction

Gin Web Framework

Build Status codecov Go Report Card GoDoc Sourcegraph Open Source Helpers Release TODOs

Gin is a web framework written in Go. It features a martini-like API with performance that is up to 40 times faster thanks to httprouter. If you need performance and good productivity, you will love Gin.

The key features of Gin are:

  • Zero allocation router
  • Fast
  • Middleware support
  • Crash-free
  • JSON validation
  • Routes grouping
  • Error management
  • Rendering built-in
  • Extendable

Getting started

Prerequisites

  • Go: any one of the three latest major releases (we test it with these).

Getting Gin

With Go module support, simply add the following import

import "github.com/gin-gonic/gin"

to your code, and then go [build|run|test] will automatically fetch the necessary dependencies.

Otherwise, run the following Go command to install the gin package:

$ go get -u github.com/gin-gonic/gin

Running Gin

First you need to import Gin package for using Gin, one simplest example likes the follow example.go:

package main

import (
  "net/http"

  "github.com/gin-gonic/gin"
)

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

And use the Go command to run the demo:

# run example.go and visit 0.0.0.0:8080/ping on browser
$ go run example.go

Learn more examples

Quick Start

Learn and practice more examples, please read the Gin Quick Start which includes API examples and builds tag.

Examples

A number of ready-to-run examples demonstrating various use cases of Gin on the Gin examples repository.

Documentation

See API documentation and descriptions for package.

All documentation is available on the Gin website.

Articles about Gin

A curated list of awesome Gin framework.

Benchmarks

Gin uses a custom version of HttpRouter, see all benchmarks details.

Benchmark name (1) (2) (3) (4)
BenchmarkGin_GithubAll 43550 27364 ns/op 0 B/op 0 allocs/op
BenchmarkAce_GithubAll 40543 29670 ns/op 0 B/op 0 allocs/op
BenchmarkAero_GithubAll 57632 20648 ns/op 0 B/op 0 allocs/op
BenchmarkBear_GithubAll 9234 216179 ns/op 86448 B/op 943 allocs/op
BenchmarkBeego_GithubAll 7407 243496 ns/op 71456 B/op 609 allocs/op
BenchmarkBone_GithubAll 420 2922835 ns/op 720160 B/op 8620 allocs/op
BenchmarkChi_GithubAll 7620 238331 ns/op 87696 B/op 609 allocs/op
BenchmarkDenco_GithubAll 18355 64494 ns/op 20224 B/op 167 allocs/op
BenchmarkEcho_GithubAll 31251 38479 ns/op 0 B/op 0 allocs/op
BenchmarkGocraftWeb_GithubAll 4117 300062 ns/op 131656 B/op 1686 allocs/op
BenchmarkGoji_GithubAll 3274 416158 ns/op 56112 B/op 334 allocs/op
BenchmarkGojiv2_GithubAll 1402 870518 ns/op 352720 B/op 4321 allocs/op
BenchmarkGoJsonRest_GithubAll 2976 401507 ns/op 134371 B/op 2737 allocs/op
BenchmarkGoRestful_GithubAll 410 2913158 ns/op 910144 B/op 2938 allocs/op
BenchmarkGorillaMux_GithubAll 346 3384987 ns/op 251650 B/op 1994 allocs/op
BenchmarkGowwwRouter_GithubAll 10000 143025 ns/op 72144 B/op 501 allocs/op
BenchmarkHttpRouter_GithubAll 55938 21360 ns/op 0 B/op 0 allocs/op
BenchmarkHttpTreeMux_GithubAll 10000 153944 ns/op 65856 B/op 671 allocs/op
BenchmarkKocha_GithubAll 10000 106315 ns/op 23304 B/op 843 allocs/op
BenchmarkLARS_GithubAll 47779 25084 ns/op 0 B/op 0 allocs/op
BenchmarkMacaron_GithubAll 3266 371907 ns/op 149409 B/op 1624 allocs/op
BenchmarkMartini_GithubAll 331 3444706 ns/op 226551 B/op 2325 allocs/op
BenchmarkPat_GithubAll 273 4381818 ns/op 1483152 B/op 26963 allocs/op
BenchmarkPossum_GithubAll 10000 164367 ns/op 84448 B/op 609 allocs/op
BenchmarkR2router_GithubAll 10000 160220 ns/op 77328 B/op 979 allocs/op
BenchmarkRivet_GithubAll 14625 82453 ns/op 16272 B/op 167 allocs/op
BenchmarkTango_GithubAll 6255 279611 ns/op 63826 B/op 1618 allocs/op
BenchmarkTigerTonic_GithubAll 2008 687874 ns/op 193856 B/op 4474 allocs/op
BenchmarkTraffic_GithubAll 355 3478508 ns/op 820744 B/op 14114 allocs/op
BenchmarkVulcan_GithubAll 6885 193333 ns/op 19894 B/op 609 allocs/op
  • (1): Total Repetitions achieved in constant time, higher means more confident result
  • (2): Single Repetition Duration (ns/op), lower is better
  • (3): Heap Memory (B/op), lower is better
  • (4): Average Allocations per Repetition (allocs/op), lower is better

Middlewares

You can find many useful Gin middlewares at gin-contrib.

Users

Awesome project lists using Gin web framework.

  • gorush: A push notification server written in Go.
  • fnproject: The container native, cloud agnostic serverless platform.
  • photoprism: Personal photo management powered by Go and Google TensorFlow.
  • lura: Ultra performant API Gateway with middlewares.
  • picfit: An image resizing server written in Go.
  • dkron: Distributed, fault tolerant job scheduling system.

Contributing

Gin is the work of hundreds of contributors. We appreciate your help!

Please see CONTRIBUTING for details on submitting patches and the contribution workflow.

gin's People

Contributors

0x2d3c avatar andreynering avatar appleboy avatar austinheap avatar bestgopher avatar bisstocuz avatar dependabot[bot] avatar dmarkham avatar easonlin404 avatar flc1125 avatar guonaihong avatar javierprovecho avatar jbampton avatar jincheng9 avatar justinbeckwith avatar kmulvey avatar lancoliu avatar manucorporat avatar mopemope avatar msoedov avatar mstmdev avatar panjf2000 avatar pinscript avatar sairoutine avatar sashamelentyev avatar se77en avatar thinkerou avatar vkd avatar y-yagi avatar zihengcat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gin's Issues

google group creation, please!

Hi guys,

Just passing here to ask you guys, when you have some time, to create a google group.
I think it is very usefull and it will be nice to keep reading and helping the users through there.

You guys should be there with Gorilla, Revel, Martini and others...

URL with the trailing slash

I can't specify a URL with a slash at the end: router.GET("/login/", login).

prefix := path.Join(group.prefix, component) in func (group *RouterGroup) Group(...) and p = path.Join(group.prefix, p) in func (group *RouterGroup) Handle(...) removes the trailing slash.

encoding/xml cannot marshal maps

This code from the documentation:

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

Will result in a xml: unsupported type: gin.H error.

Marshalling a specific type would of course work:

type Response struct {
        Name string
}
c.XML(200, Response{"Alexander Nyquist"})

// <Response><Name>Alexander Nyquist</Name></Response>

Logged Intrusion?

I started poking around with the samples locally to test a few things to use gin for an API handler. Anyways, the live logger in my terminal started reporting activity after an hour of inactivity. Logs are below:

austin@cloud:/var/go/src/hello$ go run main.go
2014/07/05 12:55:26 / in 129.33us
2014/07/05 12:55:44 / in 128.017us
2014/07/05 12:55:45 /favicon.ico in 880ns
2014/07/05 12:56:04 / in 40.44us
2014/07/05 13:11:55 http://best-proxies.ru/azenv.php?rand=7374898ec89df9a63dcf8f                                                                                        0aac549df5 in 1.063us
2014/07/05 13:12:21 http://92.222.28.46/httptest.php in 654ns
2014/07/05 13:12:21 http://www.google.com/search?q=wp.pl in 621ns

The snippet I was running in main.go is as follows:

 package main
 import "github.com/gin-gonic/gin"

 func main() {
     r := gin.Default()
     r.GET("/", func(c *gin.Context){
         c.JSON(200, gin.H{"message": "hello world!", "success": true})
     })
     r.Run(":8080")
 }

I installed Go 1.3 using GVM on Ubuntu 12.04, completely up to date on all other system binaries and no other point of intrusion other than right there. What could have caused those logs to show that? Keep in mind those logs are all from gin's logger.

Any ideas?

Issue with custom CORS header middleware

I have created a the following middleware function but It doesn't seem to be working properly. When I do an options request I get a 404 and I get http: multiple response.WriteHeader calls in my console.

func CORSMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {

        c.Writer.Header().Set("Content-Type", "application/json")
        c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
        c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
        if c.Req.Method == "OPTIONS" {
            fmt.Println("options")
            c.Abort(200)
            return
        }
        // c.Next()
    }
}

I have mounted it as the before anything else with the following.

r.Use(CORSMiddleware())

Go1.3 only support?

I was experimenting with the new sync.Pool. It will make Gin a little bit faster running in a single core and much faster when running in several cores.

Sadly sync.Poolis only available in Go1.3. So if Gin uses it, we can't support 1.2.

What do you guys think? would you have any problem with that?

gorilla websocket error

I am trying to use gin with gorilla/websocket:

func ServeSocket(c *gin.Context) {
    conn, err := websocket.Upgrade(c.Writer, c.Request, nil, 1024, 1024)
    if err != nil {
        http.Error(w, "Websocket error", 400)
        fmt.Println(err)
        return
    }
}

But I am getting an error: websocket: response does not implement http.Hijacker.

As I see, there is no Hijack method on c.Writer, maybe it should be added? Or please tell my how can I use it without changing gin code. Thanks.

Content negotiation

My application will serve an API that is available via JSON and XML. There is currently not a convenient way of doing this in Gin. As it is now, I end up with a bunch of switch-cases.

What do you guys say about supporting (maybe a basic implementation) content negotiation (conneg)[0]?

The most simple API could look something like this:

r.GET("/ping", func(c *gin.Context) {
    c.Negotiate(200, Response{foo: "Bar"})
})

The response format is then inferred from the Accept-header.

We could also implement a mechanism to try and infer what to return based on URL parameters (/api/?format=xml/json) or file endings (api.json/xml).

Is this something you guys want to move forward with? If so, let me know and I'll implement it.

[0] http://en.wikipedia.org/wiki/Content_negotiation

A better way to send an error as JSON/XML, canceling next handlers

I've been trying naively to send a 400 http status code with a JSON message in it, adding proper headers as "application/json" and a body with a proper error message. The first thing I thought was using c.JSON(400, gin.H{"error": "error here"}) but if this appears in a middleware, and there are new handlers or middlewares following up, I receive http: multiple response.WriteHeader calls from the logs.

I assume the problem is that actually there's nothing underlying preventing to execute next middlewares / handlers if I send an error. I've checked the auth.go file with the basic auth middleware but that's only sending a 401 header, with no body at all.

So I've ended up doing this:

c.Writer.Header().Add("Content-Type", "application/json")
c.Fail(404, errors.New(errorMessage))
c.JSON(-1, gin.H{"error": errorMessage})

So I append first the proper JSON header, then calling fail (so, underlying the function properly cancels all the subsequent middlewares / handlers) and then, after a quick check to the JSON method, I've seen that if the header is 0 or up, the header gets added, but since I've already added one on c.Fail() I don't want a new one, so I pass -1.

Is there a proper way to send this? I mean, there's a shorthand for proper JSON responses but nothing that actually ends the subsequent middlewares even if I want to send a response body there.

Organize a decent template system

I know this might be caused by my lack of experience or the way html/template works, but I cannot figure how I could get:

  1. an easy to maintain hierarchical template structure
  2. how to organize this so that I can easily use it from the app.

In my ideal world:

  1. I could have a base.tmpl
  2. this could be extended/customized in final templates
  3. templates would be organized in a directory hierarchy that emulates the URL structure (so over time it's easy to figure out where to look for things

I have tried something very similar to what was described in #27, but haven't been able to get it to work.

Update: I got the solution described in #27 to work.

I'm not suggesting gin to implement from scratch a templating engine, but:

  1. I'd really find very helpful seeing a more realistic use of templates
  2. if this is not doable/optimal with html/template only then maybe recommending a solution.

How can I use html template?

Hello.
Thank you for sharing nice framework.

I wonder how can I use html template in gin framework.

I've tried below,

html := template.ParseFiles("file1", "file2")
r.HTMLTemplates = html

Then I've got an error bellow.

multiple-value "html/template".ParseFiles() in single-value context

And I've researched bit more.
Finally discovered Context.HTML.

func render(c *gin.Context) {
    c.HTML(200, "template/index.html", gin.H{})
}

but it gave me a blank page.

How can I use html template?

[Binding] Embedded struct fails required condition

The following will not be caught by binding.JSON.Bind()

type T struct {
    Embedded E `json:"embedded" binding:"required"`
}

type E struct {
    Field string `json:"field_name"`
}

The expected error would be "Required Embedded"
If we change E to

type E struct {
    Field string `json:"field_name" binding:"required"`
}

it will be caught with the error message "Required Field", with no information about that Field resides in an embedded struct .

iota results in missing parameter

Synopsis:
When using iota to default a const group to a 0 value, and sending a 0 value via a JSON payload, the binding process fails believing the required value is missing.

Schema:

const (
    EventTypeEntry = iota
    EventTypeExit
)

Event struct {
        Type      int    `bson:"type" json:"type" binding:"required"`
        Timestamp string `bson:"timestamp" json:"timestamp" binding:"required"`
    }

JSON:

{
    "events": [
        {
            "timestamp": "2014-08-18T14:03:26.761-0400",
            "type": 0
        }
    ]
}

Response:

[GIN] 2014/08/18 - 14:08:03 | 400 |     78.894us | 127.0.0.1:52575 POST /v1/events
Error #01: Required Type 
     Meta: Operation aborted

Can't unmarshal JSON array with c.EnsureBody

trying this:

var json []api.Patch
if c.EnsureBody(&json) {
    ... 

and i'm getting this:

2014/07/09 15:33:07 PANIC: reflect: NumField of non-struct type
/usr/local/go/src/pkg/reflect/type.go:658 (0x4ad079)
    (*rtype).NumField: panic("reflect: NumField of non-struct type")
/home/ben/go/src/github.com/gin-gonic/gin/binding/binding.go:164 (0x540c5b)
    Validate: for i := 0; i < typ.NumField(); i++ {
/home/ben/go/src/github.com/gin-gonic/gin/binding/binding.go:37 (0x53fc01)
    jsonBinding.Bind: return Validate(obj)
<autogenerated>:2 (0x5413ba)

c.Html(...) default suffix

I hope the suffix will be defautl as ".tmpl", so I can use like c.Html(200,"index",nil) ,this will find index.tmpl, if c.Html(200,"index.html".nil) will find the index.html.
ps: i'm not a english user, so my English is very bad, please forgive me

Development mode

IDEAS

  • HTML rendering without cache.
  • Additional logging
    • Log existing routes
    • Log listening port

API

  • Debug mode by default
  • Using an environment variable called GIN_MODE that is loaded at init time.
$ export GIN_MODE=release
  • Developer-API.
    Any call to this method would replace the default option.
gin.SetMode(gin.DebugMode)

Log example:

~ $ go run test.go
[GIN-debug] POST  /v1/login                 --> main.loginEndpoint (3 handlers)
[GIN-debug] POST  /v1/submit                --> main.submitEndpoint (3 handlers)
[GIN-debug] GET   /v1/read                  --> main.readEndpoint (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080

undefined: sync.Pool error

go get github.com/gin-gonic/gin                                                                                                                      
# github.com/gin-gonic/gin
../go/src/github.com/gin-gonic/gin/gin.go:74: undefined: sync.Pool

sync.Pool seems to be introduced in go1.3 meaning gin no longer works with Google App Engine, drone.io and others running go1.2.

Is this intentional?

Unable to get http response code in middle ware.

If I wanted to create a simple logger to mimic apache access logs, it is currently impossible to get the written status code. http.ResponseWriter's implementation is http.response which is unexported. As such there is no way to get to it's also unexported http.response.status.

You can get the entire header map from http.ResponseWriter.Header() however it won't give you anything about the status because it never actually gets written to that map.

Mimicking apache access logs may not be ideal, but I will surely want to record the return code in some way.

Some (broken) sample code trying to implement a proper access_log logger.

 func Logger() gin.HandlerFunc {
    return func(c *gin.Context) {
        t := time.Now()
        ip, err := net.ResolveTCPAddr("tcp", c.Req.RemoteAddr)
        if err != nil {
            c.Abort(500)
        }

        // before request
        c.Next()
        // after request

        var user string
        if c.Req.URL.User != nil {
            user = c.Req.URL.User.Username()
        } else {
            user = "-"
        }

        latency := time.Since(t)
        statusCode := c.Writer.(*http.Response).StatusCode
        //statusCode := c.Writer.(*http.response).status
        log.Print(latency)
        fmt.Printf("%v - %v [%v] \"%v %v %v\" %v %v\n",
            ip.IP, user, t, c.Req.Method, c.Req.URL.Path,
            c.Req.Proto, statusCode, c.Req.ContentLength)
    }
}

JSON does not set the correct Content-Type header

Hi,

I'm experimenting with Gin and stumbled on some problems. The code below does not result in a Content-Type: application/json being set in the response.

func main() {
    r := gin.Default()
    r.GET("/test", func(c *gin.Context) {
        c.JSON(200, gin.H{"status": "you are logged in"})
    })

    r.Run(":8082")
}

Response:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 6
Date: Tue, 01 Jul 2014 07:13:36 GMT

I've tried fixing the issue myself but i cannot find a way to set a header. All headers are just ignored.

Anyone else experiencing the same problem?

I'm on Go 1.1 on Windows so that might have something to do with it.

How to write request test ?

Use std and http handler can write following test case, but how to do similar thing in gin ?

I think the main point should be how to create a request and response and fill it into gin's Context structure...

package main

  import (
    "net/http"
    "net/http/httptest"
    "testing"
  )

func IndexHandler(res http.ResponseWriter, req *http.Request) {
    data, _ := json.Marshal("{'hello':'wercker!'}")
    res.Header().Set("Content-Type", "application/json; charset=utf-8")
    res.Write(data)
}

func TestHandleIndexReturnsWithStatusOK(t *testing.T) {
    request, _ := http.NewRequest("GET", "/", nil)
    response := httptest.NewRecorder()

    IndexHandler(response, request)

    if response.Code != http.StatusOK {
        t.Fatalf("Non-expected status code%v:\n\tbody: %v", "200", response.Code)
    }
}

Rename context.EnsureBody() to context.ValidateBody()

I feel like the current method name is not pretty clear.

Right now, we have two methods for JSON validation (XML validation is coming soon).

func (c *Context) ParseBody(item interface{}) error

and

func (c *Context) EnsureBody(item interface{}) bool

https://github.com/gin-gonic/gin/blob/master/gin.go#L281-L298

The first one ParseBody() unmarshal the JSON stream and also validates it, if an error occurred it is returned, otherwise, nil is returned.

The second one EnsureBody() calls ParseBody() internally, if an error occurred, a 400 error is automatically responded, and a false boolean is returned. This means that using EnsureBody() you only should handle the "true" case.

        if c.EnsureBody(&json) == true {
            // do something important
            c.JSON(200, gin.H{"status": "ok"})
        } else {
            // pointless
        }

if you need to manage the false statement, ParseBody() is the way to go.

        if err := c.ParseBody(&json); err == nil {
            // do something important
            c.JSON(200, gin.H{"status": "ok"})
        } else {
            // do stuff with err ;)
        }

The idea is to rename EnsureBody() to

func (c *Context) ValidateBody(item interface{}) bool

thoughts?

ROADMAP for 0.2

Roadmap for 0.2

  • Performance improments, reduce allocation and garbage collection overhead
  • Fix bugs
  • Ask our designer for a cool logo
  • Add tons of unit tests and benchmarks
  • Improve logging system
  • Improve JSON/XML validation using bindings
  • Improve XML support
  • Improve documentation
  • Add more cool middlewares, for example redis catching (this also helps developers to understand the framework)

I will create an issue for each one if it was not created yet and link them from here.

How can I use websocket

Hello! Thank you for cool framework!

I use code.google.com/p/go.net/websocket package

http.Handle("/socket", websocket.Handler(echoHandler))

How can I handle websocket with gin?

Important performance improvement

I just tested a new system to reduce the allocation and garbage collection overhead.

Some benchmarks:

Current (old) system:

BenchmarkGin_Param   5000000           340 ns/op         161 B/op          2 allocs/op
BenchmarkGin_Param5  5000000           537 ns/op         290 B/op          2 allocs/op
BenchmarkGin_Param20     1000000          1278 ns/op         774 B/op          2 allocs/op
BenchmarkGin_ParamWrite  5000000           384 ns/op         161 B/op          2 allocs/op
BenchmarkGin_GithubStatic   10000000           239 ns/op         128 B/op          1 allocs/op

New system:

BenchmarkGin_Param  10000000           249 ns/op          33 B/op          1 allocs/op
BenchmarkGin_Param5  5000000           442 ns/op         162 B/op          1 allocs/op
BenchmarkGin_Param20     1000000          1102 ns/op         646 B/op          1 allocs/op
BenchmarkGin_ParamWrite  5000000           319 ns/op          33 B/op          1 allocs/op
BenchmarkGin_GithubStatic   10000000           167 ns/op           0 B/op          0 allocs/op

But this is even better.

  • It also reduces drastically the garbage collection stress in a full-loaded system.
  • This system allows the community to extend the gin.Context (adding more static variables etc...) without degrading the performance
  • The implementation is still hacky, the performance can be even better once we make this system CPU cache friendly

Setup of gin with Google App Engine

I don't seem to be able to setup gin with GAE. I understand that the trunk is Go1.3, but checking out the app_engine branch and running go install results in an error too:

go install
deprecated.go:4:2: cannot find package "github.com/gin-gonic/gin/binding" in any of:
    /usr/local/Cellar/go/1.2.2/libexec/src/pkg/github.com/gin-gonic/gin/binding (from $GOROOT)
    /Users/apopescu/Dropbox/workspace/golang/sportscal/src/github.com/gin-gonic/gin/binding (from $GOPATH)
    /Users/apopescu/.golang/src/github.com/gin-gonic/gin/binding
go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/apopescu/Dropbox/workspace/golang/sportscal:/Users/apopescu/.golang"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.2.2/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.2.2/libexec/pkg/tool/darwin_amd64"
TERM="dumb"
CC="clang"
GOGCCFLAGS="-g -O2 -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fno-common"
CXX="clang++"
CGO_ENABLED="1"

go get failing

When running

go get github.com/gin-gonic/gin

I get an error, seems master branch is broken

# github.com/gin-gonic/gin
../../gin-gonic/gin/gin.go:74: undefined: sync.Pool

Session Mgmt?

Hi,

Any plans to support session management like github.com/gorilla/sessions?

Inability to use '/' for static files

Hi,

I'm very sad to find out that gin doesn't allow you to have '/' as your top level route for static files. Almost every single web framework out there assumes that the static files you have inside your project are going to be served from $static_dir and they will be mapped as HTTP routes from '/'. An example from express.js does this:

server.use(express.static(__dirname + '/public'));

Doing that maps "/index.html" to "public/index.html". Expected behavior. Any other frameworks like Rails or Martini have this convention as well. Basically it means that if you have the following files inside a "./public" directory:

--- public/
 |
 |--- index.html
 |--- css/
 |      |--- app.css

Files will be accessible with HTTP requests like $server_url/index.html or $server_url/css/app.css. Gin disallows you to do this (although the problem lies in httprouter), and forces you to have a separate (non-top-level) route for public/static files like:

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

So, if I use this:

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

I get this panic:

panic: wildcard route conflicts with existing children

goroutine 16 [running]:
runtime.panic(0x2d5da0, 0xc2080013a0)
    /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
github.com/julienschmidt/httprouter.(*node).insertChild(0xc208004360, 0xc208001302, 0xc208040de1, 0x10, 0xc208040e20)
    /Users/cachafla/Code/Go/go/src/github.com/julienschmidt/httprouter/tree.go:201 +0x11e
github.com/julienschmidt/httprouter.(*node).addRoute(0xc208004360, 0xc208040de1, 0x10, 0xc208040e20)
    /Users/cachafla/Code/Go/go/src/github.com/julienschmidt/httprouter/tree.go:172 +0x952
github.com/julienschmidt/httprouter.(*Router).Handle(0xc208040c60, 0x3ce8b0, 0x3, 0xc208040de0, 0x11, 0xc208040e20)
    /Users/cachafla/Code/Go/go/src/github.com/julienschmidt/httprouter/router.go:205 +0x186
github.com/gin-gonic/gin.(*RouterGroup).Handle(0xc208070340, 0x3ce8b0, 0x3, 0xc208040de0, 0x11, 0xc2080380a0, 0x1, 0x1)
    /Users/cachafla/Code/Go/go/src/github.com/gin-gonic/gin/gin.go:223 +0x477
github.com/gin-gonic/gin.(*RouterGroup).GET(0xc208070340, 0xc208040d40, 0x11, 0xc2080380a0, 0x1, 0x1)
    /Users/cachafla/Code/Go/go/src/github.com/gin-gonic/gin/gin.go:233 +0x6d
github.com/gin-gonic/gin.(*RouterGroup).Static(0xc208070340, 0xc208040d40, 0x11, 0x3eed10, 0x8)
    /Users/cachafla/Code/Go/go/src/github.com/gin-gonic/gin/gin.go:276 +0x252

It might seem silly, but this is actually an incorrect behavior for defining a static directory to be served by the HTTP server. The router should be able to handle multiple matching routes, as almost any other HTTP library out there In my case, I really need my index.html to be /index.html and not /static/index.html.

In any case, I understand that this comes from a predefined httprouter behavior and I acknowledge that I could use a prefix and "deal with it", but I would prefer if this worked as it should. If somebody has any tips on how to workaround this issue I would really appreciate it, thanks!

Binding doesn't support multipart/form-data

context.go only supports application/x-www-form-urlencoded for forms:
case c.Request.Method == "GET" || ctype == MIMEPOSTForm:
b = binding.Form

[GIN] 2014/09/01 - 03:48:13 | 400 | 248.788us | 172.4.231.9 POST /post
Error #1: unknown content-type: multipart/form-data
Meta: Operation aborted

Pluggable view renderer

Hi Guys,

I've been playing with the framework and overal I really like it. One point where I think it's lacking is a pluggable view rendering engine. The engine struct is currently tied to HTMLTemplate so it's not really easy to switch it out and use a different implementation when appropriate. Wouldn't it be better to introduce interfaces for these components? Say, for instance, in the case of the view rendering you'd use an interface:

type ViewRenderer interface {
    ExecuteTemplate(wr io.Writer, name string, data interface{}) error
}

// And engine being
Engine struct {
       *RouterGroup
       HtmlRenderer ViewRenderer
       cache sync.Pool
       handlers404 []HandlerFunc
       router *httprouter.Router
}

This way, by default, you'd be able to just assign an html/template instance for a 'batteries included' approach while maintaining the performance characteristics because you don't incur a performance penalty for wrapping the default template package.

People (like me) who'd like a little bit more functionality in the view engine could just easily swap out the default html/template package and encapsulate/augment it with more advanced layout functionality for instance. Or use a different view renderer all together of course.

I'd be more than happy to work on this and submit a pull request but I'd rather start a discussion first to see if this a direction you'd be willing to go.

Disclaimer: I'm a go noob so if this is not really 'idiomatic' go, please correct me :)

the router not overrite

if you register the router
r.GET("/test/:name", func(c *gin.Context) {
name := c.Params.ByName("name")
c.String(200, "the parmas are"+name)
})
this will error when compiling, they can't coexist!
r.GET("/test/json", func(c *gin.Context) {
c.String(200, "this will error because the router top")
})

Change c.Req to c.Request similar to c.Writer

Hi,

So, this is not an urgent request, but I think it's only fair to call things in their actual names.

store.Get(c.Request,"session-name")
// instead of
store.Get(c.Req,"session-name")

I'm not going to go crazy about it and request something like this 😄

Context struct {
    Request   *http.Request
    ResponseWriter   http.ResponseWriter
...

but this improve the readability of the context, and indicate that these are the http request and writer.

r.group not working

I made a quick test with custom middleware groups:

func TestHandle() gin.HandlerFunc {
    return func(c *gin.Context) {
        fmt.Printf("TEST: \n" )

        c.Next()

        fmt.Printf("TEST2: \n" )
    }
}

 r.Group("/", TestHandle()) {
        r.GET("/test", func(c *gin.Context) {
            fmt.Printf("test")
            c.String(200, "ok")
        })
}

TEST and TEST2 never gets printed.

I do get a warning:
[GIN] WARNING. Headers were already written!

Any ideas ?

Support for 405 Method Not Allowed

Would be great to easy add support for status 405, specially when creating a REST API.

And do you have any example adding a more verbose access logger? Logging response-code, user-agent, client-ip, etc?

Keep up the good work! 👍

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.