apigee-127 / swagger-tools

A Node.js and browser module that provides tooling around Swagger.
MIT License
702 stars 373 forks source link

Unable to host multiple APIs on a single express server #530

Closed mlasevich closed 7 years ago

mlasevich commented 7 years ago

Is there a way to properly host multiple instances of swagger-tools based APIs on a single web server?

I am attempting to do so by creating a separate express app for each API mountpoint, configured the usual way (using app.use(middleware.*) without a specified mountpoint ), and mounting them on a parent express app using a mountpoint. This is my preferred approach and it almost works, but has an issue where the basePath is, one way or another, invalid. If I set basePath to a properly full /mountpoint, then the API endpoints listens under /mountpoint/mountpoint instead of expected /mountpoint - now, the API URI is not what is expected and - Swagger UI is broken because it is trying to send APIs to wrong URIs. If I set the basePath in swagger to / - API endpoints are mounted in correct location and seem to work, however the swagger file is wrong (basePath is wrong) and SwaggerUI is still broken as it is trying to go to / on the server instead of /mountpoint

Proposed fix, add a parameter to swagger-tools (to metadata middleware?) that modifies basePath by removing a prefix for metadata processing (or adding a suffix for all other uses, including modifying swagger document being served)

For what its worth, I also tried using a single express app and mounting each API's middleware set under a mountpoint, but that does not seem to work either.

whitlockjc commented 7 years ago

Can you give a code example of what you're doing? Just the server initialization and such related to swagger-tools will suffice.

mlasevich commented 7 years ago

Attached is the stripped down example with two apis - /api/one and /api/two - first is configured with basePath: /api/one and second with basePath: /

Included also are two examples, one with subapps and the other with mounts

multi-swagger-tool-example.zip

whitlockjc commented 7 years ago

Well, the basePath: /api/one will overlap basePath: / so I'm not sure how you expect this to work. But I can look into your sample.

mlasevich commented 7 years ago

basePath is a setting in swagger, not in express. In express they are mounted in correct location. To be clear, basePath: / is not correct item, but it is the one thing that sort-of does the intended thing - having the actual API endpoint be /api/two/ping instead of /api/two/api/two/ping

whitlockjc commented 7 years ago

One more thing, can you tell me what isn't working? It would be easiest if you ran your app with debugging, make a request you expect to work and give me the output (obfuscated however you deem fit).

whitlockjc commented 7 years ago

To be honest with you, there is no secret sauce for this stuff. The basePath in your Swagger document is the thing that dictates whether swagger-metadata matches a request or not. I've just opened your code and will update accordingly.

mlasevich commented 7 years ago

basically it is this:

My expectation/needs/wants are these:

  1. basePath is set correctly (/api/one, for example) so that it can be used by other tools
  2. the api listed in document as /ping, for example, can be reached via URI /api/one/ping
  3. When UI is enabled, I can execute test calls with correct URI

Currently in case of /api/one, number 1 is correct, but I have a problem with number 2 and 3 where the api can only be reached via URI /api/one/api/one/ping (2) but UI calls it with desired, but incorrect URI of /api/one/ping (3) (you can actually argue that only 2 is a problem here)

In case of /api/two, number 2 is correct, but number 1 is incorrect (wrong basePath) and UI tries to call it with incorrect URI of /ping (3)

Does this help?

whitlockjc commented 7 years ago

Can you join me here so we can talk in real-time: https://gitter.im/apigee-127/swagger-tools

mlasevich commented 7 years ago

Based on explanation, I understood that if I simply configure each api with a proper basePath and add them to express without a mountpoint, it will just work fine because if a URI is not matched, it just falls through to next one.

Thank you.