pactflow / swagger-mock-validator

Other
13 stars 4 forks source link

Support OAS `servers` in URL matching #28

Closed mefellows closed 1 year ago

mefellows commented 1 year ago

Given a consumer contract that has a request to path /mybaseurl/resource And a provider Open API Spec yaml with a server parameter like:

servers:
  - url: /mybaseurl
and then defines the resource as:
  /resource
    post:
      ...

swagger-mock-validator should by able to correctly discover the matching path and perform the validation.

At the moment, this will not match the pact test as it disregards the servers parameter, and the URLs will not match.

Requirements

  1. Relative URLs must also be considered
  2. Variable substitutions must also be considered
  3. Handle scenario where multiple servers are provided:
    1. If there are unambiguous base paths with different hosts, the solution is to prepend the common base path and use this in the checks
      1. e.g. if http://test.foo.com/v1/ and http://prod.foo.com/v1/ are provided, then /v1 is the common base path to check
    2. If there are multiple ambiguous paths, we could:
      1. Throw an error explaining the ambiguity needs resolution (This error should degrade to a warning if 4.a.iii is chosen as the migration strategy)
      2. Match all of them and and pick any successful one (I think this is not ideal)
  4. Handling existing users
    1. Existing users will already have taken into account the fact that we previously did not support base paths - thus, we need to either
      1. provide a migration path (such as the strategy employed in ),
      2. introduce a breaking change, or
      3. We could consider testing both with and without the base URL and if one passes we consider it a “match”, and emit a warning (displayed by ) if the only match isn’t one of the servers
github-actions[bot] commented 1 year ago

👋 Hi! The 'smartbear-supported' label has just been added to this issue, which will create an internal tracking ticket in PactFlow's Jira (PACT-1043). We will use this to prioritise and assign a team member to this task. All activity will be public on this ticket. For now, sit tight and we'll update this ticket once we have more information on the next steps.

See our documentation for more information.

mefellows commented 1 year ago

Diving deeper into the use cases of servers and thinking about how we might go about using them.

Let’s assume a consumer contract has a request to path /mybaseurl/resource while the OAS has the following:

servers:
  - url: https://foo.com/mybaseurl

and then defines the resource as:

  /resource
    post:
      ...

This is easy enough for us to support - the resource identified in the OAS to compare against the pact file is /resource, as we can join the path in servers and get a “resolved” URL of /mybaseurl/resource.

However, very quickly you can build conflicting or ambiguous scenarios. e.g.

servers:
  - url: https://foo.com/mybaseurl
  - url: https://bar.com/adifferenturl

Now there are two different top level base paths! These effectively rewrite the actual URLs that would be present in different servers.

You could also do this sort of thing:

paths:
  '/fruits/apple'
    servers:
      - url: https://hostname/
  '/apple'
    servers:
      - url: https://hostname/fruits

These two would result in same “resolved” path.

Servers can also be built dynamically:

servers:
  - description: SwaggerHub API Auto Mocking
    url: https://k8-swaggerhub.mwhiggins.com/virts/SmartBear_Org/Book/1.3.0
  - description: Static server
    url: https://books.mhiggins.com/v1.3
  - description: Live Bookstore dynamic servers
    url: https://{host}:{port}/{basePath}
    variables:
      host:
        enum:
          - test.book.com
          - staging.book.com
          - sandbox.book.com
          - production.book.com
        default: test.book.com
      port:
        enum:
          - '443'
          - '8443'
        default: '443'
      basePath:
        enum:
          - v1.0
          - v1.1
          - v1.2
          - v1.3
        default: v1.3

This condenses the possible servers and creates a more expressive language, and supports visual editors like SwaggerHub to provide helpful "try it out" capabilities. It also shows the point of how flexible servers can be:

Screenshot 2023-06-23 at 9 24 32 am

But also, now there are multiple divergent base paths to consider and the resolution rules are more likely to cause confusion and complexity.

So given the above, it's not clear we'll be able to provide a reliable mechanism here.

Workaround

If your OAS has the basic use case of a single server entry with a consistent base URL, you can either

  1. Transform your OAS to transpose the base URL into each of the resources
  2. Transform your pact file before publishing to strip the base URL

this way, you will have alignment.