Generate types from components/securitySchemes to be used as a key in context.WithValue
Summary
Generate types from components/securitySchemes to be used as a key in context.WithValue.
Background
For example, prepare the following API schema and configuration.
schemas.yaml
paths:
/example:
get:
summary: Example
operationId: example
security:
- BearerAuth: []
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
config.yaml
package: schemas
generate:
chi-server: true
models: true
output: schemas.gen.go
output-options:
skip-prune: true
If you run oapi-codegen, the following code is generated.
const (
BearerAuthScopes = "BearerAuth.Scopes"
)
func (siw *ServerInterfaceWrapper) Example(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, BearerAuthScopes, []string{})
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.Example(w, r)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r.WithContext(ctx))
}
The constant BearerAuthScopes is generated as a key for context.WithValue, but its type is a string and there is a risk of collision between packages.
The provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys.
https://pkg.go.dev/context#WithValue
If you use staticcheck, it will also warn this.
https://staticcheck.dev/docs/checks/#SA1029
This can be avoided by defining a type as shown below.
type bearerAuthContextKey string
const (
BearerAuthScopes bearerAuthContextKey = "BearerAuth.Scopes"
)
In this PR, I have implemented to generate types from components/securitySchemes to be used as keys for context.WithValue, as shown above.
Considerations
While the implementation has been done to avoid breaking the existing code as much as possible, if users are directly using the underlying string (in this case, "BearerAuth.Scopes), they will no longer be able to extract values from the context.
However, this is considered to be a rare case.
type contextKey string
const exampleContextKey contextKey = "example"
func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, exampleContextKey, "hello")
val := ctx.Value(exampleContextKey)
fmt.Println(val) // => hello
val = ctx.Value("example")
fmt.Println(val) // => nil
}
@jamietanna any updates on this? I would really love seeing this merged. Not like I'm the one who makes decision here, yet I think it's good to go.
Will need to double check if https://github.com/oapi-codegen/oapi-codegen/issues/1200 and https://github.com/oapi-codegen/oapi-codegen/issues/836 are related here / can be closed after this