Giter VIP home page Giter VIP logo

Comments (16)

manucorporat avatar manucorporat commented on April 19, 2024

Gin has a built-in error management.
You can do this:

r := gin.Default()
r.Use(gin.ErrorLogger()) // this will print all the errors
// r.Use(gin.ErrorLoggerT(gin.ErrorTypeExternal) // prints all the errors that come from you

r.GET("/path", func(c *gin.Context) {
    c.Fail(404, errors.New(errorMessage))
}

If you use the built-in error management, you do not have to change your code when entering production, simply do not use the ErrorLogger()

from gin.

patrickdappollonio avatar patrickdappollonio commented on April 19, 2024

That's not what I mean. You surely receive the error added in the logger provided, but what about the page body? What if I want to add a JSON response as a page body? Currently, looks very hack-ish to do by doing those 3 lines added in the previous comment, but there are several frameworks who actually has a function to stop execution of following handlers and show a response body of whatever we like, such as JSON, XML or plain text.

With your response, I'm assured to get an error logged in the logger, but the user will only see their 4-oh-4 browser's page, but nothing else.

from gin.

manucorporat avatar manucorporat commented on April 19, 2024

Have you tried it?
ErrorLogger prints it in the body!
see the implementation here: https://github.com/gin-gonic/gin/blob/master/logger.go#L13-L23

Maybe ErrorLogger is a bad name

from gin.

manucorporat avatar manucorporat commented on April 19, 2024

you could even create your our "error printer" middleware you can do whatever you want, print in a log, in the http response body, send them to sentry...

from gin.

patrickdappollonio avatar patrickdappollonio commented on April 19, 2024

Yeah, maybe the name isn't properly self-explanatory. Also, I'm curious: ErrorLoggerT looks like it is actually calling c.Next() so that's not preventing the execution of next middlewares. Is that right?

from gin.

manucorporat avatar manucorporat commented on April 19, 2024

c.Next() is used to execute the next handlers in the same stack frame.
func(c *gin.Context) {
// before your logic
c.Next() //your logic (handlers) are called "inside" Next()
// after your logic
// now we can read the errors array c.Errors and do whatever you want
}

so no!, Next() never change the flow order, or prevent the execution, it just allows the developers to execute the next handlers in the chain before retuning the current handler.

from gin.

manucorporat avatar manucorporat commented on April 19, 2024

You should do this:

r := gin.Default()

// this middleware will write the errors submitted from `c.Fail/c.Error` to the response body.
r.Use(gin.ErrorLogger(gin.ErrorTypeExternal))
....

func processing(c *gin.Context) {
    if err == nil {
        c.JSON(200, gin.H{"status": "everything worked fine"})
    } else {
        c.Fail(404, errors.New(errorMessage))
}

that simple! if you need custom error management feel free to implement your own middleware (it's like another handler) and read this variable: c.Errors

from gin.

patrickdappollonio avatar patrickdappollonio commented on April 19, 2024

Thank you. That's more like an answer I could understand being just a guy recently switching to gin-gonic. :)

from gin.

manucorporat avatar manucorporat commented on April 19, 2024

Awesome, please let me know if you have ideas to improve the current error management.

Right now I have an idea, c.Fail should allow any kind of type as data, not just error, so you could do this:

c.Fail(500, gin.H{"complex":"data"})

from gin.

patrickdappollonio avatar patrickdappollonio commented on April 19, 2024

Something like that was the thing I was looking for in the first place: a way to directly send proper data to the destination. gin.H could be parsed there as JSON or even XML so there's no need to send an error element to c.Fail.

from gin.

patrickdappollonio avatar patrickdappollonio commented on April 19, 2024

Think about this way: if there's a c.JSON and c.XML there should be a way to send a, i.e., 404 or 400 with those in mind, like c.AbortJSON() and c.AbortXML(). Also, there should be an option to cancel next handlers (if needed).

Let me tell you my use case: I was trying to create an API where the requests to a certain url contains in the path the customer ID, like /api/v1/:customer_id/products/add, so all of the URLs for that customer starts with the :customer_id parameter. I created a middleware so I could pre-check for the existence of the given customer_id and, if it wasn't found, send a 404 with a JSON body { "error": "customer not found" }. I've tried with the code I pasted on the first comment, but looks so hackish, so I thought to ask here if there was a better way. My API is sending JSON responses so it makes sense to send JSON, but the API could also be in XML.

from gin.

manucorporat avatar manucorporat commented on April 19, 2024

You can also do:

c.JSON(404, errordata)
c.Abort(-1)

I think this is a pretty good solution for your problem.

from gin.

manucorporat avatar manucorporat commented on April 19, 2024

some code from my startup:

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

        // Try to get an authorization pass.
        // We provide a AuthRequest and we should get AuthPass in response
        pass, err := SERVER.GetAuthPass(AuthRequest{
            UserId: c.Request.Header.Get("F_UserID"),
            Token:  c.Request.Header.Get("F_Token"),
            UDID:   c.Request.Header.Get("F_UDID"),
        })

        if err != nil {
            // Unauthorized
            c.Fail(401, err)

        } else {
            // Map authpass to the current http request
            c.Set("auth", pass)
        }
    }
}

we do not use:

c.JSON(404, errordata)
c.Abort(-1)

because in our case, the error could be security related, we do not want to show it in production. But in your case looks completely fine!

from gin.

pkopac avatar pkopac commented on April 19, 2024

Hi! Please, could you mention this on the README.md, at least in one example? That would spare others searching in discussions for how to handle errors in gin. Thank you.
PS: nice framework!

from gin.

fabulousduck avatar fabulousduck commented on April 19, 2024

Currently i ama getting type *gin.Context has no field or method Fail)
I have attached the error logger like so
router.Use(gin.ErrorLogger(gin.ErrorTypeExternal))

Was this feature removed or am i doing something wrong ?

from gin.

abdennour avatar abdennour commented on April 19, 2024

c.Fail undefined (type *gin.Context has no field or method Fail)

from gin.

Related Issues (20)

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.