express-openapi-validator icon indicating copy to clipboard operation
express-openapi-validator copied to clipboard

oneOf with (additionalProperties: false) and (validateResponses: removeAdditional setting) does not work as expected

Open vileanco opened this issue 3 years ago • 5 comments

Describe the bug It looks like removeAdditional: "failing" response validation fails. I feel like the validator first tries to validate against type A and in progress removes property "extra", then it passes this to validate against B and it now also fails since "extra" field is missing. Note that the schema works if I change the order of TypeA and TypeB in the oneOf property.

To Reproduce I've added a test case that fails in my fork of this repo, link to commit:

https://github.com/vileanco/express-openapi-validator/commit/1963bd6d0f3dc101290df945d792bcc6fcc5c72f

Actual behavior Response validation fails with 500 "Internal server error". Errors returned

errors: [
    {
      path: '/response/type',
      message: 'must be equal to one of the allowed values: A',
      errorCode: 'enum.openapi.validation'
    },
    {
      path: '/response/extra',
      message: "must have required property 'extra'",
      errorCode: 'required.openapi.validation'
    },
    {
      path: '/response',
      message: 'must match exactly one schema in oneOf',
      errorCode: 'oneOf.openapi.validation'
    }
  ]

Expected behavior Response validation should pass.

Examples and context

Validator options:

{
        apiSpec,
        validateApiSpec: true,
        validateRequests: true,
        validateResponses: { removeAdditional: 'failing' },
}

Spec:

openapi: "3.0.2"
info:
  version: 1.0.0
  title: requestBodies $ref
  description: requestBodies $ref Test

servers:
  - url: /v1

paths:
  /one_of:
    post:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: "#/components/schemas/TypeA"
                - $ref: "#/components/schemas/TypeB"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/TypeA"
                  - $ref: "#/components/schemas/TypeB"

        "400":
          description: Bad Request

components:
  schemas:
    TypeA:
      type: object
      required:
        - id
        - type
      additionalProperties: false
      properties:
        id:
          type: string
        type:
          type: string
          enum:
            - A

    TypeB:
      type: object
      required:
        - id
        - type
        - extra
      additionalProperties: false
      properties:
        id:
          type: string
        type:
          type: string
          enum:
            - B
        extra:
          type: string

vileanco avatar Jun 10 '22 08:06 vileanco

Looking further into ajv docs https://ajv.js.org/guide/modifying-data.html#removing-additional-properties it looks like this is expected behavior. So I tried this also with the suggestion of adding discriminator property but still seeing same behavior.

vileanco avatar Jun 10 '22 09:06 vileanco

I am running into the same issue here and after some debugging, I find that express-openapi-validator does not pass distriminator: true to ajv and the generated validate function is incorrect. To generate the correct one, discriminator: true has to be set. But there is no way to explicitly config ajv as express-openapi-validator only extracts coerceTypes, removeAdditional.

Tianle-Leviathan avatar Mar 24 '23 02:03 Tianle-Leviathan