luvcoding
luvcoding

Reputation: 41

swagger-ui-express Multiple Routes for Different API Documentation

I have 2 separate swagger API documentations which I want to run via swagger-ui-express NPM package, and my express server is starting fine on port 5000, but when I am trying to access any of the URL always getting the 404 error, Here is my app.js file and URL's for your reference:

Route 1: http://localhost:5000/edi Route 2: http://localhost:5000/ecom

const express    = require('express');
const router     = require('express').Router();
const swaggerUi  = require('swagger-ui-express');

const ediSwaggerDocument  = require('./edi-openapi.json');
const ecomSwaggerDocument = require('./ecom-openapi.json');

const SWAGGER_APP_PORT = process.env.SWAGGER_APP_PORT || 5000;

const app = express();

// Route Middleware to be called before serving Any Route
router.use('/', swaggerUi.serve); 

// Route - EDI RESTful API Documentaion 
router.get('/edi', swaggerUi.setup(ediSwaggerDocument)); 

// Route - eCommerce RESTful API Documentaion 
router.get('/ecom', swaggerUi.setup(ecomSwaggerDocument));

app.listen(SWAGGER_APP_PORT, () => console.log(`RESTful API Up and Running on Port ${SWAGGER_APP_PORT}`));

Upvotes: 4

Views: 10931

Answers (6)

Adebayo Ilerioluwa
Adebayo Ilerioluwa

Reputation: 339

Had a similar issue, the major fix here was to use the .serveFiles method instead of .serve.

const swaggerUi = require("swagger-ui-express");
const swaggerJSDoc = require("swagger-jsdoc");

const v02SwaggerConfig = require("./config/v0.2/swagger");
const swaggerConfig = require("./config/swagger");

const v02SwaggerDocs = swaggerJSDoc(v02SwaggerConfig);

const swaggerDocs = swaggerJSDoc(swaggerConfig);


app.use("/v0.2.4/api-docs", swaggerUi.serveFiles(swaggerDocs), swaggerUi.setup(swaggerDocs));

app.use("/v0.2/api-docs", swaggerUi.serveFiles(v02SwaggerDocs), swaggerUi.setup(v02SwaggerDocs));

Upvotes: 0

Hafeez Hamza
Hafeez Hamza

Reputation: 814

I was also looking for a solution for this issue, and found a better solution recommended by Swagger UI Express. check the link below

https://github.com/scottie1984/swagger-ui-express#two-swagger-documents

const express = require('express');
const app = express();
const swaggerUi = require('swagger-ui-express');
const swaggerDocumentOne = require('./swagger-one.json');
const swaggerDocumentTwo = require('./swagger-two.json');

var options = {}

app.use('/api-docs-one', swaggerUi.serveFiles(swaggerDocumentOne, options), swaggerUi.setup(swaggerDocumentOne));

app.use('/api-docs-two', swaggerUi.serveFiles(swaggerDocumentTwo, options), swaggerUi.setup(swaggerDocumentTwo));

Hope this will help others as well.

Upvotes: 1

Roy Lee
Roy Lee

Reputation: 10842

Try the following configurations to hook swaggerUi with express-app


app.use("/edi", swaggerUi.serve, (...args) => swaggerUi.setup(ediSwaggerDocument)(...args));
app.use("/ecom", swaggerUi.serve, (...args) => swaggerUi.setup(ecomSwaggerDocument)(...args));


Upvotes: 8

Benoît Guérout
Benoît Guérout

Reputation: 1997

I haven't dig enough into the swagger-ui-express but i think the problem comes from the function generateHTML (called in swaggerUi.setup). A global module variable (swaggerInit) is updated when called.

So the last call to generateHTML has side effects on every routes that use swaggerUi.setup middleware.

A quick fix is to generate HTML each time the route is called. According to the code snippet you provide, it should looks like :

 let swaggerDocEdi = require('./edi-openapi.json');
 let swaggerDocEcom= require('./ecom-openapi.json');
 let router = express.Router();

 router.use('/api/edi', swagger.serve, (req, res) => {
     let html = swagger.generateHTML(swaggerDocEdi);
     res.send(html);
 });

 router.use('/api/ecom', swagger.serve, (req, res) => {
     let html = swagger.generateHTML(swaggerDocEcom);
     res.send(html);
  });

Note that the global variable is still updated.

Upvotes: 3

Rohit Singh Rana
Rohit Singh Rana

Reputation: 19

router.use('/jobs/api/:id',swaggerUi.serve,(req,res)=>{
console.log("here")
let a = req.params.id
if(a==='all'){ res.status(200).send(swaggerUi.generateHTML(swaggerDocument))}
if(a==='google'){res.status(200).send(swaggerUi.generateHTML(GoogleAds)) }

});

Upvotes: 1

codedawi
codedawi

Reputation: 314

It looks like the Router is being used incorrectly. For this simple use case I would recommend adding your routes directly to the app instance. See:

const express    = require('express');
// xxxx const router     = require('express').Router();
const swaggerUi  = require('swagger-ui-express');

const ediSwaggerDocument  = require('./edi-openapi.json');
const ecomSwaggerDocument = require('./ecom-openapi.json');

const SWAGGER_APP_PORT = process.env.SWAGGER_APP_PORT || 5000;

const app = express();

// Route Middleware to be called before serving Any Route
app.use('/', swaggerUi.serve); // replaced router with app

// Route - EDI RESTful API Documentaion 
// REPLACED "router" with "app"
app.get('/edi', swaggerUi.setup(ediSwaggerDocument)); 
// Route - eCommerce RESTful API Documentaion 
// REPLACED "router" with "app"
app.get('/ecom', swaggerUi.setup(ecomSwaggerDocument));

app.listen(SWAGGER_APP_PORT, () => console.log(`RESTful API Up and Running on Port ${SWAGGER_APP_PORT}`));

Now, you could use the Router by adding it to the app instance with app.use(). See:

// Route - EDI
router.get('/edi', swaggerUi.setup(ediSwaggerDocument)); 

// Route - eCommerce 
router.get('/ecom', swaggerUi.setup(ecomSwaggerDocument));

// Adding it to App instance
app.use('/swagger', router)

// End Point =>     localhost:5000/swagger/edi

Hope this helps!!

Upvotes: -1

Related Questions