Skip to content

Response validation doesn't support media types with wildcards #316

Description

@adrienyhuel

I found out that response validation can't handle wildcard content types.

The OpenAPI spec can define response conte type with wildcards, like "application/", "/*"....

Sample extracted from open website https://swagger.io/docs/specification/v3_0/media-types/ :

paths:
  /info/logo:
    get:
      responses:
        "200": # Response
          description: OK
          content: # Response body
            image/*: # Media type
              schema:
                type: string
                format: binary

In my case, the OpenAPI Spec had a ContentType "/"
If the backend send a response with the Content-Type header "application/json", the validation fail with an error :

POST / 200 operation response content type 'application/json' does not exist","reason":"The content type 'application/json' of the POST response received has not been defined, it's an unknown type

If the backend respond with Content-Type "/", there is no error, but the body is not validated as there is no parser for that content type.

I think there is two places where the response Content-Type is compared to the OpenAPI Spec :

if mediaType, ok := foundResponse.Content.Get(mediaTypeSting); ok {

} else if mediaType, ok := operation.Responses.Default.Content.Get(mediaTypeSting); ok {

The code Content.Get(mediaTypeSting) check if there is a schema with the exact content type in the operation spec.

Maybe the lib should loop over Content keys and compare with Content-Type from response, taking into account the wildcards.

func getMatchingMediaType(foundResponseContent, contentType string) (foundResponseContentMedia, bool){
  for media := foundResponseContent.First(); media != nil; media = media.Next() {
    mediatype, mediasubtype, _ := strings.Cut(media, "/")
    contenttype, contentsubtype, _ := strings.Cut(mediaTypeSting, "/")
    t := contenttype == mediatype || (contenttype == "*") || (mediatype == "*")
    st := mediasubtype == contentsubtype || mediasubtype == "*" || contentsubtype == "*"
    if t && st {
      return media, true
    }
  }
  return nil, false
}

if mediaType, ok := getMatchingMediaType(foundResponse.Content, mediaTypeSting); ok {
  ...

PS : the code is just a draft, not optimized, missing typing...

Edit : here is how kin-openapi handle it :
https://github.com/getkin/kin-openapi/blob/f5d61a7ecfdcfd776eeb7d121cbd4d8bb12c404f/openapi3/content.go#L64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions