question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[openapi-response-validator] valid body fails incorrectly against allOf schemas with additionalProperties: false

See original GitHub issue

Hi,

Thanks for this great package!

@rolfisub and I found a bug where if you validate a response body against allOf multiple schemas where one of them has additionalProperties: false, then you get a failure (when you should get no failures).

I.e., this test should pass:

module.exports = {
  constructorArgs: {
    responses: {
      '2XX': {
        schema: {
          allOf: [
            {
              type: 'object',
              properties: {
                expectedProperty1: {
                  type: 'string'
                }
              }
            },
            {
              type: 'object',
              properties: {
                expectedProperty2: {
                  type: 'string'
                }
              },
              additionalProperties: false,
            },
          ]
        }
      }
    },

    definitions: null
  },

  inputStatusCode: 200,
  inputResponseBody: {
    expectedProperty1: 'foo',
    expectedProperty2: 'bar',
  },

  expectedValidationError: void 0
};

But instead it fails with this error:

{
  message: 'The response was not valid.',
  errors: [
    {
      path: 'response',
      errorCode: 'additionalProperties.openapi.responseValidation',
      message: 'should NOT have additional properties'
    }
  ]
}

This bug seems to occur only in this specific case. For example, schemas with additionalProperties: true seem to work correctly, as do schemas with allOf just one schema, with additionalProperties: false, e.g.:

allOf: [
            {
              type: 'object',
              properties: {
                expectedProperty1: {
                  type: 'string'
                }
              }
              additionalProperties: false,
            },
            // just one schema, with `additionalProperties: false`
          ]

// this passes and fails when it should

Looking at the code of openapi-response-validator, it seems that you outsource your validation to Ajv, which I guess is this one https://github.com/epoberezkin/ajv/issues?utf8=✓&q=additionalProperties. I see recent mention of unexpected errors for anyOf schemas with additionalProperties: false, but they were resolved 2 months ago, and I’m a bit out of my depth spotting the fix.

Before I raise an issue there, I wondered if you have any ideas/thoughts on this?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
mvegtercommented, Dec 24, 2020

Hey, does anyone know how to restrict additional properties in inherited types (which is usually done with allOf and additionalProperties: false) at the schema level and make response pass through openapi-response-validator? I’m well stuck how to workaround this limitation properly.

Hi @Envek , we ran into the same issue. We solved this by having a source version of our specification from which we generated the actual fully resolved version. You can see it here: https://github.com/AliceO2Group/Bookkeeping/tree/master/spec , it includes the required source code (in JavaScript). Do note that the convert.js file does more than just resolving, it will also sort members.

0reactions
Envekcommented, Feb 26, 2021

Finally I solved it by using json-schema-merge-allof library to preprocess existing schema.

It works like a charm with code like this:

import yaml from "js-yaml"
import { readFileSync } from "fs"
import mergeAllOf from "json-schema-merge-allof"
import $RefParser from "@apidevtools/json-schema-ref-parser"

const apiSpec = <Record<string, any>>yaml.safeLoad(readFileSync("./apiSchema.yaml").toString())

async function preprocessOpenapiSpec(apiSpec: Record<string, any>): Promise<Record<string, any>> {
  const schema = await $RefParser.dereference(apiSpec)

  function mergeAllOfRecursively(candidate: Record<string, any>, parent: Record<string, any>, k: any) {
    if (typeof candidate !== "object") return

    if (candidate.allOf) {
      parent[k] = mergeAllOf(candidate, { ignoreAdditionalProperties: true, deep: true })
    } else {
      for (const [key, value] of Object.entries(candidate)) {
        mergeAllOfRecursively(value, candidate, key)
      }
    }
  }

  for (const [key, value] of Object.entries(schema)) {
    mergeAllOfRecursively(value, apiSpec, key)
  }

  return schema
}

const preprocessedApiSpec = await preprocessOpenapiSpec(apiSpec)

See https://github.com/mokkabonna/json-schema-merge-allof/issues/26 for more details about why it is so verbose 😄

Read more comments on GitHub >

github_iconTop Results From Across the Web

Schema validation incorrectly fails when using ... - GitHub
When using additionalProperties: false in combination with allOf (and I'm guessing others such as oneOf) the documentation generates ...
Read more >
JSON schema : "allof" with "additionalProperties"
This problem is why I have made these two proposals for draft v5: ... be valid against the current schema and all schemas...
Read more >
Test incorrectly passes when mock expects a field that is not in ...
The reason that swagger mock validator accepts this Pact file is because the response body schema allows additional properties.
Read more >
Schema generation rules · GitBook - Goswagger.Io
JSONSchema defaults to "additionalProperties": true , go-swagger defaults to ignoring extra properties. Same for additionalItems . When "additionalProperties": ...
Read more >
It all starts with applicability - JSON Schema Fundamentals ...
As the keyword implies, all of the schemas in the array must result in a true assertion. If any one of the schemas...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found