Accept and parsing request in expressjs - node.js

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.

Related

expressjs, use regular exp to match route

I use a regular exp to match a path and route the request to pageRouter.
When I request the localhost:8000/new, the regular EXP looks not work, but I have test the EXP use /^\/(?!api$|api\/.*|resource$|resource\/.*)/.test('/new'), it return true.
What happened?
router.use('/api',apiRouter);
router.use('/resource',resourceRouter);
router.use(/^\/(?!api$|api\/.*|resource$|resource\/.*)/,pageRouter);
pageRouter.get("*",(req,resp,next)=>{let name = req.originalUrl...})
In this case, instead of regexp you just need to use the wildcard :
const express = require('express'); const app = express()
app.get('/api', function(req, res){ res.send('API·Router') })
app.get('/resource', function(req, res){ res.send('RESOURCE·Router') })
app.get('/*', function(req, res){ res.send('[*] PAGE.Router') })
app.listen(3000)
Its important to define all the other routes before the wildcard '/*'
WHY? : If your first route is the wildcard, it will trap all the requests
Detecting Paths using Wildcard
app.get('/*', function (req, res) {
var paths = req.path.split("/")
if(paths[1].length==0){
res.send('[/] Page.Root')
}else if(paths[1]=='portal'){
if(paths[2]){ res.send('[*] PAGE.Router : '+paths[2]) }
else{ res.send('[*] PAGE.Router : '+paths[1]) }
}else{ res.send('[404] PATH : '+paths[1]+' not found!') }
});
Using an array :
If you have a specific list of routes that you want to use for pageRouter you can always group them inside an array for the first argument of the app.get() handler :
const pageRoutes = ['en/page','es/pagina','dk/side','jp/頁']
app.get(pageRoutes, function(req, res){ res.send('[*] PAGE.Router') })
It seems OP is trying to exclude /api and /resource for pageRouter by regular expression. However, it's not needed. As long as /api and /resource router are defined before pageRouter, they will be triggered first, and won't go though pageRouter any more.
Just define /api and /resource before pageRouter, and then use router.use('/', pageRouter);, so that all URL except /api and /resource will be listened by pageRouter.
Here is the example code. I've verified and confirmed that HTTP request to /resource won't go through pageRouter.
Files:
./app.js
./routes.js
./pageRouter.js
./resourceRouter.js
For ./app.js:
const express = require('express');
const app = express();
const routes = require('./routes');
app.use('/', routes);
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
For ./routes.js:
var express = require('express');
var router = express.Router();
const resourceRouter = require('./resourceRouter');
const pageRouter = require('./pageRouter');
router.use('/resource',resourceRouter);
router.use('/', pageRouter);
module.exports = router;
For ./resourceRouter.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('respond with resource');
});
module.exports = router;
For ./pageRouter.js:
var express = require('express');
var router = express.Router();
router.get('/resource', function(req, res, next) {
console.log('hit /resource in pageRouter');
res.send('respond with page by /resource');
});
router.get('/new-page', function(req, res, next) {
res.send('respond with page by /new-page');
});
router.get('*', function(req, res, next) {
console.log('hit * in pageRouter');
res.send('respond with page by *');
});
module.exports = router;
After running ./app.js, the HTTP GET request for /resource would never hit ./pageRouter.js.
I got an answer from the expressjs's github,the link is https://github.com/expressjs/express/issues/3404
It is not just a matter of does the regular expression match the
input, but since .use needs to strip down the matched path, it expects
your match to stop before a / character to cut on.

Dynamically adding a route with Express using frontend parameter

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}.

How do I separate one route in a different module and "require it" in index.js?

I have a Node/Express application, and I need to move one route to a different file.
This is my index.js.
'use strict';
let express = require('express'),
bodyParser = require('body-parser'),
logger = require('morgan'),
_ = require('lodash');
let app = express();
app.use(logger('combined'));
app.use(express.static('public'));
app.use(bodyParser.json({}));
app.use(bodyParser.urlencoded({ extended: true }));
console.log("I am open");
let users = [///stuff ];
let games = [];
// Handle POST to create a user session
app.post('/v1/session', function(req, res) {
// do things
});
// Handle POST to create a new user account
app.post('/v1/user', function(req, res) {
// do things
});
// Handle GET to fetch user information
app.get('/v1/user/:username', function(req, res) {
// do things
});
// Handle POST to create a new game
app.post('/v1/game', function(req, res) {
// do things
});
// Handle GET to fetch game information
app.get('/v1/game/:id', function(req, res) {
// do things
});
let server = app.listen(8080, function () {
console.log('Example app listening on ' + server.address().port);
});
I want to have a new server side route (GET /v1/game/shuffle?jokers=false), but I don't quite understand how to separate it into a new file, perhaps in ./routes/shuffleRoute.js.
I read through this one, but I don't quite understand it due to the file names being similar. How to separate routes on Node.js and Express 4?
And I'm just trying to separate one route, not all.
Create a file in routes, called shuffleRoute.js. In this file write something like
var express = require('express');
var router = express.Router();
router.get("/shuffle", function (req, res, next) {
// magic here
});
router.get("/:id", function (req, res, next) {
// more magic here
});
module.exports = router;
and in your server.js
app.get("/v1/games", require("./routes/shuffleRoute.js"));
It's important to node that in your case, as you are using a param for id, your shuffle route needs to come before the :id route. Otherwise express will interpret shuffle as an id (which will hopefully not be an id)
If you only want to "outsource" "/v1/games/shuffle, make sure that comes before app.get("/v1/games/:id"...) in your server.js file

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.

Resources