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

Reconsider multiple basePath values #562

Closed
fehguy opened this issue Feb 10, 2016 · 16 comments
Closed

Reconsider multiple basePath values #562

fehguy opened this issue Feb 10, 2016 · 16 comments

Comments

@fehguy
Copy link
Contributor

fehguy commented Feb 10, 2016

This was one of those features that shipped with swagger 1.0, 1.1, and 1.2 but was removed in 2.0.

The current spec does not allow multiple hosts to be defined for execution. You can host the spec in different pieces and across multiple hosts, but the execution shall be for a single host. That host is configurable in the spec, but it applies to all operations.

There has been pushback on this from a number of people so I'd like to put it back out in the open. We can reintroduce a construct for multiple hosts. Having gone through the pains of both implementing and supporting it in tools, I would strongly suggest we do not.

My reasoning:

  • Often different hosts have different authorization mechanisms. If we re-introduce this feature, we'll need to support scoping authorizations to a particular host.
  • Spanning different protocols (calling a http operation from a https-hosted page, for example) introduces show-stopping compatibility issues for web-based tools. Multiple hosts in a single spec will exacerbate this issue
  • The original support was intended for microservices, which is now better served by apis.json.

So this ticket gives some background and a recommendation for the next version. If there is strong objection, now is the time.

@fehguy
Copy link
Contributor Author

fehguy commented Feb 10, 2016

parent issue #560

@IvanGoncharov
Copy link
Contributor

I think we should consider real life scenarios for this issue.
Most common is separate base paths for file uploads, for example in Google APIs
https://www.googleapis.com/drive/v3
https://www.googleapis.com/upload/drive/v3

https://www.googleapis.com/youtube/v3
https://www.googleapis.com/upload/youtube/v3

Or different subdomain:
https://uploady.com/v1/api/
https://content.uploady.com/v1/api/

https://api.dropboxapi.com/2
https://content.dropboxapi.com/2

I think RAML have pretty good solution for this problem:
https://github.com/raml-org/raml-spec/blob/master/raml-0.8.md#base-uri-parameters

And I think template parameters in host and basePath also needed for other things like separate subdomain for sandbox, allow to choose server location, etc.

@fehguy
Copy link
Contributor Author

fehguy commented Feb 10, 2016

Thanks @IvanGoncharov. Aside from ease of modeling, what do you think of three concerns I listed above? I don't think the hard part is how to model it, which RAML does, it's more about how you use it.

@IvanGoncharov
Copy link
Contributor

My main point here is that separate baseUrl for file upload/download is common pattern and it has performance reasoning behind it. So it will not disappears in nearest future and should be dealt with as first-class citizen in OpenAPI world. Also it don't require any special mechanism to handle just template parameters for host and basePath which already requested for other reasons #169

Often different hosts have different authorization mechanisms. If we re-introduce this feature, we'll need to support scoping authorizations to a particular host.

I'm also not like idea of putting two different APIs in one spec.
If they differ in something other than host or basePath it should be separate spec.
I think it's make a good borderline principle, but allow to handle most of real life scenarios.

The original support was intended for microservices, which is now better served by apis.json.

I'm totally against putting separate APIs into one Swagger file it's creating a total mess.
And I think if you ask people why they asked for such feature you will hear that it's file upload/download in most of the cases.

Moreover in my project I work with hundreds of different real-world APIs and I only had problems similar to the ones that I presented in my previous comment.

Spanning different protocols (calling a http operation from a https-hosted page, for example) introduces show-stopping compatibility issues for web-based tools. Multiple hosts in a single spec will exacerbate this issue

Can you provide more concrete example, because right now I don't see any problem?
I'm not a frontend developer so I can miss something obvious, but still it's better to explicitly describe possible problems.

@webron
Copy link
Member

webron commented Feb 12, 2016

@IvanGoncharov API design choices aside, it's difficult to discount the number of times we've been asked for a solution for multiple basePath support since we published 2.0. We had plans on introducing a solution to it (still have it somewhere) as an external extension, but we abandoned it partly due to lack of resources and partly because there's an alternative solution such as apis.json.

@IvanGoncharov
Copy link
Contributor

@webron I think we should distinguish two scenarios:

  • API owner want single point to describe multiply API which belong to his.
  • You have one logical API but due to performance concerns you move some of endpoint to separate hosts or basePaths. Upload/download is most widespread example.

I agree that first should be solved by totally separate format.
But in second case you make API owner to create separate file with one method and moreover to duplicate all other info like definitions, parameters, info, tags, securityDefinitions, etc.

@fehguy
Copy link
Contributor Author

fehguy commented Mar 14, 2016

Here is my proposal for this:

Add support for multiple hosts by adding optional attributes at the path and operation level. When not present, the top-level settings will apply:

host: <host>
basePath: <basePath>
schemes:
  - <scheme>

Path-level example:

paths:
  /pet/upload:
    host: https:/pets.com
    basePath: /uploadMe
    get:
      operationId: theUsualStuff

Operation-level example:

paths:
  /pet/upload:
    host: https:/pets.com
    basePath: /uploadMe
    get:
      host: https://pets.com
      basePath: /uploadMe
      operationId: theUsualStuff

@whitlockjc
Copy link
Member

I think from an API description authoring perspective, this just muddies the waters. Not only can I do the same by putting the basePath into the path key, /uploadMe/pet/upload but now I can do the same thing with a combination of path key and operation/path-level basePath? Not only that but from a tooling perspective, how does this get handled? To me, it seems like this singular path definition could potentially have three runtime checks:

  • Is this a match for /pet/upload
  • Is this a match for /uploadMe/pet/upload
  • Is this a match for /uploadMe/pet/upload when the requested host is pets.com

There could be more permutations but I have no idea what multiple base paths or per path/operation level base paths should be handled. What was once a singular view of your API is no longer the case. I have to do some computation just to figure out what this API looks like and that violates the human readability of the OpenAPI documents.

@whitlockjc
Copy link
Member

To me, when I have an API it is host/path agnostic. I write an API and whether I deploy it to QA, test, prod, ... my API looks and works the same. Now I realize based on the deployed environment that things like the hostname will obviously be different and that the base path could potentially be different but my API is still the same. The same operations will return the same objects and have the same contract.

All of this being said, I often wonder why these details are even in the OpenAPI documents at all.

@whitlockjc
Copy link
Member

This might not be the proper place for that last comment.

@fehguy
Copy link
Contributor Author

fehguy commented Mar 14, 2016

@whitlockjc there are no path permutations to worry about. This is only for the execution of an operation, and it would follow the same inheritance as, say, consumes.

  1. If schemes are defined in the operation, use it, otherwise, use the parent schemes
  2. If host is defined in the operations, use it, otherwise use the parent host
  3. If basePath is defined in the operation, use it, otherwise use the parent basePath

I don't think this is a modeling concern, more an operations concern. It allows a user to send a request to an alternate location which as @IvanGoncharov mentioned, can make sense.

@whitlockjc
Copy link
Member

I got you. That makes more sense now. Thanks for clarifying.

To me, this seems like a feature where you want to have a single OpenAPI document to sit in front of N different real APIs. Is this a use case we want to support? For the APIs that share a common host name, to me that is a single API and you can easily support this with path patterns. (The Google APIs examples from @IvanGoncharov.) For the APIs that do not share a common host, is it really even fair to treat them as the same API? (The uploadly and dropbox examples from @IvanGoncharov.)

@fehguy
Copy link
Contributor Author

fehguy commented Mar 18, 2016

@whitlockjc I get it--one could take this very far in the direction of having many hosts in one specification, we can't keep people from abusing the idea. But I do think it's worth supporting this construct. Tooling will be easy to handle it.

@november1306
Copy link

creating separate spec document with code duplication if you have more than one subdomain is so stupid

@fehguy
Copy link
Contributor Author

fehguy commented Jul 25, 2018

Try to keep it cool, @november1306

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants