expressJS routing issue, simple stuff not resolving - express

I've recently moved all my route code into separate files, but now my route resolution is spotty. Here's a simple example -
My app.js
const express = require('express');
const app = express();
var dataLoader = require('./routes/dataLoader');
app.all( '/api/load', dataLoader);
My dataLoader.js
const express = require('express');
const router = express.Router();
router.get('/api/load', (req, res) => {
res.send('Hello Loader...');
});
router.get('/api/load/bob', (req, res) => {
res.send('Hello Loader - Bob...');
});
router.get('/api/load/jim', (req, res) => {
res.send('Hello Loader - Jim...');
});
module.exports = router;
/api/load works fine, while /api/load/jim and /api/load/bob both result in:
Cannot GET /api/load/jim (or Cannot GET /api/load/bob, respectively)
I user app.all() instead of app.use() because I was having an issue resolving the main path "/api/load", the use of all seemed to fix that, but now I am not sure.
"engines": {
"node": "^8.9.1"
},
"dependencies": {
"bluebird": "^3.5.1",
"body-parser": "^1.15.1",
"express": "^4.13.4",
"mongoose": "4.9.8"
}
any suggestions?

When you do this:
app.all( '/api/load', dataLoader);
And, then in the dataLoader router, you define routes like this:
router.get('/api/load', (req, res) => {
res.send('Hello Loader...');
});
What you're actually doing is defining a route for api/load/api/load which is likely not what you want. The paths are cumulative.
The app.use() statement should have whatever common prefix applies to your entire router and then the paths on the router itself should be relative to that. In addition, you should use using app.use(), not app.all() for a router.
So, in your case, change the dataLoader router to this:
// whole router is configured at /api/loader
const router = require('express').Router();
router.get('/', (req, res) => {
res.send('Hello Loader...');
});
router.get('/bob', (req, res) => {
res.send('Hello Loader - Bob...');
});
router.get('/jim', (req, res) => {
res.send('Hello Loader - Jim...');
});
module.exports = router;

Related

Express + body-parser + Postman: failing to parse POST body

As you can see in the code and the attached screenshot, my body is always sent empty, and I have no idea why. Would love some help.
Versions:
"body-parser": "^1.20.1",
"express": "^4.18.2"
Code:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.get("/blockchain", function (req, res) {});
app.post("/transaction", function (req, res) {
console.log(req.body);
console.log(req.body.amount);
res.sendStatus(200);
});
app.get("/mine", function (req, res) {});
app.listen(3000, function () {
console.log("Listening on port 3000...");
});
Screenshot:

node axios as middleware

I am trying to construct a middleware and then use it within the app.get route.
I know it's looks very "pioneer" but i am learning.... How can io get it to work?
const BooksMiddle = async (req, res, next) => {
axios
.get(`https://www.googleapis.com/books/v1/volumes/? q=${term}&keyes&key=${process.env.GBOOKSKEY}`)
.then((result) => {
const data = result.data;
const books = data.items;
return books;
});
next();
}
module.exports = textMiddle;
app.get("/", textMiddle, (req, res, next) => {
res.render('index');
});
If the point of this middleware is to get some book data and make that available for your template rendering, then you can put that data into res.locals where templates called from res.render() will automatically look for data:
const bookMiddle = async (req, res, next) => {
axios
.get(`https://www.googleapis.com/books/v1/volumes/?q=${term}&keyes&key=${process.env.GBOOKSKEY}`)
.then((result) => {
res.locals.books = result.data.items;
next();
}).catch(next);
}
module.exports = bookMiddle;
And, then after you import bookMiddle, you can use it like this:
app.get("/", bookMiddle, (req, res, next) => {
res.render('index');
});
If you refer to the books data structure in your template, the template engine will look in res.locals.books for that data (where the middleware puts the data).

Not sure how to get express routing to work

I have a index.js file with the following code...
const express = require('express');
const app = express();
app.use(express.json({ extended: false }));
app.use('/api/users/', require('./users/routes'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on PORT ${PORT}`));
and a routes.js file with the following code...
const express = require('express');
const router = express.Router();
router.get('test', (req, res) => {
console.log('im here!')
res.send('hello from test route!');
});
module.exports = router;
my file structure is...
server/
users/
routes.js
index.js
I am able to start the server with no issues, however, if I try to go to the route /api/users/test it does not work and says cannot get that route.
For some reason when I am creating files with the .js extension a .jsx icon comes up. I am using vscode and feel that this might be the issue but I don't know how to fix it?
As an update in my routes file...
router.get('test', (req, res) => {});
needs to change to the following...
router.get('/test', (req, res) => {});
and in my index.js file
app.use('/api/users', require('./users/routes'));
basically, adding the slash before the test and taking away the slash after users.
I do not know why that would be an issue but it now works.
In routes.js:
router
.get ('/test',(req, res) => {
console.log('im here!')
res.send('hello from test route!');
});
You just forgot the slash in front of your route.
You should now see your response # http://localhost:5000/api/users/test.

Using Express Router with Next.js

I'm trying to use the Express Router with Next.js using their custom-express-server example as my boilerplate. The only difference is that I'm trying to define the routes externally on routes/router.js as follows:
Code in server.js:
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const routes = require('./routes/router')
app.prepare()
.then(() => {
const server = express()
server.use('/', routes)
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
module.exports = app;
Code in routes/router.js:
const express = require('express'),
app = require('../server.js'),
router = express.Router();
router.get('/a', (req, res) => {
return app.render(req, res, '/b', req.query)
})
router.get('/b', (req, res) => {
return app.render(req, res, '/a', req.query)
})
router.get('/posts/:id', (req, res) => {
return app.render(req, res, '/posts', { id: req.params.id })
})
module.exports = router;
At this point, even when I'm importing "app" from server.js, app is not available within router.js.
Is my logic incorrect?
If it's not, then why is app not available within router.js?
Just solved it. This issue is known as a circular dependency, and it should be avoided at all costs... unless the pattern you're using (like the boilerplate I used, I guess...) requires it.
To solve it, just export from file "A" the dependency that file "B" uses before you require file "B" on file "A".
...And that's it pretty much.
You might also try using next-routes, which I use on all of my Next project:
// server.js
const { createServer } = require('http');
const next = require('next');
const routes = require('./routes');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = routes.getRequestHandler(app);
app.prepare().then(() => {
createServer(handler).listen(port, err => {
if (err) {
throw err;
}
console.log(`> Ready on http://localhost:${port}`);
});
});
Then you can configure your routes in the routes.js file without accessing the app:
// routes.js
const nextRoutes = require('next-routes');
const routes = (module.exports = nextRoutes());
routes
.add('landing', '/')
.add('blog', '/blog', 'blog')
.add('blog-post', '/blog/:postId', 'blog')

routes in exported router not available in app

I'm trying to export a router 'Accounts' to use in my app. The 'Accounts' router has the paths '/login' (POST), '/register'(POST), 'login' (GET), and '/logout' (POST). In my index app I am using the router with the path '/account'. So the paths should be:
/account/login (POST)
/account/login (GET)
/account/register(POST)
/account/logout (GET)
But when I call these paths they aren't found by the app:
How do I get the paths in the 'accounts.js' router to work in the 'index.js' app?
My file structure is like this:
my account.js file looks like this:
const express = require('express');
const passport = require('passport');
const Account = require('../models/Account');
const Branch = require('../models/Branch')
const router = express.Router({mergeParams: true});
const registerAccount = (req, res, next) => {
//register the account
};
const createUser = (req,res) => {
//create a user in another db
}
router.post('/register',
[registerAccount, createUser]);
router.get('/login', function(req, res) {
res.json(user);
});
router.post('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect: 'account/login' }));
router.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
});
module.exports=router;
and my index.js looks like this:
// index.js
var express = require("express");
var bodyParser = require("body-parser");
var jwt = require("jwt-simple");
var auth = require("../auth/auth.js")();
var users = require("./users.js");
var cfg = require("../config.js");
const accountController = require('./account');
var app = express();
app.use(bodyParser.json());
app.use(auth.initialize());
app.use('/account',accountController);
app.get("/", function(req, res) {
res.json({
status: "My API is alive!"
});
});
app.post("/token", function(req, res) {
//some token stuff that doesn't matter here
});
module.exports = app;
For starters, you don't pass an array to a router.post(), so change this:
router.post('/register', [registerAccount, createUser]);
to this:
router.post('/register', registerAccount, createUser);
And make sure that registerAccount calls next() when it's done and wants createUser() to get called.
In the doc, for this syntax:
app.post(path, callback [, callback ...])
the brackets in [, callback] mean that parameter is optional. The brackets are not supposed to be used.