Parameters and response-body not documented while using express-oas-generator
MounikaKommineni opened this issue ยท 24 comments
Thanks for the library. I am using version 1.0.7
Below is my app.js code here i am using express-oas-generator
var express = require('express');
var app = express();
const expressOasGenerator = require('express-oas-generator');
var bodyParser = require('body-parser');
var port = process.env.PORT || 3606;
var db = 'mongodb://localhost/example';
expressOasGenerator.init(app, {});
var books = require('./routes/books');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use('/books', books);
app.listen(port, function(){
console.log('app listening on port: '+port);
});
Below is my schema:
var BookSchema = new Schema({
title: String,
author: String,
category: String,
booknames: [ String],
booktypes: [{
_id : false,
lang_code:{type : String ,required : true },
booktype: String,
}]
});
My api-spec looks like below:
paths: {
/books: {
get: {
summary: "/books",
consumes: [
"application/json"
],
parameters: [ ]
},
post: {
summary: "/books",
consumes: [
"application/json"
],
parameters: [ ]
}
},
My post api looks like below:
router.post('/', async(req, res, next)=>{
res.setHeader('Content-Type', 'application/json');
var newBook = new Book();
newBook.set(req.body)
await newBook.save(function(err, book){
if(err) {
res.status(HttpStatus.BAD_REQUEST)
.send({
error: HttpStatus.getStatusText(HttpStatus.BAD_REQUEST)
});
}
});
next();
});
I have seen the similar issues and implemented in the similar way. Please help where I am doing wrong.
https://github.com/mpashkovskiy/express-oas-generator/issues/9
https://github.com/mpashkovskiy/express-oas-generator/issues/4
Hi Mounika, will check it this week.
Hi mpashkovskiy,
Is this issue resolved. I am waiting to use this package in my application if the issue is fixed.
Hi Mounika, thank you for being patient. Will investigate the issue and get back to you today.
Hi Mounika, tried to reproduce the problem in the branch issue-24 (see server.js) but with no luck. May I ask you to modify the code in server.js or somewhere around index.js#177 so the problem appear?
I ran it like node server.js
and then checked http://localhost:3606/api-docs/ in the browser.
@MounikaKommineni did you have time check server.js? Maybe you can give a hint how to reproduce the problem?
Hi mpashkovskiy,
I have tried with your server.js It is giving the response body. But do I need to specify all my methods manually like you are doing for POST ?
app.listen(port, function() {
console.log('app listening on port: ' + port);
setTimeout(() => {
request({
url: `http://localhost:${port}/books`,
method: 'POST',
headers: {'content-type' : 'application/json'},
body: JSON.stringify({data: 'data'})
});
}, 2000);
});
Hi MounikaKommineni
Not sure that I understand your question, I'm not specifying anything here I'm just making a call right after server gets up and running. I did it just to show that if you make a call to your server express-oas-generator will catch it and parse parameters and update swagger specification.
Let me quote one thing from README.md:
Important! In order to get description of all parameters and JSON payloads you have to start using your REST API or run REST API tests against it so module can analyze requests/responses
So that means if you want to see all the parameters in swagger specification you have to run REST API tests (or just call your REST API with postman/insomnia/your favorite REST API client) against your service and then express-oas-generator will do the job for you - fill the specification.
Please let me know if it is clear.
Hi mpashkovskiy,
Thank you for giving the clarity. I have done the same initially only, which is mentioned in the README.md
But the problem is when I post my data initially through postman in the swagger response body of post is getting displayed and request body is still empty. I have added screenshot for reference
I have added the sample example zip file for which I am trying to generate the swagger
- Unzip and run npm install
- after that run node app.js
As I am new to nodejs I am working with sample example. Please check and help me where I am going wrong
could you please also attach postman screenshot, so I can reproduce it?
Ok, here is the problem: express-oas-generator (EOG) adds parameters handler as a very last middleware. If any middleware or path in router breaks the chain and doesn't pass execution to next middleware/router then very last EOG middleware won't be called. So call next() or next(err) as the very last line in your handler.
Some docs:
- calling next() https://expressjs.com/en/guide/writing-middleware.html
- handling errors with next() https://expressjs.com/en/guide/error-handling.html
To fix the problem call next()/next(err) at the end of all your handlers. For example for POST handler the code will looks like:
router.post('/', async(req, res, next) => {
var newBook = new Book();
console.log(req.body)
newBook.set(req.body);
await newBook.save(function(err, book) {
if (err) {
res.status(HttpStatus.BAD_REQUEST)
.send({
error: HttpStatus.getStatusText(HttpStatus.BAD_REQUEST)
});
next(err);
} else {
res.status(HttpStatus.OK)
.send(book)
next();
}
});
});
Thank you for pushing this issue forward. Let me know if there are still problems.
Many Thanks for solving my issue.
It's working.
I suggest adding this information to the documentation/README file.
@mpashkovskiy can we somehow make it possible to add in as first middleware
@duke7able We cannot because we need to analyze the response object after you send the response.
But that makes me think -- perhaps we could hook into express' res.send
function and handle our logic there so that the end user does not need to call next()
everywhere (at times it's not even supposed to be called - see #36).
I think it might be possible - I'm looking at express' source code right now, and it seems that you can access req
and other variables from res.send
. Needs more investigation.
/cc @mpashkovskiy
Just a small "wording fix": not "after you send the response." but "after your server sends the response."
In overall @kiprasmel it is an excellent idea to hook to res.send
!
@matveypashkovskiy oh wow that's amazing, it seems like we can make it happen!
Sadly I'm currently hella bussy - if anyone wants to take a shot at creating a PR - let us know by commenting here, and try your luck:)
I think we could achieve an API like this:
const express = require("express");
const expressOasGenerator = require("express-oas-generator");
const app = express();
const eoasConfig = { };
app.use(expressOasGenerator(eoasConfig));
it'd be great!
ok, I'll check, or maybe you, @duke7able, want to give it a try?
moved to #81
ok, I'll check, or maybe you, @duke7able, want to give it a try?
Sorry covid hit us bad, needed to cut of time from foss . I could contribute in it later, but i dont have a specific timeline
I have similar question, I defined my route and I know I need to some parameters in body but I do not know how to define/show these parameters on doc.
This is my route;
router.post('/login', errorHandler(async (req, res) => {
const { username, password } = req.body;
const loginResult = await UserService.login({ username, password });
if (loginResult) {
return res.status(200).json({
success: true,
...loginResult
});
}
return res
.status(401)
.json({ success: false, msg: 'Incorrect username or password' });
})
);
And I used advanced implementation of generator;
expressOasGenerator.handleResponses(app, {
predefinedSpec: (spec) => {
_.set(spec, 'info', options.swaggerDefinition.info);
_.set(spec, 'mongooseModels', mongoose.modelNames());
_.set(spec, 'components.securitySchemes.bearerAuth', {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT'
});
_.set(spec, "paths['/v1/some-path'].get.security", [{ bearerAuth: [] }]);
return spec;
},
mongooseModels: mongoose.modelNames(),
alwaysServeDocs: true
});
...
createRoutes(app);
...
expressOasGenerator.handleRequests();
app.listen(port, () => {
logger.info(`App running on port ${port}`);
});
But on the localthost:3000/api-docs I can't see the body parameters, how can I define and show on doc those parameters? Can someone help me?