Skip to content

Instantly share code, notes, and snippets.

@bluebrown
Created November 18, 2022 17:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bluebrown/ec35f25ab9b394a5ade206892c69609e to your computer and use it in GitHub Desktop.
Save bluebrown/ec35f25ab9b394a5ade206892c69609e to your computer and use it in GitHub Desktop.
Validate http requests based on openapi spec
type ValidationInterceptor struct {
router http.Handler
val routers.Router
}
func (s *ValidationInterceptor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
route, pathParams, err := s.val.FindRoute(r)
if err != nil {
log.Printf("no route: %v", err)
w.WriteHeader(http.StatusNotFound)
return
}
requestValidationInput := &openapi3filter.RequestValidationInput{
Request: r,
PathParams: pathParams,
Route: route,
}
err = openapi3filter.ValidateRequest(r.Context(), requestValidationInput)
if err != nil {
log.Printf("invalid request: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
var (
statusCode = 200
body = new(bytes.Buffer)
)
wrapped := httpsnoop.Wrap(w, httpsnoop.Hooks{
WriteHeader: func(whf httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
return func(code int) {
statusCode = code
}
},
Write: func(wf httpsnoop.WriteFunc) httpsnoop.WriteFunc {
return func(b []byte) (int, error) {
return body.Write(b)
}
},
})
s.router.ServeHTTP(wrapped, r)
responseValidationInput := &openapi3filter.ResponseValidationInput{
RequestValidationInput: requestValidationInput,
Status: statusCode,
Header: w.Header(),
}
responseValidationInput.SetBodyBytes(body.Bytes())
err = openapi3filter.ValidateResponse(r.Context(), responseValidationInput)
if err != nil {
log.Printf("invalid response: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(statusCode)
io.Copy(w, body)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment