request.body undefined after using express bodyParser - javascript

Edit: i fixed it by using:
app.configure(function(){
app.use(express.bodyParser());
});
Original post:
I'm trying to figure out how to handle a post with node and express and i'm completely stuck.
After some reading i noticed people saying i should use 'middleware' whatever that means and create a line app.use(express.bodyParser());. I assumed that after adding that i would have a req.body available in my post method. This isn't the case however. It console.log's into a undefined.
I think I don't know how to properly set this up, so here goes nothing:
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, UserProvider = require('./userprovider').UserProvider,
qs = require('querystring');
var userProvider = new UserProvider('localhost', 27017);
var app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server);
server.listen(8080);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.get('/new_game', function (req, res) {
res.sendfile(__dirname + '/new_game.html');
});
app.post('/new_game', function(req, res) {
var codeToUse = Math.random()*10000;
codeToUse = Math.round(codeToUse);
console.log(req.body);
});
app.use(express.bodyParser());
app.listen(3000);

Though you've said now your code works, but i won't suggest you to use bodyParser in the options of
app.configure()
What it does is that, if you use it as you have done, any file can be send into your system for all post requests. It's better if you use
express.json()
and
express.urlencoded()
in the options of
app.configure(),
and when you expect a file use bodyParser in the respective post route like this
app.post('/upload', express.bodyParser(), function(req, res){//do something with req.files})

Related

Express route only works after the second try

I am using the express framework for a node.js backend server. I am using the express router to define the different routes.
This is my app.js file:
var express = require('express');
var app = express();
var server = require('http').Server(app);
var cors = require('cors');
app.use(cors());
app.use(express.json());
var route = require('./route');
app.use('/api/', route);
server.listen(3000, () => {
console.log('App running on port 3000!');
});
This is my router route.js:
var express = require('express');
var router = express.Router();
var controller = require('./controller');
router.use(function (req, res, next) {
next();
router.get('/test', function (req, res, next) {
controller.get(req, res, next);
});
});
module.exports = router;
The route itself uses a controller for the logic controller.js
exports.get = function (req, res, next) {
res.send('Hello World');
}
Starting the app with node app.js and calling the defined route http://localhost:3000/api/test will result in a Cannot GET /api/test on the first try. Calling the route a second time however will result in the expected answer hello world.
What is the reason for the first call failing? Why does it work on the second try? Any ideas are appreciated
Because router.use(function (req, res, next) { will only get executed on the first request, and when you call next() the route was not yet added. Afterwards you call router.get(...) which will add the route, so it will be available the next time.
Nevertheless thats just bad, move the .get(...) outside of .use(...) (you can also get rid of it entirely).

Correct/Concisest way to nest routers with Express

I can set up two routes like this
index.js
var express = require('express');
var app = express();
var router = express.Router();
const PORT = 3001;
app.get('/', function(req, res){
res.send('hello app');
});
app.use('/routes', require('./routes'));
app.listen(PORT, function(){
console.log('listening on port:', PORT);
});
./routes/index.js
var express = require('express');
var app = express();
var router = express.Router();
router.use('/sub1', require('./sub1'));
router.use('/sub2', require('./sub2'));
module.exports = router;
./routes/sub1.js
var express = require('express');
var app = express();
var subOneRouter = express.Router();
subOneRouter.get('/', function(req, res){
res.json({route: 'sub1-base'});
});
subOneRouter.get('/:id', function(req, res){
res.json({'route': 'sub1-base', 'id': req.params.id});
});
module.exports = subOneRouter;
For brevity ./routes/sub2.js looks exactly the same, but its variables are named subTwo
What is the shortest way to nest sub2 under sub1? Within index.js I have tried
var subOne = router.use('/sub1', require('./sub1'));
subOne.use('/sub2', require('./sub2'));
But that didn't work at all. Within index.js
router.use('/sub1/:id/sub2', require('./sub2'));
//localhost:3000/sub1/123/sub2/456 => { "route": "sub2-base","id":"456"}
Does work, but it seems it could get verbose and difficult to maintain if the structure got much longer. What's the best way to do this? Is there a shorter way to nest these?
Your code in index.js makes it difficult to understand what you want. So far I understand you want a route like /sub1/:id/sub2 but more easy to write and maintain and inside index.js.
So yes you can do it and it is quite simple.
You just need to require sub1 and sub2 and use sub2 in sub1, then you can mount sub1 on the router.
Ex:
var sub1= require('./sub1');
var sub2 = require('./sub2');
sub1.use(sub2);
router.use('/sub1:id', sub1);
So your index.js becomes,
var express = require('express');
var app = express();
var router = express.Router();
const PORT = 3001;
app.get('/', function(req, res){
res.send('hello app');
});
var sub1= require('./sub1');
var sub2 = require('./sub2');
sub1.use(sub2);
router.use('/sub1:id', sub1);
app.listen(PORT, function(){
console.log('listening on port:', PORT);
});
This wouldn't be very difficult to maintain. Let me know if this isn't what you are looking for.
So you have
/routes/sub1
/routes/sub1/:id
/routes/sub2
/routes/sub2/:id
if i understand correctly, you want these routes:
/routes/sub1/sub2
/routes/sub1/sub2/:id
/routes/sub1/:id/sub2
/routes/sub1/:id/sub2/:id
So your solution can be something similar to this:
var express = require('express'),
app = express();
routerA = express.Router(),
routerB = require('./sub2');
routerA.get('/', function(req, res) { console.log('sub1 base') });
//The next 2 mounts order matters, cause they can overlap each other
routerA.use('/sub2', routerB); //routes/sub1/sub2 + routes/sub1/sub2/:id
routerA.get('/:id', function(req, res) { console.log('sub1 id:' + req.params.id) });
routerA.use('/:id/sub2', routerB); //routes/sub1/:id/sub2 + routes/sub1/:id/sub2/:id
app.use('/routes', routerA);
app.listen(3000);
It is up to you to decide that will there be a sub1-id called 'sub2'
Cause any request to the resource with id 'sub2' will be taken a way by routerB
The way I would recommend to write your node.js routes would be to have a routes.js file, which will contain all your routes.
You can then put, in your routes.js file your route for sub1, like so:
const router = require('express').Router();
const sub1 = require('./sub1');
router.use('/sub1', sub1);
module.exports = router;
I would then, in sub1.js, put your sub2 route, like so:
const subOneRouter = require('express').Router();
subOneRouter.get('/', function(req, res){
res.json({route: 'sub1-base'});
});
subOneRouter.get('/:id', function(req, res){
res.json({'route': 'sub1-base', 'id': req.params.id});
});
const sub2 = require('./sub2');
subOneRouter.use('/:id/sub2);
module.exports = subOneRouter;
This will make all your sub1 routes have the prefix of '/sub1' and all your sub2 prefixes, inside sub1, have a prefix of '/:id/sub2'. You can then feel free to put whatever routes inside sub2 that you wish.
Using this setup means that if you ever want to change the prefix for sub1, or sub2, you just change it in one place.

Express route not being recognized. Responds with 'Cannot GET'

app.js
var express = require("express");
var app = express();
var path = require('path');
var db = require('./db');
var bodyParser = require('body-parser');
app.listen(80);
app.set('view engine', 'jade');
app.set('views', "./views");
// app.get('/', _GetMainPage);
// app.get('/sites', _GetSites);
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({ extended: true })); // Support encoded bodies
app.use(bodyParser.json()); // Support json encoded bodies
app.use(require('./controllers'));
./controllers/index.js
var express = require('express');
var router = express.Router();
router.use('/', require('./sites'));
router.use('/site', require('./site'));
module.exports = router;
./controllers/sites.js
var express = require('express');
var router = express.Router();
var site = require('../models/site');
router.get('/', function(req, res) {
site.getAll(function(err, rows){
if(err) {
res.send(err);
return;
}
res.render('sites', { sites : rows });
});
});
./controllers/site.js
var express = require('express');
var router = express.Router();
var site = require('../models/site');
router.get('/site', function(req, res) {
// console.log("get /site received. req.body: " + req.body);
res.render('site', {
site: {
name : req.params.name
}
});
});
module.exports = router;
When I request localhost/site I get a response saying:
Cannot GET /site
localhost/ works perfectly
I have been looking at this for a while and can't find the problem yet. If there is anything I can add, let me know. Thanks.
Thank you to the person that commented with the answer:
What happens if you navigate to /site/site? Your site.js route is relative to the route you provided in use. So it should be router.get('/' ... not router.get('/site' ...
The ./controllers/site route is already being routed to /site. On top of this I was calling router.get('/site', ...). This means it was actually routing to /site/site.
The solution is to just use router.get('/', ...) in the site.js file instead.
This really helped me, thank you.
Basically, the root path in the sub-app is defined in your core app where you mount it via the app.use() method.
the best example I can find from app.mountpath docs is here:
https://expressjs.com/en/4x/api.html#express.router
The app.mountpath property contains one or more path patterns on which a sub-app was mounted.
var express = require('express');
var app = express(); // the main app
var admin = express(); // the sub app
admin.get('/', function (req, res) {
console.log(admin.mountpath); // /admin
res.send('Admin Homepage');
});
app.use('/admin', admin); // mount the sub app
It is similar to the baseUrl property of the req object, except
req.baseUrl returns the matched URL path, instead of the matched
patterns.
If a sub-app is mounted on multiple path patterns, app.mountpath
returns the list of patterns it is mounted on, as shown in the
following example.
var admin = express();
admin.get('/', function (req, res) {
console.log(admin.mountpath); // [ '/adm*n', '/manager' ]
res.send('Admin Homepage');
});
var secret = express();
secret.get('/', function (req, res) {
console.log(secret.mountpath); // /secr*t
res.send('Admin Secret');
});
admin.use('/secr*t', secret); // load the 'secret' router on '/secr*t', on the 'admin' sub app
app.use(['/adm*n', '/manager'], admin); // load the 'admin' router on '/adm*n' and '/manager', on the parent app

Breaking out express routes into separate files

I have tried every answer I've found on s/o, and I'm sure I must be missing something. What doesn't error on me instead gives me a 404. I tried answers from Organize routes in Node.js, strongloop's route-separation pattern, the answers from How to include route handlers in multiple files in Express?, hit similar errors as in Router.use requires middleware function? but none of those answers worked, either. The answer for Unable to Split Routes into Separate Files in Express 4.0 doesn't error, but also 404s. It seems like each answer has a different syntax and style, and maybe it's that I'm mixing and matching incorrectly?
Right now my /routes/persons.js has this pattern:
var express = require('express');
var persons = express.Router();
persons.route('/persons/:user_id')
.put(function (req, res, next) {
// etc
});
module.exports = persons;
In my server.js file, I've got:
var persons = require('./routes/persons');
app.use('/persons', persons);
This combination doesn't throw errors, but it also doesn't do anything. I've tried adding the endpoint to server.js lines:
var persons = require('./routes/persons');
app.get('/persons/:user_id', persons.addpersons);
and stripping persons.js down to just export functions:
exports.addpersons = function (req, res, next) {
var list = req.body;
// etc
}
Plus variations like wrapping the whole person.js file in module.exports = function(), sticking module.exports = router at the end, using app instead of router, etc.
What am I overlooking? Should I be adding some other middleware, rearranging how I call the endpoint, using app, or sticking with router.route? What are the most likely culprits when there's no error but the endpoint is still 404'ing?
many thanks in advance!
============= EDITED TO INCLUDE SERVER.JS =============
Since it's clear something is set wrong, somewhere, here's my server.js file:
var express = require('express');
var app = express();
var methodOverride = require('method-override');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var router = express.Router();
var jwt = require('jsonwebtoken');
var config = require('./config');
var nodemailer = require('nodemailer');
var bcrypt = require('bcrypt-nodejs');
var crypto = require('crypto');
var async = require('async');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'email#gmail.com',
pass: 'password'
}
});
// I don't know if both are necessary, used multiple conflicting tutorials
app.use(require('express-session')({
secret: 'secret',
resave: false,
saveUninitialized: false
}));
app.set('superSecret', config.secret);
var Schema = mongoose.Schema,
Person = require('./models/person.js'),
User = require('./models/user.js'),
Event = require('./models/event.js');
var port = process.env.PORT || 8080;
mongoose.connect(config.database);
app.use(bodyParser.json());
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('X-HTTP-Method-Override'));
app.use(express.static(__dirname + '/public'));
// routes go here
app.use('/api', router);
app.listen(port);
console.log('gogogo port ' + port);
I have no idea where else I might look for why including routes requires such a break in the usual pattern. My config files? My procfile? Those are the only other files sitting on the server, not counting /models and /routes.
The key here is to understand what app.use() does to your req object (in particular to req.path), how app.get() and friends are different, and how Express wraps path-to-regexp (its internal path matching module) to handle routes.
1) app.use(path, middleware) mounts the middleware. Inside the mounted middleware/router, req.path is relative to the mount path. Only the beginning of the request path needs to match, so /foo will work for requests at /foo (relative path will be /), /foo/bar (relative path is /bar), etc.
app.use(function (req, res, next) {
console.log('Main: %s %s', req.method, req.path);
next();
});
app.use('/foo', function (req, res) {
console.log('In /foo: %s %s', req.method, req.path);
res.send('Got there');
});
Try running the setup above, navigate to localhost/foo and see the following logs:
Main: GET /foo
In /foo: GET /
2) app.get(path, middleware), app.post(path, middleware) etc. do not mount the target middlewares, so req.path is preserved. req.path must match the whole pattern you defined your route with, so /foo will only work for /foo requests.
app.use(function (req, res, next) {
console.log('Main: %s %s', req.method, req.path);
next();
});
app.get('/foo', function (req, res) {
console.log('In /foo: %s %s', req.method, req.path);
res.send('Got there');
});
Navigate to localhost/foo and see :
Main: GET /foo
In /foo: GET /foo
3) app.route(path), as explained in the Express docs, is just a convenience to define multiple app.get(middleware), app.post(middleware) etc. sharing the same path.
Now in your case, here is a working setup:
main
var persons = require('./routes/persons');
app.use('/persons', persons);
routes/persons.js
var router = require('express').Router();
router.route('/:user_id')
.post(function (req, res) {
// handle potato data
})
.get(function (req, res) {
// get and send potato data
});
module.exports = router;
This is convenient as you only have to set the /persons entry point once in your main file, so you can easily update it later on if needed (you could also import that path value from a config file, from your router object or whatever, Node is pretty flexible in this regard). The persons router itself takes care of its business controllers, regardless of where it is exactly mounted at.
I FIGURED IT OUT!
Of course, this might be the totally wrong way to go about it (pls tell me if so) but it WORKS.
in my server.js file, I have:
var persons = require('./routes/persons');
router.get('/persons/:user_id', persons);
router.post('/persons/:user_id', persons);
and my persons.js file now looks like this:
var mongoose = require('mongoose');
var express = require('express');
var router = express.Router();
var Schema = mongoose.Schema,
Person = require('../models/person.js');
router.post('/persons/:user_id', function (req, res) {
var potatoBag = req.body;
Person.collection.insert(potatoBag, function onInsert(err, potatoBag) {
if (err) {
return res.json(err);
} else {
res.status(200).end();
}
});
});
router.get('/persons/:user_id', function(req, res) {
var id = req.params.user_id;
Person.find({'user_id':id},function(err, person) {
if (err)
return res.json(err);
res.send(person);
});
});
module.exports = router;
This seems like more overhead than most of the examples, but maybe it's because of a) using router.route and b) using imported schemas? I also had (req, res, next) in there, and it threw fits until I removed the next pieces. Probably still a bit awkward, but hey, it's working. Thanks for the help, everyone!
instead of
persons.route('/persons/:user_id')
.put(function (req, res, next) {
// etc
});
do:
persons.put('/persons/:user_id',function (req, res, next) {
// etc
});

Node JS App Better design and seperation

I've created a node application with express. I try to separate the following layers which will give me the ability to test the application with unit testing...
The problem is that I don't know how to call to the router.js file which will stops in the post/get/delete application.
The server.js file looks as follows
http = require('http'),
app = require('./app')(),
http.createServer(app).listen(app.get('port'), function (err) {
console.log('Express server listening on port ' + app.get('port'));
});
This is the app.js file
var express = require('express'),
logger = require('morgan'),
bodyParser = require('body-parser'),
routesApp = require('./ro/route');
module.exports = function () {
var app = express();
app.set('port', process.env.PORT || 3005);
app.use(logger('dev'));
app.use(function (req, res, next) {
res.set('APP', 'User app');
next();
});
app.use(bodyParser.json());
app.use(routesApp);
return app;
};
This is the router.js, which will route the call to other module according to the http type like post/delete/get etc...
var handleGet = require('../controller/handleGet');
var handlePost = require('../controller/handlePost');
var express = require('express');
module.exports = function (app) {
var appRoute = express.Router();
app.use(appRoute);
appRoute.route('*')
.post(function (req, res) {
handlePost(req, res);
})
.get(function (req, res) {
handleGet(req, res)
})
Currently I've two questions:
How to make it work since when in debug It dump in
app.use(appRoute); on the router.js file?
The error is TypeError: undefined is not a function
Is it good way to structure the node app like in my post? I want to seperate all this layers like SOC, I'm fairly new to node and express and I try to build it to be modular and testable...
How to make it work since when in debug It dump in app.use(appRoute); on the router.js file? The error is TypeError: undefined is not a function
This fails because you don't pass app into the module when you require it in app.js, you would need to do something like
app.use(routesApp(app)); // <- this hurts my eyes :(
Is it good way to structure the node app like in my post?I want to sperate all this leyrs like SOC,I fairly new to node and express and I try to build it to be modular and testable...
Your definitely on the right track, keeping things separated is generally always a good idea. Testing is definitely one of the big pluses but it also helps with other things like maintainability & debugging.
Personally, I would make use of the bin directory for any start up script configuration
bin/www
var app = require('./app');
app.set('port', process.env.PORT || 3005);
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
This will help decouple your express app from all the environment setup. This should keep your app.js clean and only contain app-related config
app.js
var express = require('express')
, app = express()
, logger = require('morgan')
, bodyParser = require('body-parser')
, routes = require('./routes.js');
app.use(logger('dev'));
app.use(function (req, res, next) {
res.set('APP', 'User app');
next();
});
app.use(bodyParser.json());
app.use('/', routes);
...
module.exports = app;
Then finally, your routes.js should do nothing but handle your URLs
routes.js
var express = require('express')
, router = express.Router()
, handleGet = require('../controller/handleGet')
, handlePost = require('../controller/handlePost');
router.get('/', handleGet);
router.post('/', handlePost);
...
module.exports = router;

Categories

Resources