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

feat(openapi): support OpenAPI version 3.1

Open SF97 opened this issue 2 years ago • 15 comments

  • This PR adds support for OpenAPI version 3.1. This has been tried before, as described in https://github.com/cdimascio/express-openapi-validator/issues/573, but these attempts failed. Mainly due to a bug in AJV that makes it incompatible with OpenAPI version 3.1 - https://github.com/ajv-validator/ajv/issues/1745

This PR circumvents AJV issue by replacing all $dynamicAnchor keywords in OpenAPI schema with a direct reference, using $ref. This has been suggested by @Jackman3005 in https://github.com/cdimascio/express-openapi-validator/issues/573#issuecomment-1869810476, which originally came from @seriousme, which already made this workaround in his own OpenAPI schema validation library, https://github.com/seriousme/openapi-schema-validator. From what I understand this shouldn't be an issue. Using $dynamicAnchor would allow this lib to replace OpenAPI specification definitions, which it does not do.

Changes

  • openapi.schema.validator.ts now creates a different AJV instance that supports JSON schema 2020-12 when it detects version 3.1. This AJV instance accepts the format media-range but does not validate its content. This validation can be made in another PR
  • Adds OpenAPI specification 3.1 with $dynamicAnchor references changed to $ref
  • Change test scripts to use Mocha's --extension flag. With the previous setup, the new tests weren't being picked up by the runner

OpenAPI 3.1 support

  • [x] Support webhook property without any defined paths
  • [x] Support an API with only components
  • [x] Fully complete Open API 3.1 schema in type.ts
  • [x] Support "summary" in Info Object
  • [x] Support "identifier" field for SPDX licenses in License Object
  • [x] Ensure "nullable" property does not work anymore. Null type works instead
  • [x] Ensure Request Body validation works in GET HTTP methods
  • [x] Ensure "default" must exist in server variable "enum" values
  • [x] Ensure it is possible to create an Operation Object without responses
  • [x] Support "pathItems" in Components Object

There are some more changes introduced by Open API 3.1, but they're schema changes that are validated by AJV, so tests, although important, aren't as critical as the ones above. They are:

  • Ensure mutual TLS works correctly
  • Ensure extension prefixed with "x-oas-" is not allowed
  • Ensure "exclusiveMaximum" and "exclusiveMinimum" do not accept boolean values
  • Ensure server variable "enum" can not be empty
  • Ensure "jsonSchemaDialect" is supported
  • Ensure "style", "explode" and "allowReserved" for multipart/form-data are allowed as media types

Closes #573 #755

SF97 avatar Jan 01 '24 13:01 SF97

Thank you! can you help build the scaffolding and establish a pattern for 3.1 tests, enabling myself and the community to contribute and expand on them

cdimascio avatar Jan 31 '24 01:01 cdimascio

Thank you! can you help build the scaffolding and establish a pattern for 3.1 tests, enabling myself and the community to contribute and expand on them

Yes, I can do that! I've been really busy lately so I haven't got around to that yet

I think I'll have to time to pick it up this weekend

SF97 avatar Jan 31 '24 23:01 SF97

Hello!

I just pushed the first test for OpenAPI 3.1, where we test for webhook support without any API routes, in which I found some bugs immediately :rofl: but at least I was able to fix it and the tests are passing :partying_face:

I created the folder test/openapi_3.1 for version 3.1 related tests. I've also added the interface DocumentV3_1 for a OpenAPI 3.1 compatible type, and refactored all references to the OpenAPI document to union both 3.0 and 3.1. I found this pretty ugly, maybe we should create an abstraction around it. Anyway, what I wanted was to at least do the first tests so we can all contribute to this PR :)

I also added an (incomplete) list of things to support in OpenAPI 3.1

I'll try to contribute as much as I can in the upcoming days. Anything that I can help with, just let me know

SF97 avatar Feb 05 '24 00:02 SF97

Hello

Just added the list of things we need to ensure that work in OpenAPI 3.1. I based it on OpenAPI's own changelog. I'm currently adding tests to ensure that everything works with the 3.1 spec just fine. Just added some and I'm happy to receive contributions :)

SF97 avatar Feb 29 '24 23:02 SF97

Hello @cdimascio

I've added the most important tests. There are some more things to validate, but they're assured by AJV, thus I don't think they're critical to have this feature.

But I need help in one thing before shipping. I've added a test to ensure that pathItems is supported in components object, but it's failing. The YAML (test/openapi_3.1/resources/components_path_items.yaml) is fine, since it's parsed correctly in https://editor-next.swagger.io/, and it's according to the spec, but AJV is saying it's invalid, and I'm not sure why. It throws this error: image

Can you give a little help here to ensure that we'll support this feature? After this test is passing we can proceed with a full review and add support for OpenAPI 3.1 :partying_face:

Thank you

SF97 avatar Apr 28 '24 19:04 SF97

Can you give a little help here to ensure that we'll support this feature? After this test is passing we can proceed with a full review and add support for OpenAPI 3.1 🥳

Had a look at this. As far as I understand the YAML is invalid, and swagger-editor is being lax about it.

Looking at the 3.1 schema https://github.com/cdimascio/express-openapi-validator/pull/882/files#diff-380b880ffe3121cfdcd466e6bc447b3607d1ddaea014b3167b3b9ee12611fd1e line 286, we see:

    "paths": {
      "$comment": "https://spec.openapis.org/oas/v3.1.0#paths-object",
      "type": "object",
      "patternProperties": {
        "^/": {
          "$ref": "#/$defs/path-item"
        }
      },
      "$ref": "#/$defs/specification-extensions",
      "unevaluatedProperties": false
    },

where in line 268:

        "pathItems": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/$defs/path-item-or-reference"
          }
        }

That is, paths' elements must be "#/$defs/path-item", while pathItems' elements might also be references. The yaml looks like this:

openapi: 3.1.0
info:
  title: Example specification
  version: "1.0"
servers:
  - url: /v1
components:
  pathItems: 
    entity:
      get: 
        [...]
paths:
  /entity:
    $ref: '#/components/pathItems/entity'

We try to use a reference from paths to components/pathItems, where they are only allowed in the other direction.


@SF97, thank you very much for working on this.

medranocalvo avatar May 03 '24 12:05 medranocalvo

@medranocalvo

Thank you very much! I took a look at the schema, and it looks like it was a bug at the schema level, which has been fixed in https://github.com/OAI/OpenAPI-Specification/pull/3355, i.e. the YAML was fine, but the schema wasn't validating it correctly. I've updated the schema to the newest, and it no longer throws a schema error :sunglasses:.

The test is still failing, but I suspect what it is... I'm going to work on it

SF97 avatar May 13 '24 22:05 SF97

And it is fixed :) All tests are passing

That means this PR is complete AFAIK and can be reviewed and merged to fully support Open API 3.1, including reusable path items which I just fixed

@cdimascio could you please review and let me know if there's anything that needs to be changed?

SF97 avatar May 16 '24 22:05 SF97

Reviewed lightly and added a couple of comments. Hope it helps.

medranocalvo avatar May 17 '24 10:05 medranocalvo

Thank you

cdimascio avatar May 23 '24 01:05 cdimascio

Hi @cdimascio @mdmower @SF97 I'm still looking forward to testing this as I think it will help with a number of issues I'm facing around nullable.

Where are things at right now? Is there a list of outstanding tasks we could make or is it ready for a alpha release?

Thanks in advance 🙏

Jackman3005 avatar Jul 05 '24 07:07 Jackman3005

Hi @cdimascio @mdmower @SF97 I'm still looking forward to testing this as I think it will help with a number of issues I'm facing around nullable.

Where are things at right now? Is there a list of outstanding tasks we could make or is it ready for a alpha release?

Thanks in advance 🙏

Hello

From my end, it's ready. I've added all the test cases and fixed the bugs that I've found along the way. If we can't do an alpha release, you can always install it from this branch to test it out locally

SF97 avatar Jul 09 '24 17:07 SF97

@cdimascio @mdmower @SF97 Hi, is there any plan when this feature will be released?

huilingwei avatar Aug 06 '24 06:08 huilingwei

chiming in to express interest, particularly in unevaluatedProperties. Thanks all for the work

patricktyndall avatar Aug 20 '24 03:08 patricktyndall

The content in this PR is now available on branch oas-3.1 and package [email protected]. please try it out.

# experimental OAS 3.1 in alpha (contributions welcome - see branch `oas-3.1` and pr-882)
npm install [email protected]

To contribute submit a PR against oas-3.1

cdimascio avatar Aug 24 '24 15:08 cdimascio