oapi-codegen
oapi-codegen copied to clipboard
Echo context with StrictServerInterface
Is there an example or configuration showing how to use echo.Context with the StrictServerInterface generated by oapi-codegen?
I had a very similar problem and the only way I managed to solve it involved replacing the context object which definetely seems hacky (but hey, it works!)
so, first and foremost, excerpt of setting up middleware:
e := echo.New()
_server := server.New(app) // just initializing some business logic, nothing of importance here
specs.RegisterHandlersWithBaseURL(
e,
specs.NewStrictHandler(
_server,
[]specs.StrictMiddlewareFunc{
authenticationMiddleware(app),
},
),
"/api",
)
now let's take a look at the middleware:
// I did warn you that it was hacky, didn't I ?
func setSession(ctx echo.Context, session *auth.Session) {
currentRequest := ctx.Request()
currentContext := currentRequest.Context()
// yes, the compiler did warn me to not use string type. this is just for demo purposes, relax.
newContext := context.WithValue(currentContext, "session", session)
newRequest := currentRequest.WithContext(newContext)
ctx.SetRequest(newRequest)
}
// again, myApp is how I communicated with external stuff, like database and so on. nothing really specific to the question asked.
func authenticationMiddleware(app myApp) specs.StrictMiddlewareFunc {
return func(f specs.StrictHandlerFunc, operationId string) specs.StrictHandlerFunc {
// here you can check if operationId is on the list of known public operations, oapi-codegen does include
// another example which IIRC parses the spec and extracts this information from the spec itself
// https://github.com/oapi-codegen/oapi-codegen/tree/main/examples/authenticated-api/echo
// on the other hand, this involves a separate library and does not use strict server
return func(ctx echo.Context, request any) (response interface{}, err error) {
header := ctx.Request().Header.Get("Authorization")
// just for demo purposes:
if (header == "super-secure-token") {
setSession(ctx, &SessionObject{UserId: "logged-in-user"})
return f(ctx, request)
}
return nil, echo.NewHTTPError(http.StatusUnauthorized, "better luck next time")
}
}
}
finally, in your handler function you can retrieve the session object from the context:
func (s *server) MyHandler(ctx context.Context, ...) {
// again, don't use string for a key, demo purposes, etc.
fmt.Printf("session: %+v", ctx.Value("session"))
}