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

feat: enable WrappedContext for router specifics access points in Adapters #699

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions adapters/humabunrouter/humabunrouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ func (c *bunContext) Operation() *huma.Operation {
return c.op
}

func (c *bunContext) WrappedContext() interface{} {
return c.r
}

func (c *bunContext) Context() context.Context {
return c.r.Context()
}
Expand Down
4 changes: 4 additions & 0 deletions adapters/humachi/humachi.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func (c *chiContext) Operation() *huma.Operation {
return c.op
}

func (c *chiContext) WrappedContext() interface{} {
return c.r
}

func (c *chiContext) Context() context.Context {
return c.r.Context()
}
Expand Down
4 changes: 4 additions & 0 deletions adapters/humaecho/humaecho.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ func (c *echoCtx) Operation() *huma.Operation {
return c.op
}

func (c *echoCtx) WrappedContext() interface{} {
return c.orig
}

func (c *echoCtx) Context() context.Context {
return c.orig.Request().Context()
}
Expand Down
4 changes: 4 additions & 0 deletions adapters/humafiber/humafiber.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ func (c *fiberCtx) Matched() string {
return c.orig.Route().Path
}

func (c *fiberCtx) WrappedContext() interface{} {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For fiber this is unsafe.

Please take a look to this comment - #686 (comment)
and this PR - #693

	/*
	 * Web framework "fiber" https://gofiber.io/ uses high-performance zero-allocation "fasthttp" server https://github.com/valyala/fasthttp
	 *
	 * The underlying fasthttp server prohibits to use or refer to `*fasthttp.RequestCtx` outside handler
	 * The quote from documentation to fasthttp https://github.com/valyala/fasthttp/blob/master/README.md
	 *
	 * > VERY IMPORTANT! Fasthttp disallows holding references to RequestCtx or to its' members after returning from RequestHandler. Otherwise data races are inevitable. Carefully inspect all the net/http request handlers converted to fasthttp whether they retain references to RequestCtx or to its' members after returning
	 *
	 * As the result "fiber" prohibits to use or refer to `*fiber.Ctx` outside handler
	 * The quote from documentation to fiber https://docs.gofiber.io/#zero-allocation
	 *
	 * > Because fiber is optimized for high-performance, values returned from fiber.Ctx are not immutable by default and will be re-used across requests. As a rule of thumb, you must only use context values within the handler, and you must not keep any references. As soon as you return from the handler, any values you have obtained from the context will be re-used in future requests and will change below your feet
	 *
	 * To deal with these limitations, the contributor of to this adapter @excavador (Oleg Tsarev, email: [email protected], telegram: @oleg_tsarev) is clear variable explicitly in the end of huma.Adapter methods Handle and ServeHTTP
	 *
	 * You must NOT use member `unsafeFiberCtx` directly in adapter, but instead use `orig()` private method
	 */
	unsafeFiberCtx  *fiber.Ctx
	unsafeGolangCtx context.Context

Copy link
Owner

@danielgtaylor danielgtaylor Jan 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would using orig() here help? @genslein do you need Fiber support?

return c.orig
}

func (c *fiberCtx) Context() context.Context {
return &contextAdapter{
Ctx: c.orig,
Expand Down
4 changes: 4 additions & 0 deletions adapters/humaflow/humaflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func (c *goContext) Operation() *huma.Operation {
return c.op
}

func (c *goContext) WrappedContext() interface{} {
return c.r
}

func (c *goContext) Context() context.Context {
return c.r.Context()
}
Expand Down
4 changes: 4 additions & 0 deletions adapters/humagin/humagin.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ func (c *ginCtx) Operation() *huma.Operation {
return c.op
}

func (c *ginCtx) WrappedContext() interface{} {
return c.orig
}

func (c *ginCtx) Context() context.Context {
return c.orig.Request.Context()
}
Expand Down
4 changes: 4 additions & 0 deletions adapters/humago/humago.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func (c *goContext) Operation() *huma.Operation {
return c.op
}

func (c *goContext) WrappedContext() interface{} {
return c.r
}

func (c *goContext) Context() context.Context {
return c.r.Context()
}
Expand Down
4 changes: 4 additions & 0 deletions adapters/humahttprouter/humahttprouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ func (c *httprouterContext) Operation() *huma.Operation {
return c.op
}

func (c *httprouterContext) WrappedContext() interface{} {
return c.r
}

func (c *httprouterContext) Context() context.Context {
return c.r.Context()
}
Expand Down
4 changes: 4 additions & 0 deletions adapters/humamux/humamux.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func (c *gmuxContext) Operation() *huma.Operation {
return c.op
}

func (c *gmuxContext) WrappedContext() interface{} {
return c.r
}

func (c *gmuxContext) Context() context.Context {
return c.r.Context()
}
Expand Down
6 changes: 6 additions & 0 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ type Context interface {
// Operation returns the OpenAPI operation that matched the request.
Operation() *Operation

// WrappedContext returns the underlying Adapter original
// Request context. For example, `*http.Request` for the `http` adapter.
// This is useful for accessing router-specific information and
// transitioning existing handler functionality.
WrappedContext() interface{}

// Context returns the underlying request context.
Context() context.Context

Expand Down