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

Validation of endpoints against a given OpenAPI schema #3645

Open
adamw opened this issue Mar 28, 2024 · 23 comments
Open

Validation of endpoints against a given OpenAPI schema #3645

adamw opened this issue Mar 28, 2024 · 23 comments

Comments

@adamw
Copy link
Member

adamw commented Mar 28, 2024

Sometimes it might be desirable to verify if the endpoints match a given OpenAPI schema. To implement this, we would need to parse the schema (see softwaremill/sttp-apispec#2 - although this is already partially done), and then invoke comparison of the two schemas (generated from endpoints & parsed), ignoring fields which do not matter (e.g. descriptions, or examples)

@ghik ghik self-assigned this Apr 8, 2024
@ghik
Copy link
Contributor

ghik commented Apr 8, 2024

What's the "user story" here? Is it something like:

  1. User has a given OpenAPI to implement
  2. Decides to do it manually instead of using codegen
  3. Writes an API in tapir but wants to validate it against the given OpenAPI

?

@adamw
Copy link
Member Author

adamw commented Apr 8, 2024

This, or: develops an API, publishes it, and wants to ensure that anything that's changed doesn't break the published contract

@ghik
Copy link
Contributor

ghik commented Apr 25, 2024

softwaremill/sttp-apispec#157 introduced SchemaComparator to check compatibility between schemas. This is likely the most complex part of full OpenAPI validation. Schema comparator would be used:

  • to check compatibility of inputs (parameters, request bodies) - schemas from previous API version (i.e. client's) would be used as "writer" schemas, while schemas from current API version (i.e. server's) would be used as "reader" schemas
  • to check compatibility of outputs (responses) - schemas from current API version (i.e. server's) would be used as "writer" schemas, while schemas from previous API version (i.e. client's) would be used as "reader" schemas

Possible improvements to SchemaComparator:

  • Make it understand more Schema patterns and JSON Schema keywords (see SchemaComparator sttp-apispec#157 for more details on comparator's assumptions and limitations)
  • Make it customizable with pluggable validation logic
    The comparator may be too conservative in some cases. For example, it might not understand that some format values are compatible, or that some particular schema patterns are compatible in specific use cases. It may be worth to open SchemaComparator's implementation to extensions which would allow the user to override parts of its logic, in order to fine-tune it to their needs and avoid false negatives.
  • Possibly rethink the structure of compatibility issues being reported (e.g. by making it completely flat or completely tree-like, deduplicating issues for heavily reused named schemas etc.). Optimal structure largely depends on how exactly we want these results to be presented to the user.

Further work needed to have a full OpenApi comparator:

  • Make sure OpenAPI can be deserialized (it looks to me like all the decoders are already there, but I haven't tested them)
  • Implement an OpenAPIComparator similar to SchemaComparator.
    This requires comparing the following OpenAPI objects: MediaType, Encoding, RequestBody, Responses, Response, Header, Parameter, Operation, PathItem, and ultimately OpenAPI itself.

@ghik
Copy link
Contributor

ghik commented Apr 25, 2024

Proposed structure for compatibility issues reported by full OpenAPI comparator

  • missing path - server API does not define a path item that client API expects
  • incompatible path - there are incompatibilities in operations for given path item
    • missing operation for given HTTP method
    • incompatible operation for given HTTP method
      • a required server operation parameter is missing or optional in client operation
      • client parameter is incompatible with corresponding server parameter
        • client parameter schema is incompatible with server parameter schema
        • client content is incompatible with server content (see below for details)
        • style or explode don't match between client and server
        • allowEmptyValue is true for client but false for server
        • allowReserved is true for client but false for server
      • request body is required in server operation but is missing or optional in client operation
      • client request body is incompatible with server request body
        • client content is incompatible with server content (see below for details)
      • server responses are incompatible with client responses
        • response for some status code or range is defined by the server but not by the client (note: response for a particular code may be defined using a range or default)
        • response for some status code or range defined by the server is not compatible with corresponding definition on the client
          • server response content is incompatible with client response content (see below for details)
          • a response header is required by the client but is missing or optional on the server
          • server response header is incompatible with client response header
            • server header schema is incompatible with client header schema
            • server header content is incompatible with client header content (see below for details)
            • style or explode don't match between server and client
            • allowEmptyValue is true for server but false for client
            • allowReserved is true for server but false for client
      • TODO: callbacks, security?

Compatibility issues for content comparison:

  • media type is defined in writer's content but not defined in reader's content
  • writer media type is incompatible with reader media type
    • writer schema does not match reader schema
    • TODO: encoding?

Note: "writer" and "reader" correspond to:

  • client and server, when comparing input (request) definitions
  • server and client, when comparing output (response) definitions

@ghik ghik removed their assignment Jun 15, 2024
@adamw
Copy link
Member Author

adamw commented Oct 16, 2024

Current state: we've got the SchemaComparator as describe above.

What's left to do:

  • ensure that the openapi-circe module in sttp-apispec includes all necessary Decoders, which allow parsing an openapi schema file (write tests + fix if necessary)
  • introduce an OpenAPIComparator in the sttp-apispec project, as part of the openapi-model module. This should compare OpenAPI instances, as defined above. Non-essential differences (e.g. in examples, doc strings etc.) should be ignored.
  • in Tapir's openapi-docs module, add an OpenAPIVerifier, which would verify that a given set of endpoints matches the given openapi spec (given as a yaml string). This should have three modes: exact (every endpoint corresponds to exactly one openapi endpoint, and vice versa), at-least (there might be additional endpoints), at-most (there might be more openapi endpoints, than Tapir endpoints)

@adamw
Copy link
Member Author

adamw commented Oct 16, 2024

/bounty $750

Copy link

algora-pbc bot commented Oct 16, 2024

💎 $750 bounty • SoftwareMill

Steps to solve:

  1. Start working: Comment /attempt #3645 with your implementation plan
  2. Submit work: Create a pull request including /claim #3645 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to softwaremill/tapir!

Add a bountyShare on socials

Attempt Started (GMT+0) Solution
🟢 @Saturn225 Oct 16, 2024, 1:17:41 PM WIP
🔴 @vishwamartur Nov 16, 2024, 4:02:24 PM WIP
🟡 @promisingcoder Dec 12, 2024, 2:44:26 AM WIP
🟢 @abdelfetah18 Dec 19, 2024, 7:34:57 PM #4215

@Saturn225
Copy link

Saturn225 commented Oct 16, 2024

/attempt #3645

Algora profile Completed bounties Tech Active attempts Options
@Saturn225 1 bounty from 1 project
Cancel attempt

@adamw
Copy link
Member Author

adamw commented Oct 21, 2024

As we are getting first PRs for the bounties, I've published our "How to prepare a good PR" guide. I should have probably done this right away, sorry! :)

@kernel-loophole
Copy link

@adamw is this issue is still open .would love to work on it .

@Saturn225
Copy link

@adamw @kernel-loophole I have worked on it and need a few quick fixes and will draft PR soon

@vishwamartur
Copy link

vishwamartur commented Nov 16, 2024

/attempt #3645

Copy link

algora-pbc bot commented Nov 16, 2024

Note

The user @Saturn225 is already attempting to complete issue #3645 and claim the bounty. We recommend checking in on @Saturn225's progress, and potentially collaborating, before starting a new solution.

vishwamartur added a commit to vishwamartur/tapir that referenced this issue Nov 16, 2024
Related to softwaremill#3645

Implement `OpenAPIVerifier` in the `openapi-docs` module to verify endpoints against a given OpenAPI spec.

* Add `OpenAPIVerifier` class in `docs/openapi-docs/src/main/scala/sttp/tapir/docs/openapi/OpenAPIVerifier.scala`
  - Implement three modes: exact, at-least, and at-most
  - Use `OpenAPIComparator` to compare `OpenAPI` instances
* Add tests for `OpenAPIVerifier` in `docs/openapi-docs/src/test/scalajvm/sttp/tapir/docs/openapi/OpenAPIVerifierTest.scala`
  - Test all three modes: exact, at-least, and at-most
  - Use sample endpoints and OpenAPI specs for testing
Copy link

algora-pbc bot commented Nov 23, 2024

@vishwamartur: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then 🙏

@abdelfetah18
Copy link
Contributor

abdelfetah18 commented Nov 28, 2024

Hi @adamw, I've started working on the OpenAPIComparator. Could you take a look at this PR and let me know if I'm heading in the right direction?

softwaremill/sttp-apispec#194

@ThijsBroersen
Copy link
Contributor

ThijsBroersen commented Nov 29, 2024

What about reusing openapi-diff . I have used this tool standalone in CI to check for compatibility with previous openapi specs of projects. But it could easily be included in tests as it is a java module. Could probably save a lot of work and maintenance for this project.
It also has some nice reporting features, very useful for CI release pipelines and notes.

@adamw
Copy link
Member Author

adamw commented Nov 29, 2024

@abdelfetah18 yes this looks like the good direction. Would be good to have tests which read .yaml/.json files as well, though.

@ThijsBroersen ah didn't know about that :) We could definitely use it as well - as long as we can provide an appropriate interface on top (comparing endpoints to a specification, ignoring unimportant details (descriptions, examples), and providing exact/at-least/at-most modes

@promisingcoder
Copy link

promisingcoder commented Dec 12, 2024

/attempt #3645

Copy link

algora-pbc bot commented Dec 12, 2024

Note

The user @Saturn225 is already attempting to complete issue #3645 and claim the bounty. We recommend checking in on @Saturn225's progress, and potentially collaborating, before starting a new solution.

Copy link

algora-pbc bot commented Dec 19, 2024

@promisingcoder: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then 🙏

@abdelfetah18
Copy link
Contributor

abdelfetah18 commented Dec 19, 2024

/attempt #3645

Algora profile Completed bounties Tech Active attempts Options
@abdelfetah18 1 softwaremill bounty
Java, C++
Cancel attempt

Copy link

algora-pbc bot commented Dec 19, 2024

💡 @abdelfetah18 submitted a pull request that claims the bounty. You can visit your bounty board to reward.

Copy link

algora-pbc bot commented Dec 23, 2024

🎉🎈 @abdelfetah18 has been awarded $750! 🎈🎊

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

8 participants