Skip to content

Context

Fox handlers use *fox.Context, a thin wrapper around Gin’s *gin.Context. It embeds Gin’s context, so Gin methods such as Query, Param, JSON, Abort, and GetHeader are available directly, while Fox adds request body caching, TraceID helpers, logger access, and context.Context compatibility.

Fox handlers can optionally accept a *fox.Context parameter:

r.GET("/path", func(c *fox.Context) (any, error) {
// Access context
return response, nil
})

Gin middleware still uses *gin.Context:

func MyMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("user_id", 123)
c.Next()
}
}
name := c.Query("name") // Get query param
page := c.DefaultQuery("page", "1") // With default value
r.GET("/user/:id", func(c *gin.Context) {
id := c.Param("id")
})
token := c.GetHeader("Authorization")
userAgent := c.Request.UserAgent()
var data map[string]any
c.ShouldBindJSON(&data)

Fox also provides RequestBody() for reading and caching the raw request body. It restores the body so later binding can read it again:

body, err := c.RequestBody()
ip := c.ClientIP()
c.JSON(200, gin.H{
"message": "success",
})
c.String(200, "Hello, World!")
c.HTML(200, "index.html", gin.H{
"title": "Home",
})
c.Redirect(302, "/new-path")
c.Status(204) // No Content
c.Set("user_id", 123)
userID := c.GetInt("user_id")
value, exists := c.Get("key")
userID := c.MustGet("user_id").(int)
file, _ := c.FormFile("file")
c.SaveUploadedFile(file, "./uploads/"+file.Filename)
form, _ := c.MultipartForm()
files := form.File["files"]
for _, file := range files {
c.SaveUploadedFile(file, "./uploads/"+file.Filename)
}
c.File("./assets/image.png")
c.SetCookie(
"session_id", // name
"abc123", // value
3600, // maxAge (seconds)
"/", // path
"example.com", // domain
false, // secure
true, // httpOnly
)
value, err := c.Cookie("session_id")

Stop processing and return:

if !isAuthenticated(c) {
c.JSON(401, gin.H{"error": "Unauthorized"})
c.Abort()
return
}
c.Logger.Info("Processing request")
traceID := c.TraceID()

*fox.Context implements the standard context methods by delegating to c.Request.Context():

select {
case <-c.Done():
return nil, c.Err()
default:
}
value := c.Value(myKey)