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
Related
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.
I am using express.js framework for my node.js server.
This is how I setup my server.
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 index = require('./routes/index');
var createUsers = require('./routes/users/createUsers');
var updateUsers = require('./routes/users/updateUsers');
var deleteUsers = require('./routes/users/deleteUsers');
var readUsers = require('./routes/users/readUsers');
var app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
var mysql = require("mysql");
//Database connection
app.use(function(req, res, next){
res.locals.connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'password',
database : 'project'
});
res.locals.connection.connect();
next();
});
// 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('/', index);
app.use('/createUsers', createUsers);
app.use('/updateUsers', updateUsers);
app.use('/deleteUsers', deleteUsers);
app.use('/readUsers', readUsers);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error.ejs');
});
var http = require('http');
module.exports = app;
var server = http.createServer(app);
server.listen(4000);
This is my readUsers.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
//console.log("pending data");
res.locals.connection.query('SELECT id,name,email,username,address,phone,status FROM user', function (error, results, fields) {
if (error) throw error;
res.send(JSON.stringify(results));
});
});
module.exports = router;
My server is listen at port 4000. My react frontend componentDidMount() function use axios.get("http://localhost:4000/readUsers") to read the data from database and it worked well.
However, if I directly type in http://localhost:4000/readUsers in my browser, it will directly connect to my database and read all User data and displayed the data in browser. This is not I want because everyone can read my data if they know this address. Any way to prevent this issue?
Add middleware to your router. here's the doc Router-level middleware
Express have many middleware, one of it is route-level middleware. This middleware handle anything between users and your function.
Here is the example i fetch from the documentation.
var app = express()
var router = express.Router()
// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', function (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}, function (req, res, next) {
console.log('Request Type:', req.method)
next()
})
In your case you may add some permission validation before request. Usually it's an API key, but it can be anything, secret word in header, secret parameter, everything.
Here is the example for your case.
function isPermitted(req, res, next) {
var permitted = false;
// Your validation here, is your user permitted with this access or not.
if (permitted) {
next();
} else {
res.send('Sorry, you are not belong here.');
}
}
/* GET home page. */
router.get('/', isPermitted, function(req, res, next) {
//console.log("pending data");
res.locals.connection.query('SELECT id,name,email,username,address,phone,status FROM user', function (error, results, fields) {
if (error) throw error;
res.send(JSON.stringify(results));
});
});
Use POST instead of GET as method for request.
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)
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.