Description

GIN's gin.Context implements Go context.Context interface, so we can do something like

ctx, cancel := context.WithCancel(ginCtx)

and pass this ctx around.

Can we make changes in the GIN's context Value(key interface{}) interface{} method to return the original GIN's context?

Expectations

package demo

import (
    "context"

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

func AwesomeFun(ginCtx *gin.Context) {
    ctx, cancel := context.WithCancel(ginCtx)
    defer cancel()

    test(ctx)
}

func test(ctx context.Context) {
    ginCtx, ok := ctx.Value(gin.ContextKey).(*gin.Context)
    if !ok {
        return
    }

    // We now have the GIN context in ginCtx var
}

Comment From: samc1213

For anyone trying to test a gin handler by manually cancelling a context, this code snippet might help:

req := httptest.NewRequest("POST", "/my_api", bytes.NewReader(body))
resp := httptest.NewRecorder()
tc, engine := gin.CreateTestContext(resp)
engine.ContextWithFallback = true
newReqCtx, cancel := context.WithCancel(req.Context())
req = req.WithContext(newReqCtx)
tc.Request = req

handlers.HandleMyApi(tc) // This implements /my_api

cancel() // Call this when you want to simulate client disconnect - `tc` will be context canceled

This is helpful to simulate a client disconnecting in the middle of a request in a unit/functional test.