I'm a new developer trying to understand routers and controllers with Express, Express Router, and Axios.
server (app.js):
var createError = require('http-errors');
var express = require('express');
var cors = require('cors');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var authRouter = require('./routes/auth');
var app = express();
app.use(cors());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// routes
app.use('/', indexRouter);
app.use('/login', authRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// 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');
});
module.exports = app;
router (auth.js):
var express = require('express');
var router = express.Router();
const controller = require("../controllers/auth.controller");
router.post('/login', controller.login);
module.exports = router;
controller (auth.controller.js):
var axios = require('axios');
const url = "https://my-api-url.com";
module.exports = {
login: (req, res) => {
console.log('made login request');
return axios.post(url + "/token", {
username: req.body.username,
password: req.body.password
}, {
headers: { "Content-Type": "application/json" },
}).then((response) => {
res.send({
access_token: response.data.access_token
});
}).catch((err) => {
console.log('failed to login');
});
}
};
I receive a "POST localhost 404 (Not Found)" and "Uncaught (in promise) Error: Request failed with status code 404" response on the console. However, this works perfectly:
app.js (without router and controller):
var createError = require('http-errors');
var express = require('express');
var axios = require('axios');
var cors = require('cors');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var app = express();
app.use(cors());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
const url = "https://my-api-url.com";
// returns access token
app.post('/login', (req, res) => {
console.log('made login request!');
axios.post(url + "/token", {username: req.body.username, password: req.body.password}, {
headers: {"Content-Type": "application/json"},
}).then((response) => {
res.send({access_token: response.data.access_token});
}).catch((err) => {
console.log('failed to login');
});
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// 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');
});
module.exports = app;
I could just continue using the last code segment since it works perfectly fine, but I want to learn the logic and best practices. I'm just not sure what I'm doing wrong. Thanks in advance.
In app.js, when you used a router:
app.use('/login', authRouter);
Your application will get any route inside your router in relative way.
When inside your router you handle post that way:
router.post('/login', controller.login);
Your application will wait a call like this: http://localhost:3000/login/login/
If you want to call with http://localhost:3000/login/, your router should be like this:
var express = require('express');
var router = express.Router();
const controller = require("../controllers/auth.controller");
router.post('/', controller.login);
module.exports = router;
Related
I am writing nodejs express to fetch the data to web page. an error appear 404 Not Found when open
http://127.0.0.1:3000/users
in the Dev tool on the browser show: users:1 GET http://127.0.0.1:3000/users 404 (Not Found)
below are the app.js and index.js and users.js files
I think I have an issue with the routes
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var expressValidator = require('express-validator');
var flash = require('express-flash');
var session = require('express-session');
var bodyParser = require('body-parser');
var mysql = require('mssql');
// var connection = require('./lib/db');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
//I put false instead true
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: '123456cat',
resave: false,
saveUninitialized: true,
cookie: { maxAge: 60000 }
}))
app.use(flash());
app.use(expressValidator());
app.use('/', indexRouter);
app.use('/list', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// 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');
});
module.exports = app;
below are the routes files.
routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
routes/users.js
var express = require('express');
var router = express.Router();
var connection = require('../database.js');
/* GET home page. */
router.get('/', function(req, res, next) {
connection.query('SELECT * FROM users',function(err,rows) {
if(err){
req.flash('error', err);
res.render('list',{page_title:"Users - Node.js",data:''});
}else{
res.render('list',{page_title:"Users - Node.js",data:rows});
}
});
});
module.exports = router;
As I already mentioned in my comment, you don't have a /user route therefore you will get a 404 NotFound error.
Change this
app.use('/list', usersRouter);
To this
app.use('/user', usersRouter);
I am new to javascript and would like to retrieve the json response from my express route get request. I can return the whole json but when i try to return a specific element i recieve an error (eg res.body.data). Here is my route file
route.js
var express = require('express');
var router = express.Router();
var request = require('request');
router.get('/', function(req, res, next) {
request({
uri: 'https://www.reddit.com/r/meme/new/.json'
}).pipe(res);
});
module.exports = router;
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var cors = require("cors");
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var testAPIRouter = require('./routes/testAPI');
var route = require('./routes/route');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/testAPI', testAPIRouter);
app.use('/route', route);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// 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');
});
module.exports = app;
You need to use body parser:
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
Currently my code is this:
var express = require('express');
var router = express.Router();
var db = require('../helpers/db');
var data = {
"1": 127,
"2": 236,
"3": 348
}
router.get('/', function(req, res, next) {
res.send(data);
});
router.get('/:id', function(req, res, next) {
var key = req.params.id;
res.send({ [key]: data[key] });
});
router.post('/:id', function(req, res, next) {
var id = req.params.id;
console.log(id);
})
My goal is to be able to POST a value from Postman to API/values/:id, save that value under the id key and then save that "key": value pair in the data variable. Unfortunately, when I try to POST anything and then access it with req.body, I get {} or undefined.
app.js
var routes = require('./routes/');
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var expressSession = require('express-session');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// 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(expressSession({
secret: 'secretText',
saveUninitialized: true,
resave: true
}))
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes.home);
app.use('/values', routes.values);
// 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');
});
module.exports = app;
To do so you need to have body-parser plugin of expressjs.
Install it using npm install --save body-parser and then use it like below
var bodyParser = require('body-parser');
express()
.use(bodyParser.urlencoded({
extended: true
}))
.use(bodyParser.json())
My express application seems to return 404 NOT FOUND whenever im using a post request method in my routes file. GET-requests are working fine and i can only see "GET" requests in the console aswell, even if im using a post request.
Is there some missing link between app.js and routes/index.js that might be causing this?
// routes/index.js
router.post('/foo', function (req, res, next) {
res.setHeader('Content-Type', 'application/json');
res.send('You sent: sdadad to Express');
})
// 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 index = require('./routes/index');
var app = express();
var cors = require('cors')
app.use(cors())
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// 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);
// 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');
});
module.exports = app;
Result:
Not Found 404
Error: Not Found
at C:\Users\willow\Desktop\backend\app.js:29:13
at Layer.handle [as handle_request] (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:317:13)
at C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:284:7
at Function.process_params (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:275:10)
at C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:635:15
at next (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:260:14)
at Function.handle (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:174:3)
at router (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:47:12)
at Layer.handle [as handle_request] (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:317:13)
at C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:284:7
at Function.process_params (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\willow\Desktop\backend\node_modules\express\lib\router\index.js:275:10)
at SendStream.error (C:\Users\willow\Desktop\backend\node_modules\serve-static\index.js:121:7)
What you wanna do should look like this in practice:
// routes/index.js
module.exports = (express) => {
// Create express Router
var router = express.Router();
// add routes
router.route('/foo')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
res.send('You sent: sdadad to Express');
});
return router;
}
// 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 routes = require('./routes')(express); // require routes at routes/index.js
var app = express();
var cors = require('cors')
app.use(cors())
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// 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('/', routes);
// 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');
});
module.exports = app;
What I usually do is create a function that expects express as param like this
(routes/index.js)
module.exports = (express) => {
// Create express Router
var api = express.Router();
// add routes
api.route('/some_endpoint')
.post((req, res) => {
res.json({ message : 'some message' })
});
return api;
}
then I just import this file to my app.js
like this
(app.js)
// set api as a middleware
const api = require('./routes')(express);
app.use('/api/v1', api);
that way I hook up my api and my server.
Im having trouble connecting Node.js application with sql database.
Error occurs is "req.getConnection is not a function".
I am trying to get data from the database the moment I click on a certain page (eg.users).
My code is as below
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 flash = require('express-flash');
var session = require('express-session');
var expressValidator = require('express-validator');
var methodOverride = require('method-override');
var connection = require('express-myconnection');
var mysql = require('mysql');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// 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(session({secret:"mysecretpass"}));
app.use(flash());
app.use(expressValidator());
app.use(cookieParser());
app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use(methodOverride(function(req, res){
if (req.body && typeof req.body === 'object' && '_method' in req.body)
{
var method = req.body._method;
delete req.body._method;
return method;
}
}));
/*-----------------------------------------
* Connection peer, register as middleware
* type koneksi:single,pool and request
-----------------------------------------*/
app.use(
connection(mysql,{
host:'localhost',
user:'root',
password:'',
port:3306,
database:'stores'
},'single')
);
// 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 handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('dashboard', { title: 'Dashboard' });
});
router.get('/admin_users', function(req, res, next) {
req.getConnection(function(err,connection){
var query = connection.query('SELECT * FROM users',function(err,rows)
{
if(err)
var errornya = ("Error Selecting : %s ",err );
req.flash('msg_error', errornya);
res.render('admin_users',{title:"Admin Users",data:rows});
});
//console.log(query.sql);
});
});
module.exports = router;
You are adding the express-myconnection middleware after your routes middleware. Middleware is executed in the order it is added, and as such the getConnection function is not defined on the req object until after your express-myconnection middleware is executed.
Simply move the connection middleware above the usage of routes, ie.
app.use(
connection(mysql,{
host:'localhost',
user:'root',
password:'',
port:3306,
database:'stores'
},'single')
);
app.use('/', routes);
app.use('/users', users);