Skip to content

Commit

Permalink
Add HandleWithInspection method
Browse files Browse the repository at this point in the history
  • Loading branch information
dnsge committed May 11, 2023
1 parent ac195e2 commit cd24694
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
28 changes: 28 additions & 0 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,31 @@ func Handle(handler Handler) gin.HandlerFunc {
}
}
}

type BeforeResFunc = func(c *gin.Context, res Res)
type BeforeErrorFunc = func(c *gin.Context, err Err)

// HandleWithInspection wraps a Handler into a gin.HandlerFunc instance.
// The inspection callbacks are invoked before writing the response and writing
// the error, respectively.
func HandleWithInspection(handler Handler, beforeRes BeforeResFunc, beforeError BeforeErrorFunc) gin.HandlerFunc {
return func(c *gin.Context) {
res, err := handler(c)
if err != nil {
if beforeError != nil {
beforeError(c, err)
}
err.WriteError(c)
return
}

// Assume that the handler already somehow took care of a response
// and knows what it's doing.
if res != nil && res != AlreadyHandled {
if beforeRes != nil {
beforeRes(c, res)
}
res.WriteResponse(c)
}
}
}
42 changes: 42 additions & 0 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"
"net/http/httptest"
"os"
"sync/atomic"
"testing"
)

Expand Down Expand Up @@ -176,3 +177,44 @@ func TestAlreadyHandled(t *testing.T) {
assert.Equal(t, http.StatusOK, r.StatusCode)
assert.Len(t, body, 0)
}

func TestHandleWithInspection(t *testing.T) {
var n atomic.Int32

router := gin.New()

// Inspecting good responses
router.GET("/handle1", HandleWithInspection(func(c *gin.Context) (Res, Err) {
return Status(http.StatusOK), nil
}, func(c *gin.Context, res Res) {
n.Add(1)
assert.Equal(t, "/handle1", c.FullPath())
assert.Equal(t, http.StatusOK, (res.(*dataResponse)).Status)
}, func(c *gin.Context, err Err) {
assert.FailNow(t, "Expected an OK response")
}))

// Inspecting error responses
router.GET("/handle2", HandleWithInspection(func(c *gin.Context) (Res, Err) {
return nil, ErrorStatus(http.StatusBadRequest)
}, func(c *gin.Context, res Res) {
assert.FailNow(t, "Expected a Bad Request response")
}, func(c *gin.Context, err Err) {
n.Add(1)
assert.Equal(t, "/handle2", c.FullPath())
assert.Equal(t, http.StatusBadRequest, (err.(*errorResponse)).Status)
}))

// Invoke good response
r := makeReq(router, "GET", "/handle1", nil)
r.Body.Close()
assert.Equal(t, http.StatusOK, r.StatusCode)

// Invoke error response
r = makeReq(router, "GET", "/handle2", nil)
r.Body.Close()
assert.Equal(t, http.StatusBadRequest, r.StatusCode)

// Confirm that both calls resulted in the callbacks (and thus their asserts) being called
assert.EqualValues(t, 2, n.Load(), "Expected both callbacks to have been invoked")
}

0 comments on commit cd24694

Please sign in to comment.