Dynamically adding a route with Express using frontend parameter - node.js

I'm trying to build an application will allow me to take a String parameter from the frontend, and create an Express route from that. Is that possible?
var express = require('express');
var router = express.Router();
router.post('/newAPI/:name', function(req, res, next) {
var name = req.params.name;
router.get('/'+name, function(req, res, next) {
res.send({"name":""+name});
});
});
With this, would calling localhost:3000/newApi/bob create a new route localhost:3000/bob that returns {"name":"bob"}?

It will work, unless you restart the application.
Also, just use {"name": name}.

Related

Express call GET method within route from another route [duplicate]

This question already has answers here:
Calling Express Route internally from inside NodeJS
(5 answers)
Closed 3 years ago.
I have multiple routes. How can I get the data from the user's route (GET method), by calling it within the GET method of the group's route? What is the best way of doing this?
My app.js looks like this:
var express = require('express');
var routes = require('./routes/index');
var users = require('./routes/users');
var groups = require('./routes/groups');
var app = express();
app.use('/', routes);
app.use('/users', users);
app.use('/groups', groups);
module.exports = app;
app.listen(3000);
Then I have another file routes/users.js:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('GET ON THE users!');
});
module.exports = router;
And another route routes/groups.js:
var express = require('express');
var router = express.Router();
var otherRouter = require('./users')
/* GET groups listing. */
router.get('/', function(req, res, next) {
// call the get on users and retrieve all data from that request
res.send('GET for the groups');
});
module.exports = router;
You shouldn't use routing for that. Just call the function responsible for retrieving the users from the GET groups route and do what you need with that data. The way you propose is much more expensive because you will have to make a http call.
For simplicity I'm assuming that your logic is synchronous and data stored in data/users.js:
var data = [{id:1, name: "one"},{id: 2, name: "two"}];
module.exports = function(){
return data;
};
in routes/users.js:
var express = require('express');
var router = express.Router();
var getUsers = required('./../data/users');
router.get('/', function(req, res, next) {
res.send(getUsers());
});
in routes/groups.js:
var express = require('express');
var router = express.Router();
var otherRouter = require('./users')
var getUsers = require('./.../data/users');
router.get('/', function(req, res, next) {
var users = getUsers();
//do some logic to get groups based on users variable value
res.send('GET for the groups');
});
I consider what was being explained "forwarding", and it's quite useful, and available in other frameworks, in other languages.
Additionally, as a "forward" it does not have any overhead from a subsequent HTTP response.
In the case of Express, the following is available in version 4.X. Possibly other versions, but I have not checked.
var app = express()
function myRoute(req, res, next) {
return res.send('ok')
}
function home(req, res, next) {
req.url = '/some/other/path'
// below is the code to handle the "forward".
// if we want to change the method: req.method = 'POST'
return app._router.handle(req, res, next)
}
app.get('/some/other/path', myRoute)
app.get('/', home)
You can use run-middleware module exactly for that
app.runMiddleware('/pathForRoute',{method:'post'},function(responseCode,body,headers){
// Your code here
})
More info:
Module page in Github & NPM;
Examples of use run-middleware module
Disclosure: I am the maintainer & first developer of this module.
For people coming here from google. If you need to hit one or more of your routes and skip the http request you can also use supertest.
const request = require("supertest");
app.get("/usersAndGroups", async function(req, res) {
const client = request(req.app);
const users = await client.get("/users");
const groups = await client.get("/groups");
res.json({
users: users.body,
groups: groups.body
});
});
You can also run them concurrently with Promise.all
I've made a dedicated middleware for this uest, see my detailed answer here: https://stackoverflow.com/a/59514893/133327

Create nodejs express 4 route on runtime

I am trying to create a route on runtime. I am trying to create a flat url structure so if we add an article it will create a slug for it and will create a new route.
I use express 4 new router function
app.js
var express = require('express');
var routes = require('./routes.js');
app.use('/', routes);
var server = http.createServer(app).listen(app.get('port'));
routes.js
var express = require('express');
var router = express.Router();
router.get('/new' ,site.new);
module.exports = router;
I tried creating a function in the router and calling it from the app.js also creating a function in the router while sharing the app instance accross the files
module.exports = app;
and calling it
var app = require("./app.js");
It doesnt seem to work any other idea ?
update:
I have a file called helpers.js and i added the following function
module.exports={
addRoute:function(){
var express = require('express');
var router = express.Router();
var app = require('../app.js');
var routes = require('../routes.js');
router.get('/book', function (req, res) {
res.send('Hello World!');
});
app.use('/book', router);
},
I end up doing that
addRoute:function(){
var express = require('express');
var router = express.Router();
var routes = require('../routes.js');
var app = require('../start-freedom1.js');
router.get('/book' ,function (req, res, next) {
res.send({"data":"kaki","values":"","errors":""});
});
for(var layer in app._router.stack){
if(app._router.stack[layer].name=="router"){
app._router.stack[layer].handle.stack.splice(0, 0, router.stack[0]);
console.log(app._router.stack[layer].handle.stack)
break;
}
}
// / app.use('/', routes);
},
the problem that i had router.get("*"..... at the end of the rout file so i always saw 404
I think that what you are looking for is passing parameters in the URL which you can extract and then use to do some processing. You can do something like below:
app.get('/article/:article_id', function(req, res){
art_id = req.params.article_id;
//query database using art_id
}
If you want to use query parameters instead (with "...../article?id=234") then you would have to use req.query. Have a look at the following page http://expressjs.com/en/api.html#req.params.
Request parameters are considered best practice as they are more readable and are also SEO friendly. You can edit your model to store the article slug as a field but should be unique, that way they can be used to query your DB.

Express routing on root "/" doesn't work in app.get

I've been having this issue where for some reason the Express route doesn't see my root get function. I've declared my app.js this way:
var index = require('./app/routes/index');
var app = express();
app.use('/', index);
Then in my index.js I have my definition this way:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
console.log('Enter root.');
});
router.get('/something', function(req, res, next) {
console.log('Enter something.');
});
Express routes into '/something' just fine, but couldn't see '/'. Anybody have an idea why it doesn't work? Thanks.
Modified based on new info:
If you're getting a 304 status back in the browser, that's because the browser has cached the GET request and the server is telling the browser that the page has not been changed so the browser can just use the cached copy.
You can make the page uncacheable by changing the headers the server sends with the request.
See Cache Control for Dynamic Data Express.JS and NodeJS/express: Cache and 304 status code and Nodejs Express framework caching for more info.
You show no exports in index.js so this line:
var index = require('./app/routes/index');
does not accomplish anything. index is an empty object and thus this:
app.use('/', index);
doesn't do anything and, in fact, may even cause an error.
Perhaps what you want is this:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
console.log('Enter root.');
});
router.get('/something', function(req, res, next) {
console.log('Enter something.');
});
// export your router
module.exports = router;
Then, index in your other file will be the router.

Combine routes from multiple files in ExpressJS?

What is the best way to combine routes from two files so Express Router will handle them at the same level? I'm thinking of something like this:
Default Routes File
This file would be generated and overwritten every time the generator runs:
var express = require('express'),
router = express.Router(),
custom = require('./custom.routes');
router.get('/', function (req, res) {
});
router.post('/', function (req, res) {
});
router.put('/', function (req, res) {
});
router.use('/', custom);
module.exports = router;
Custom Routes File
This file would only be generated the first time and would never be overwritten.
var express = require('express'),
router = express.Router();
router.post('/custom-method', function (req, res) {
});
module.exports = router;
Parent Route File
This file is generated and overwritten constantly. It is responsible for providing the top level api route:
var express = require('express'),
apiRouter = express.Router();
var widgetRouter = require('./widget.routes');
apiRouter.use('/widgets', widgetRouter);
var sprocketRouter = require('./sprocket.routes');
apiRouter.use('/sprockets', sprocketRouter);
module.exports = apiRouter;
The obvious goal is to allow the developer to customize the routes and know his work will be safe even when the generator is run again.
router.use() does not necessarily need to take you deeper in the tree. You could just add the following line before the exports of the first file.
router.use('/', require('./routes.custom.js'));
With this you can also remove the wrapper from the custom file.

Accept and parsing request in expressjs

I am using expressjs and I want get a request object comes form this url
http://www.thedomain.com/membername/category/item?item=abc
in server side. I am trying to use
// app.js
var express = require('express');
var routes = require('./routes/index');
var app = express();
app.use('/*', routes);
In './routes/index':
//'./routes/index''./routes/index'
var express = require('express');
var config = require('../config');
var router = express.Router();
var url = require('url');
/* GET category page. */
router.get('/category', function(req, res, next) {
console.log(' pathname: ',url.parse(req.url).pathname)
res.render('index', {
title: url.parse(req.url).pathname
});
});
Actually, I have no way to get value of membername
I want to know how could I get value of membername before process item value in query string in the category router. I also want to know how to write a regex that accept all value of membername for the router which stay on the front of the category router as a pre-process module.
Thank for all your comment and answer
req.get('/:memberName/category/item', function(req, res, next) {
// do whatever you want with req.prams.memberName here...
next();
});
req.get('/:memberName/category/item', function(req, res, next) {
// now do whatever you want with req.query.item here...
});
Since you suggest you want to restrict only to letters and numbers (and perhaps _ too), use a regular expression:
req.get('/\w+/category/item', function(req, res, next) {
// Access membername via req.params[0]
});
I've had bad luck with Express routes and regular expressions, but I believe that problem has been fixed in Express 4.0.

Resources