Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gin does not support Context for cancellation #153

Closed
eldilibra opened this issue Nov 18, 2014 · 12 comments
Closed

Gin does not support Context for cancellation #153

eldilibra opened this issue Nov 18, 2014 · 12 comments
Assignees

Comments

@eldilibra
Copy link

Check this out:
https://blog.golang.org/context

Future versions of Go will quite possibly make Contexts, used for canceling work and passing data around widely branching distributed systems across protocol and machine boundaries, built into the core libraries and/or language. The Go team at Google is pushing for all new code written in the community to use these Context objects so we have interoperability between open source libraries in the wild and Google Go code. The author of this article (Sameer Ajmani) just gave a great talk on this at GothamGo in NYC. I just want to call attention to the issue since Gin is an awesome, forward-looking framework, and it would be a shame to not be able to easily use it in a large, distributed system with various actors written in Go simply because it was not adapted to use Contexts. I will post back on this issue with a link to Sameer's talk when it's online.

Thanks for reading!

@eldilibra
Copy link
Author

By the way, Gin's current Context objects would be a perfect place to bring in the Google Context notion. The foundation has already been laid.

@javierprovecho
Copy link
Member

I assign it to @manucorporat , so he can know this when developing next version of Gin. Thanks @eldilibra.

@eldilibra
Copy link
Author

Grazie! 💎

@itsjamie
Copy link
Contributor

itsjamie commented Feb 6, 2015

Location of documentation regarding this has moved.

https://godoc.org/golang.org/x/net/context

The concept of a context that Go has put forward is simply an interface, a heavily documented interface, but one nevertheless, so it is very important that the implementation of this matches the documentation they provide.

I'd be willing to do some work on this on a touch and go basis.

This is a pretty important change to get in before the decision to lock the API comes for 1.0 as mentioned here. #204

@cmelbye
Copy link

cmelbye commented Apr 11, 2015

@manucorporat Could this change please be considered for the version 1.0 API freeze? I love gin and I love net/context, and I would love to see them work together. Gin using net/context instead of its own implementation of context would be a huge step toward a universal context that can work across all packages.

@manucorporat
Copy link
Contributor

@cmelbye @eldilibra @itsjamie
gin.Context conforms to the Context interface and it has an implementation like context.Background
f9952b0

@manucorporat
Copy link
Contributor

This is a direct port of the Google search example provided by the Go Team.
https://blog.golang.org/context/server/server.go

package main

import (
    "html/template"
    "time"

    "github.com/gin-gonic/gin"
    "golang.org/x/blog/content/context/google"
    "golang.org/x/blog/content/context/userip"
    "golang.org/x/net/context"
)

func main() {
    router := gin.Default()
    router.SetHTMLTemplate(resultsTemplate)
    router.GET("/search", handleSearch)
    router.Run(":8080")
}

// handleSearch handles URLs like /search?q=golang&timeout=1s by forwarding the
// query to google.Search. If the query param includes timeout, the search is
// canceled after that duration elapses.
func handleSearch(c *gin.Context) {
    var (
        ctx    context.Context
        cancel context.CancelFunc
    )
    timeout, err := time.ParseDuration(req.FormValue("timeout"))
    if err == nil {
        // The request has a timeout, so create a context that is
        // canceled automatically when the timeout expires.
        ctx, cancel = context.WithTimeout(c, timeout)
    } else {
        ctx, cancel = context.WithCancel(c)
    }
    defer cancel() // Cancel ctx as soon as handleSearch returns.

    // Check the search query.
    query := c.FormValue("q")
    if query == "" {
        c.String(400, "no query")
        return
    }

    // Store the user IP in ctx for use by code in other packages.
    userIP, err := userip.FromRequest(req)
    if err != nil {
        c.String(400, err.Error())
        return
    }

    ctx = userip.NewContext(ctx, userIP)

    // Run the Google search and print the results.
    start := time.Now()
    results, err := google.Search(ctx, query)
    elapsed := time.Since(start)
    if err != nil {
        c.String(400, err.Error())
        return
    }
    c.HTML(200, "results", struct {
        Results          google.Results
        Timeout, Elapsed time.Duration
    }{
        Results: results,
        Timeout: timeout,
        Elapsed: elapsed,
    })
}

var resultsTemplate = template.Must(template.New("results").Parse(`
<html>
<head/>
<body>
  <ol>
  {{range .Results}}
    <li>{{.Title}} - <a href="{{.URL}}">{{.URL}}</a></li>
  {{end}}
  </ol>
  <p>{{len .Results}} results in {{.Elapsed}}; timeout {{.Timeout}}</p>
</body>
</html>
`))

@cmelbye
Copy link

cmelbye commented May 18, 2015

@manucorporat Oh, very cool! I forgot that context.Context was an interface. That's pretty slick!

@manucorporat
Copy link
Contributor

yeah! @cmelbye so the approach is to make gin.Context behave like context.Background + Value.
This allows us to keep the Context size the same (we do not have to add a pointer to another Background context.

@pior
Copy link

pior commented Aug 3, 2019

The PR implementing the support for cancellation has been reverted.

Is there any plan for another attempt ?

@github-etermax
Copy link

Hi! I am also interested in this port, since we are starting a project and gin seems the perfect framework, but we need to interact with other libraries that need the use of go Context.

@pior
Copy link

pior commented Aug 2, 2020

So, I did not realize that the go Context is simply accessible via c.Request.Context().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants