Swagger-ui not work with restify but works with express - node.js

I am working on to create swagger docs for node restify APIs but it's not working .can any one help me out why this happened.
my code is as follow
app.js
require('dotenv').config();
var restify = require('restify');
var corsMiddleware = require('restify-cors-middleware');
var swaggerOption=require('./app/swagger/swagger.js');
const swaggerUi = require('swagger-ui-restify');
const swaggerJSDoc = require('swagger-jsdoc');
const swaggerSpec = swaggerJSDoc(swaggerOption.options);
var cors = corsMiddleware({
preflightMaxAge: 5,
origins: ['*'],
allowHeaders:['X-App-Version'],
exposeHeaders:[]
});
/**
* Initialize Server
*/
var server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);
server.use(restify.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.queryParser({ mapParams: true }));
server.use(restify.plugins.bodyParser());
server.get('/docs',swaggerUi.serve, swaggerUi.setup(swaggerSpec))
server.get('/api-docs',swaggerUi.serve, swaggerUi.setup(swaggerSpec))
server.listen(8080, function () {
console.log('%s listening at %s', server.name, server.url);
});
In my swagger.js file it contains options object for swagger ui and use with swagger jsdoc.
I am getting following error when hit this swagger url
http://localhost:8080/api-docs.
Error: ENOENT: no such file or directory, stat '/var/www/html/projects/User-Workspace/node_modules/swagger-ui-restify/static/api-docs
Can any one please help me out with this..thank you

Related

Running Swagger JSON through Swagger UI via node

I have done npm install swagger-ui-express in the root folder of the project and kept a swagger.json as well there. My app.js contains:
var swaggerUi = require('swagger-ui-express'),
swaggerDocument = require('./swagger.json');
const express = require('express');
const app = express();
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
// app.use('/api/v1', router);
const server = app.listen(3000, function () {
let host = "localhost"
let port = 3000
console.log("App listening at http://%s:%s", host, port)
})
I have created a folder api-docs as well inside the root project folder. When I run in terminal node app.js and see in the browser localhost:3000, it displays
Cannot GET /
What can be the issue?

Node.js console.log not logging in terminal

I have a simple app where I'm trying to log to the console (terminal where I started Node, not the the browser console). Express seems to execute the route since I can see the response in my browser.
Also the logging in the app.listen(..) seems to work, but I don't see any logs afterwards.
'use strict';
// 3rd-party dependencies
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const dbSetup = require('./db-setup');
// Application config
const LOCAL_APP_PORT = 8080;
const PUBLIC_APP_PORT = process.env.PUBLIC_APP_PORT || LOCAL_APP_PORT;
global.dbType = process.env.DB_TYPE;
// Sanity check for debugging
console.log("local app port:", LOCAL_APP_PORT);
console.log("public app port:", PUBLIC_APP_PORT);
console.log("db type:", global.dbType);
// Database setup for either MongoDB or Postgres
dbSetup(global.dbType);
// Express middleware
app.use(bodyParser.json()); // for parsing application/json
// Import routes
//const index = require('./routes/index');
//const owner = require('./routes/owner');
//const shop = require('./routes/shop');
//const product = require('./routes/product');
// Set up express routes
app.use('/',(req,res,next) => {
console.log("This is not showing on the terminal.");
res.send("This is sent to the browser");
next();
})
//app.use('/owner', owner);
//app.use('/shop', shop);
//app.use('/product', product);
app.listen(LOCAL_APP_PORT, () => {
console.log('App started ...');
});
EDIT: Solved. Problem was my app was basically available on two ports at the same time. One the the public port however it was not showing any logs...
Terminal screenshot

"Cannot get /" in Swagger, Express and Node.js

I am working with Swagger, Express and Node to define and run endpoints. A GET request on the localhost/docs returns all the relevant routes. But when I try a GET request on any of the routes, it returns a "Cannot Get /XXX"
Index.js
'use strict';
var fs = require('fs'),
path = require('path'),
// Basic Setup new express
http = require('http'),
express = require('express'),
mysql = require('mysql'),
parser = require('body-parser');
var swaggerTools = require('swagger-tools');
var jsyaml = require('js-yaml');
// Setup express
var app = express();
app.use(parser.json());
app.use(parser.urlencoded({ extended: true }));
app.set('port', process.env.PORT || 5000);
// Database Connection
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'root',
database : 'sample_database'
});
try {
connection.connect();
console.log('Database connected!');
} catch(e) {
console.log('Database Connetion failed:' + e);
}
// swaggerRouter configuration
var options = {
swaggerUi: path.join(__dirname, '/swagger.json'),
controllers: path.join(__dirname, './controllers'),
useStubs: process.env.NODE_ENV === 'development' // Conditionally turn on stubs (mock mode)
};
// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
var spec = fs.readFileSync(path.join(__dirname,'api/swagger.yaml'), 'utf8');
var swaggerDoc = jsyaml.safeLoad(spec);
// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
// Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
app.use(middleware.swaggerMetadata());
// Validate Swagger requests
app.use(middleware.swaggerValidator());
// Route validated requests to appropriate controller
app.use(middleware.swaggerRouter(options));
// Serve the Swagger documents and Swagger UI
app.use(middleware.swaggerUi());
// Create server
http.createServer(app).listen(app.get('port'), function(){
console.log('Server listening on port ' + app.get('port'));
});
});
While initialising the middleware, I tried using:
app.use(express.static(__dirname + './controllers'));
But the error is still present. I think this has got something to do with the routing but I am not sure where is the error is.
The directory structure for the code is:
-my_app
|
+--controllers
| |
| +--user.js
| +--userService.js
+--index.js
Try use this construction
require('./controllers/<your_routing_file>')(app);
and type routes not in index.js

app is undefined in loopback custom js file

i am using nodejs loopback framework.i want to run a cron job.i created a custom js file for this cron job in server/boot folder.but when manually i run this file(xyz). app is undefined.my code is below
var app = require('../server.js');
console.log(">>>>>>>>>>>>>>in test")
var subscription = app.models.UserNotification;
console.log(">>>>>>>>>>>..in manage")
var datasource=subscription.dataSource;
var query="SELECT DISTINCT userId FROM users_subscription";
datasource.connector.query(sql,function (err, data) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>data is>>>>>",data);
})
here is my server.js file
var bodyParser = require('body-parser');
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
var passport = require('passport');
var bodyParser = require('body-parser').urlencoded({
extended: true
})
app.use(bodyParser)
app.use(loopback.context());
app.use(loopback.token());
var path = require("path");
var url = require('url');
var http = require('http');
var fs = require('fs');
var request = require('request');
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
app.use(loopback.static(path.resolve(__dirname, '../client')));
app.use(loopback.static(path.resolve(__dirname, '../admin')));
app.use(loopback.static(path.resolve(__dirname, '../other-dir')));
boot(app, __dirname, function(err) {
if (err) throw err;
if (require.main === module) app.start();
});
Thanks,
It's really impossible to say for sure since you don't include the code that is included with:
var app = require('../server');
(which would be the most important code to include if the require returns undefined) but if app is undefined then it means that the module is loaded but its module.exports is undefined.
Do you export anything from that module?
Are you sure that it is really app that is undefined and not, say, app.models?
Without knowing the code in question those are the most reasonable things to investigate.
Update
If you don't export anything from your server.js (which was my suspection in my answer above, but now you confirmed it with you code and comment) then after this line:
var app = require('../server.js');
you will not be able to use app.models.UserNotification
If you want to use app.models in the code that requires server.js, then you'll have to add:
module.exports.models = SOMETHING;
in your server.js code. You don't seem to have anything called models in server.js, you don't export anything as module.exports.models, so you can't expect app.models to be defined in your code that does:
var app = require('../server.js');

node.js server and HTTP/2 (2.0) with express.js

Is it possible currently to get node.js HTTP/2 (HTTP 2.0) server? And http 2.0 version of express.js?
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('hello, http2!');
});
var options = {
key: fs.readFileSync('./example/localhost.key'),
cert: fs.readFileSync('./example/localhost.crt')
};
require('http2').createServer(options, app).listen(8080);
EDIT
This code snippet was taken from a conversation on Github.
If you are using express#^5 and http2#^3.3.4, then the correct way to start the server is:
const http2 = require('http2');
const express = require('express');
const app = express();
// app.use('/', ..);
http2
.raw
.createServer(app)
.listen(8000, (err) => {
if (err) {
throw new Error(err);
}
/* eslint-disable no-console */
console.log('Listening on port: ' + argv.port + '.');
/* eslint-enable no-console */
});
Notice the https2.raw. This is required if you want to accept TCP connections.
Note that at the time of this writing (2016 05 06), none of the major browsers support HTTP2 over TCP.
If you want to accept TCP and TLS connections, then you need to start the server using the default createServer method:
const http2 = require('http2');
const express = require('express');
const fs = require('fs');
const app = express();
// app.use('/', ..);
http2
.createServer({
key: fs.readFileSync('./localhost.key'),
cert: fs.readFileSync('./localhost.crt')
}, app)
.listen(8000, (err) => {
if (err) {
throw new Error(err);
}
/* eslint-disable no-console */
console.log('Listening on port: ' + argv.port + '.');
/* eslint-enable no-console */
});
Note that at the time of this writing, I did manage to make express and http2 to work (see https://github.com/molnarg/node-http2/issues/100#issuecomment-217417055). However, I have managed to get http2 (and SPDY) to work using spdy package.
const spdy = require('spdy');
const express = require('express');
const path = require('path');
const fs = require('fs');
const app = express();
app.get('/', (req, res) => {
res.json({foo: 'test'});
});
spdy
.createServer({
key: fs.readFileSync(path.resolve(__dirname, './localhost.key')),
cert: fs.readFileSync(path.resolve(__dirname, './localhost.crt'))
}, app)
.listen(8000, (err) => {
if (err) {
throw new Error(err);
}
/* eslint-disable no-console */
console.log('Listening on port: ' + argv.port + '.');
/* eslint-enable no-console */
});
There is an open pr for express 5.0 since 2018, https://github.com/expressjs/express/pull/3730. Until that is merged, it won't work out of the box.
I have created the solution in the form of a package, https://www.npmjs.com/package/http2-express-bridge
const express = require('express')
const http2Express = require('http2-express-bridge')
const http2 = require('http2')
const { readFileSync } = require('fs')
// Use the wrapper function that returns the application
const app = http2Express(express)
const options = {
key: readFileSync('<Certificate Key>'),
cert: readFileSync('<Certificate file>'),
allowHTTP1: true
};
app.get('/', function (req, res) {
res.send('Hello World')
})
const server = http2.createSecureServer(options, app)
server.listen(3000, () => {
console.log(`listening on port 3000`)
})
This works, and it falls back to Http/1.1 when it receives an Http/1.1 request.
I have also included 'res.push' method for ease of server push. The package works with ESModules and Typescript.
This issue is still around today (2016 as of writing this), so I decided to have a go at making a workaround to make express and http2 packages work nicely together: https://www.npmjs.com/package/express-http2-workaround
Edit: Does not work on any NodeJS version above v8.4 due to the native 'http2' module.
Install via NPM: npm install express-http2-workaround --save
// Require Modules
var fs = require('fs');
var express = require('express');
var http = require('http');
var http2 = require('http2');
// Create Express Application
var app = express();
// Make HTTP2 work with Express (this must be before any other middleware)
require('express-http2-workaround')({ express:express, http2:http2, app:app });
// Setup HTTP/1.x Server
var httpServer = http.Server(app);
httpServer.listen(80,function(){
console.log("Express HTTP/1 server started");
});
// Setup HTTP/2 Server
var httpsOptions = {
'key' : fs.readFileSync(__dirname + '/keys/ssl.key'),
'cert' : fs.readFileSync(__dirname + '/keys/ssl.crt'),
'ca' : fs.readFileSync(__dirname + '/keys/ssl.crt')
};
var http2Server = http2.createServer(httpsOptions,app);
http2Server.listen(443,function(){
console.log("Express HTTP/2 server started");
});
// Serve some content
app.get('/', function(req,res){
res.send('Hello World! Via HTTP '+req.httpVersion);
});
The above code is a working express application that uses both the nodejs http module (for HTTP/1.x) and the http2 module (for HTTP/2).
As mentioned in the readme, this creates new express request and response objects and sets their prototypes to http2's IncomingMessage and ServerResponse objects. By default, it's the inbuilt nodejs http IncomingMessage and ServerResponse objects.
I hope this helps :)

Resources