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

Support Reverse Proxy #210

Closed
cawoodm opened this issue Aug 7, 2020 · 4 comments
Closed

Support Reverse Proxy #210

cawoodm opened this issue Aug 7, 2020 · 4 comments

Comments

@cawoodm
Copy link

cawoodm commented Aug 7, 2020

We're using swagger-ui-express and swagger-jsdoc to serve a swagger UI for our API so I'm double posting this because I'm not sure where the problem lies.


Many applications run behind a reverse proxy. So while an application runs on localhost:8080 and swagger uses /api/ this may be completely different when someone opens the app externally e,g, https://somedomain.com/foo/bar/api.

In such situations the swagger UI loads but all attempt to run methods fail because they send the request to the app's root / instead of the external root /foo/bar.

There is no way to solve this currently since the app does not and should not know how it will be called externally:

// There is no way to know when the app starts, which external URLs will call it
app.use('/', swaggerUi.serve);
app.get('/', swaggerUi.setup(swaggerJsDoc));

Changing basePath is not an option because, even if it were known when the app starts, this would mean swagger-ui would only work externally on that basePath and not when called via localhost:8080/api/.

Using ./method/ in the jsdoc comments doesn't help either. It generates totally incorrect links:

/** @swagger
 *  './method/{id}':

Generates http://localhost:8080./method/123 => invalid URL.

Using method/ in the jsdoc comments doesn't help either. It generates totally incorrect links:

/** @swagger
 *  'method/{id}':

Generates http://localhost:8080method/123 => invalid URL.

@yinzara
Copy link

yinzara commented Oct 19, 2020

You need to set basePath based on some environment variable you make available in your deployed application.

Locally you would not set basePath (or set it to some default like /api).

Instead of passing your swagger.json/openapi.yml directly to the SwaggerUi initialization, instead just tell swagger UI to load the file by name.

You then make that name available via an express endpoint and serve the modified yaml/json file with the basePath changed based on the environment variable. You may also choose to not use an environment variable and instead use the req.url (or some other request attribute) to calculate what the basePath should be.

Something like:

const jsyaml = require('js-yaml')
const fs = require('fs')

const openapiYaml = jsyaml.load(
  fs
    .readFileSync(`${__dirname}/../dist/openapi.yaml`, 'utf8')
)
app.get("/openapi.yaml", (req, res) => {
  res.contentType("application/x-yaml")
  res.send(jsyaml.dump({...openapiYaml, basePath: process.env.OPENAPI_BASE_PATH || '/api'}))
})
const options = {
  swaggerUrl: "./openapi.yaml"
}
app.use(
  "/",
  swaggerUiExpress.serve,
  swaggerUiExpress.setup(undefined, options)
)

@scottie1984
Copy link
Owner

The only possible option would be to use some custom JS on the client to use the hostname as a way to set up swagger correctly.

https://www.npmjs.com/package/swagger-ui-express#custom-js

Other than that you would have to set the basePath correctly.

@mevljas
Copy link

mevljas commented Aug 26, 2021

None of the answers worked for me. I've solved it using custom middleware.

middlewares/forwardedPrefixSwagger.js

const forwardedPrefixSwagger = async (req, res, next) => {
      req.originalUrl = (req.headers['x-forwarded-prefix'] || '') + req.url;
      next();
};

app.js

app.use('/docs/node/api/swagger/', middlewares.forwardedPrefixSwagger, swaggerUi.serve, swaggerUi.setup(swaggerFile, options));

Note: For this to work the URL must include a trailing slash.

@scottie1984
Copy link
Owner

Closing for now - happy to add to the docs if someone wants to create a PR

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

4 participants