[go: up one dir, main page]

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

[OpenAPI Schema Validator] Nullable support with allOf, anyOf & oneOf #1318

Closed
aeoncl opened this issue Sep 12, 2024 · 2 comments
Closed

[OpenAPI Schema Validator] Nullable support with allOf, anyOf & oneOf #1318

aeoncl opened this issue Sep 12, 2024 · 2 comments

Comments

@aeoncl
Copy link
Contributor
aeoncl commented Sep 12, 2024

Describe the bug

Hello there, i come once again with an OpenAPI edge case 🥳🥳🥳🥳

In order to make a schema that we want to $ref nullable, in OpenAPI < 3.1, we are forced to use this syntax:

foo:
  nullable: true
  allOf:
  - $ref: '#/components/schemas/Foo'

source

If i run a contract test on an endpoint that uses this mechanism and the real API returns null, the OpenAPI Validator will fail. because it doesn't handle this case.

Expected behavior

nullable is set to true, so null is a valid value.

Actual behavior

nullable is not considered in the handling of composition structures by the OpenAPISchemaValidator

How to Reproduce?

You can import the following contract and use microcks to run contract test on himself (using microcks mock url as targetUrl)

openapi: 3.0.1
info:
  title: Season API
  description: useless API
  version: v1
servers:
- url: /
tags:
- name: season-controller
paths:
  /seasonAllOf:
    post:
      tags:
      - season-controller
      operationId: createSeason
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatableSeason'
            examples:
              bumpinThat:
                description: a Season
                value:
                  seasonType: "BratSummer"
        required: true
      responses:
        "201":
          description: season data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SeasonAllOf'
              examples:
                bumpinThat:
                  value: '{"seasonData":null}'
  /seasonOneOf:
    post:
      tags:
        - season-controller
      operationId: createSeason
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatableSeason'
            examples:
              bumpinThat:
                description: a Season
                value:
                  seasonType: "BratSummer"
        required: true
      responses:
        "201":
          description: season data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SeasonOneOf'
              examples:
                bumpinThat:
                  value: '{"seasonData":null}'
  /seasonAnyOf:
    post:
      tags:
        - season-controller
      operationId: createSeason
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatableSeason'
            examples:
              bumpinThat:
                description: a Season
                value:
                  seasonType: "BratSummer"
        required: true
      responses:
        "201":
          description: season data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SeasonAnyOf'
              examples:
                bumpinThat:
                  value: '{"seasonData":null}'
components:
  schemas:
    SeasonType:
      type: string
      enum:
        - BratSummer
        - SpookySeason
        - RustySpring
        - ColdHeartWinter

    CreatableSeason:
      title: CreatableSeason
      type: object
      properties:
        seasonType:
          $ref: '#/components/schemas/SeasonType'

    SeasonData:
      nullable: true
      title: SeasonData
      required:
      - isTooHot
      - isTooCold
      type: object
      properties:
        seasonType:
          $ref: '#/components/schemas/SeasonType'
        isTooHot:
          type: boolean
        isTooCold:
          type: boolean

    SeasoningData:
      nullable: true
      title: SeasoningData
      required:
        - isSalty
        - isUmami
      type: object
      properties:
        isSalty:
          type: boolean
        isUmami:
          type: boolean

    SeasonAllOf:
      type: object
      properties:
        seasonData:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/SeasonData'

    SeasonOneOf:
      type: object
      properties:
        seasonData:
          nullable: true
          oneOf:
            - $ref: '#/components/schemas/SeasonData'
            - $ref: '#/components/schemas/SeasoningData'

    SeasonAnyOf:
      type: object
      properties:
        seasonData:
          nullable: true
          anyOf:
            - $ref: '#/components/schemas/SeasonData'
            - $ref: '#/components/schemas/SeasoningData'

Microcks version or git rev

1.10.0-fix2

Install method (docker-compose, helm chart, operator, docker-desktop extension,...)

Microcks Uber through docker

Additional information

The proposed fix that i have linked to this PR adds some behavior in the OpenAPISchemaValidator.convertType() method:

The idea is:

  • when we encounter a nullable allOf or anyOf:
    we nest their content into a oneOf and add a null type to a branch of the oneOf.
  • when we encounter a nullable oneOf:
    we just add a null type if it's not already here (because this method is called recursively, this prevents treating the same structure twice)
@lbroudoux
Copy link
Member

Thanks a lot for opening this issue. It's super clear and super documented. I'll have a look at the PR asap.

@lbroudoux lbroudoux added this to the 1.10.1 milestone Sep 13, 2024
aeoncl added a commit to aeoncl/microcks that referenced this issue Sep 13, 2024
Signed-off-by: aeoncl <48886723+aeoncl@users.noreply.github.com>
aeoncl added a commit to aeoncl/microcks that referenced this issue Sep 13, 2024
Signed-off-by: aeoncl <48886723+aeoncl@users.noreply.github.com>
lbroudoux pushed a commit that referenced this issue Sep 13, 2024
* fix: #1318 Support nullable on composition structures

Signed-off-by: aeoncl <48886723+aeoncl@users.noreply.github.com>

* fix: #1318 is now spotless

Signed-off-by: aeoncl <48886723+aeoncl@users.noreply.github.com>

---------

Signed-off-by: aeoncl <48886723+aeoncl@users.noreply.github.com>
@lbroudoux
Copy link
Member

Great job on the PR! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants