I have the following scenario:
users.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const apiRoot = '/api/v1/users';
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', false);
next();
});
app.get(apiRoot, async function(req, res) {
[... do stuff ...]
});
app.get(apiRoot + '/:id', async function(req, res){
[... do stuff ...]
});
app.listen(process.env.PORT);
bookings.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const apiRoot = '/api/v1/bookings';
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', false);
next();
});
app.get(apiRoot, async function(req, res) {
[... do stuff ...]
});
app.get(apiRoot + '/:id', async function(req, res){
[... do stuff ...]
});
app.listen(process.env.PORT);
This is working fine and without errors. Problem is that I have to maintain all my app settings in more that one single file (I have others beyond users.js and bookings.js...). Is there a way I can concentrate the app creation in one file and import it to users.js, bookings.js and so on?
Each set of routes could simply be in a file that exports a function that takes app e.g.
// bookings.js
module.exports = function(app) {
app.get(...)
};
then in your main
const bookingsRoutes = require('./bookings');
bookingsRoutes(app);
The more common design and really how Express was architected is that each of your files should create a router and export the router. Then, you'd have one main file that creates the app object, imports each of your modules and hooks in their router. In this case, you could also export the root that they want to be installed on.
// m1 module
const express = require('express');
const router = express.Router();
const apiRoot = '/api/v1/users';
// set up router-specific middleware
// if this is the same for all routers, then move this to app.js and just
// do it once there
router.use(express.urlencoded({ extended: false }));
router.use(express.json());
router.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', false);
next();
});
// Configure routes for this router
// The router is installed already on apiRoot so we don't need that in the paths here
router.get('/', async function(req, res) {
[... do stuff ...]
});
router.get('/:id', async function(req, res){
[... do stuff ...]
});
module.exports = {apiRoot, router};
Then, you'd have a main app.js:
const express = require('express');
const app = express();
// load and hook in the other routers
const m1 = require('./m1");
app.use(m1.apiRoot, m1.router);
const m2 = require('./m2");
app.use(m2.apiRoot, m2.router);
app.listen(process.env.PORT);
If you really want the body-parser middleware and the CORS stuff to be common to all your routers, then move it into app.js so your router files are only about serving routes.
Both answers didn't work in my environment, because I am using nodejs on an IIS server. Here is the solution I used:
app.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', false);
next();
});
app.listen(process.env.PORT);
module.exports = function() { return app; }
users.js
const app = require('./app')();
const list = require('./list');
const apiRoot = '/api/v1/users';
app.get(apiRoot, async function(req, res) {
// [... do stuff ...]
});
Thanks for the provided answers. They put me in the right direction.
Related
I've been banging my head against the wall on this one for a few hours. I'm not sure why it doesn't work but it's probably something simple I'm missing. It usually is...
Anyway, I'm doing a simple HTTP PUT from Angular 7 like this:
protected put(cmd: string, body: any) {
let headers = new HttpHeaders();
headers.append('Content-Type','application/json');
console.log(body);
return this._http.put(cmd, body, {headers: headers});
}
cmd and body are being passed in. I can see the body print out in the console and the cmd path is correct to hit my route path in Node.
From there, it comes into my Node/Express app. Which goes as follows:
'use strict';
const express = require('express');
const bodyParser = require('body-parser')
// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
// App
const app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-
Type, Accept");
next();
});
app.use('/api', require('./routes/routes'));
app.use('/api/add-user', require('./routes/add-user/routes'));
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
And this is my routes file that console prints the empty body:
const express = require('express');
const router = express.Router();
const dvAdmin = require('../../controller/controller');
//Routes
//GETS
//PUTS
router.put('/addCCUser', function (req, res) {
console.log(req.body);
});
module.exports = router;
This is my simple nodejs app using express:
const express = require('express');
const app = express();
const user = require('./routes/user').user;
const browser = require('./routes/browser');
const bodyParser = require('body-parser');
// CORS middleware
const allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', '*');
res.header('Access-Control-Allow-Headers', '*');
next();
}
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(allowCrossDomain);
app.use('/', user);
app.use('/', browser);
const port = process.env.PORT || 4001;
app.listen(port, function() {
console.log('Express server listening on port ' + port)
});
Route handler "browser", where I added middleware:
const express = require('express');
const router = express.Router();
router.use(function (req, res, next) {
console.log(req.body);
next();
});
router.post('/get-content', (req, res) => {
});
Console
Here I got strange behaviour with middleware. I want to get request body data, but in console I see empty object instead expected body with content. After calling next() middleware fires second time and finally I am getting request body. Help me understand middleware behaviour in my case.
It`s can be help. Install cors package, and give it in express.use.
https://www.npmjs.com/package/cors
Middleware to support CORS pre-flight requests
const allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', '*');
res.header('Access-Control-Allow-Headers', '*');
//intercepts OPTIONS method
if ('OPTIONS' === req.method) {
res.sendStatus(200);
} else {
next();
}
}
I am creating a REST api using Node.js And Express, The application works fine including routes and other functanalities on local computer but when uploaded to windows server routes are not working properly, I was able to see Hello World printed on my from home page e.g:- www.abcd.com/,
But when routes are being used eg:- www.abcd.com/users/ it gives 404 - File or directory not found.
Here is my code
server.js
const http = require('http')
const app = require('./app')
const server = http.createServer(app);
server.listen(process.env.PORT, () => {
console.log("Server Started");
});
app.js
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const app = express();
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use((req, res, next) => {
res.header(
'Access-Control-Allow-Origin',
'*'
);
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-with, Content-Type, Accept, Authorization"
);
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
return res.status(200).json({});
}
next();
});
const users_routes = require('./api/routes/users.routes');
const message_routes = require('./api/routes/message.routes');
const group_routes = require('./api/routes/group.routes');
const key_routes = require('./api/routes/key.routes');
console.log(users_routes.toString());
app.use('users', users_routes);
app.use('message', message_routes);
app.use('group', group_routes);
app.use('key', key_routes);
app.use('/', (req, res, next) => {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<H1>Hello World!</H1>');
});
module.exports = app;
user.routes.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res, next) => {
Console.log("Hello there");
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('<H1>Hello World!</H1>');
});
module.exports = router;
Log file after starting app
Server Started
It prints function when used typeof(user_routes)
Having issues with the express router
I'm getting a 404 for the login route, so it must be how I've initialised my routes?
I'm not handling "/" but I'm not sure how to??
My index file:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var blogRoutes = require('./routes/blogs');
var loginRoute = require('./routes/login');
var port = process.env.PORT || '3000';
var http = require('http');
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
mongoose.connect(myInfo);
app.set('view engine', 'hbs'); //Templating engine (HandleBars)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
res.setHeader('Access-Control-Expose-Headers', 'Authorization');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE, OPTIONS');
next();
});
//ROUTES
//Handle specific routes first
app.use('/blogs', blogRoutes);
app.use('/login', loginRoute);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
return res.render('404');
});
module.exports = app;
my login.js Just a simple logging for now:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
console.log("LOG::::::::::::::::::::::::::")
});
And in Angular:
login(email, password) {
return this.http.post(this.blogsURL + 'login', {email:email, password:password} )
.map((res) => {
console.log(res)
return res;
})
Any pointers?
You are sending a POST call to a GET route /login.
(I'm sorry. I don't have enough reputation to comment.)
Apologies, I made a noobie error and didn't subscribe to the login function in the component
this.authService.login(email, password)
.subscribe(data=>console.log(data));
Thanks for your help
When I am using domainRouting function, then if I am using res.send in routes file then everything is working. When I want to show view for some reason that I dont know when I run npm start it starts normaly, but when I visit that website in browser then I don't know why, but I am getting error, and server crashes.
“Cannot GET /“
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var appRoutes = require('./routes/app');
var login = require('./routes/login');
function domainRouting(req, res, next){
var subdomain = req.headers.host.split('.')[0];
if(subdomain === 'login'){
login(req, res, next);
};
if(subdomain === 'equestriansnet'){
appRoutes(req, res, next);
}
next();
};
var app = express();
var connection =
mongoose.connect('mongodb://admin:slaptas#147.135.210.148:27017/d', { auth: { authdb: 'admin' } });
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE, OPTIONS');
next();
});
app.use('*', domainRouting);
//app.use('/', appRoutes);
// catch 404 and forward to error handler
//app.use(function(req, res, next) {
// res.render('index');
//});
module.exports = app;
(db pass is random word just for hiding real-one) and one of my route files
that points one of subdomains
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
//res.render('index');
res.send('Main ' + req.url);
});
module.exports = router;
Finaly I founded problem. It`s this line of code
next();
if I put this in if then everything will work correct.