I would like to know how to do routing for translation url in nodejs express
I have following routes in app.js, I would like to know how to do in a better way, lets say if have more than 5 languages , url will vary according to language but go to same route.
How to do in express nodejs.
app.js
app.use(/^\/(en|de)/, langRouter);
app.use(/^\/(en|de)\/((all-services-from|hui-kuan-cong)-(.+)-(to|zhi)-(.+))/, serviceRouter);
app.use('/:lang/route-services-services/:pr', aboutRouter);
app.use('/:lang/ain-jian-wen-ti/:pr', aboutRouter);
frontend urls,
will pass to langRouter
/en
/de
will pass to serviceRouter
/en/all-services-from-sin-to-mal
/de/hui-kuan-cong-sin-zhi-mal
will pass to aboutRouter
/en/route-services-services/fund
/de/ain-jian-wen-ti/fund
app.use(/:locale*, checkLangRouter);
app.use(/:locale/, langRouter);
app.use(/:locale/:slug/, serviceRouter)
app.use('/:locale/:slug/:pr', aboutRouter);
The first is the middleware to check if the locale is available..
In each router, check the slug depending of the locale. If it's not corresponding, just call the next() method...
//aboutRouter.js
module.exports = (req, res, next) => {
const locale = req.params.locale;
const slug = req.params.slug;
const myMapping = {
en: 'about',
fr: 'a-propos',
it: 'attorno'
};
if (myMapping[locale] !== slug) {
// It's not the about route
return next();
}
};
In this case, a conceil will be to export the mapping in another file to make it readable...
Related
I am new to express and node, I working on a task where I want to add some json data to middleware request, here is the approach I am following:
In my middleware I want to add some details to request like current date and time and then extract the URL path. Here is the code I came up with:
var express = require('express');
var app = express();
module.exports = app.use('/some-url', function(req, res, next) {
let logdetails = {
id: "some-id",
datetime: Date.now(),
path: '/path-in-url'
}
req.logdetails= logdetails;
next();
} );
I am using module.exports so it this function is exported. But it is giving errors. Also what is the correct way to access the URL path, for example if URL is /users/john then I want to extract /john and my middleware should be applied only when URL starts with /users.
Also what is the correct way to access the URL path, for example if
URL is /users/john then I want to extract /john
If your request url is /users/john then req.path will give you the path of the request url, i.e. /users/john. To extract john, you can use named route parameters and define your route as /users/:name. After using named route parameter in your route, if your request url is /users/john, req.params.name will give you the route parameter, i.e. john. For more details, take a look at req.params on express docs
and my middleware should be applied only when URL starts with /users
following middleware will only run when request path is /users
app.use('/users', (req, res, next) => {
...
}
If you want the middleware then just export the middleware function. Not the Whole app.use part. I think app.use returns an Express object. And :param in your url will make sure that you can access that parameter. You can check out more about path patterns here
middleware.js
module.exports = function(req, res, next) {
let logdetails = {
id: "some-id",
datetime: Date.now(),
path: '/path-in-url'
}
req.logdetails= logdetails;
next();
}
Your other main.js file:
const express = require('express');
const app = express();
const middleWare = require('./middleware')
app.use('/users/:name', middleWare, (req, res)=>{
//you can access logDetails
// and the name
const name = req.params.name;//This will be john for /users/john
const logDetails = req.logdetails;
})
req.originalUrl returns the url path like shown below
// GET /search?q=something
console.dir(req.originalUrl)
// => '/search?q=something'
source: https://expressjs.com/en/api.html
Similarly, get the URL path and split the string accordingly and apply the condition you need.
Here if your originalPath is /users/john then
const result = "/users/john".split("/")
would result in ["", "users", "john"]
Check if the result[1]==="users" and write your condition in the middleware.
You don't have to export the middle ware.
middleware.js
module.exports = {
handler: (req, res, next) => {
const userName = req.params.name;
// add payload to request
next();
}
}
app.js
middleware = require("middleware");
app.use('/users/:name', middleware.handler);
Concerning URL path access you could get access using request params, e.g
app.use('/users/:name', (req, res, next) => {
const userName = req.params.name;
// add payload to request
next();
});
1. Register your specific URL - `/users/:name`, where `:name` is dynamic params e.g *john*
2. Grab params in the callback
i have simple question , i am new in Next.JS
we have a project and my web application manage routes in BackEnd with Next JS
now my problem is here , i want use React-Router-dom in one section
forexample before im working with Laravel and React
in Laravel I set My Route like This
Route::get('/reactPage/*' ...)
and then use Clien route with react
but i dont know how handle this with Next JS
( more details => for example i want user click to some link after that user see a page with some link inside of them , if user click that link , react-router-dom handle route and no any request send to Server )
I would recommend using the Next router. You do need to create a custom server in order to overload the default Next routing, but its a trivial task:
// 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 define routes, which I do in the routes.js file:
// routes.js
const nextRoutes = require('next-routes');
const routes = (module.exports = nextRoutes());
routes
.add('landing', '/')
.add('profile', '/profile', 'profile');
I have an Express application with a router, here is the example of the router:
const router = require('express-promise-router')();
const users = require('./users');
const validate = require('./validate');
router.get('/users', users.list);
router.get('/users/:id', users.get);
// other routes here
module.exports = router;
Now I want to add a middleware that validates each query, like that (this is not the working example, it's just to show the idea of what I want to accomplish):
const schemas = {
'/users': 'some validation schema',
'/users/:id': 'another validation'
}
module.exports = (req, res, next) => {
const url = req.originalUrl; // This is where I'm stuck.
if (!schemas[url]) {
// throw new error that validation failed
}
// validating somehow
if (!req.validate(schemas[url])) {
// throw new error that validation failed
}
return next();
}
And for this, I need to get the middlelware mount folder (like '/users/:id' for '/users/557'). I've tried to use req.originalUrl, but it returns the full URL path instead of the mount folder.
How can I achieve this? And if there's no way, how can I write my validation middleware another way to make it work?
Inside req.route you will get the path of API.
Check this screenshot
I want to pass through some environment variables from a Koa server to the client. In express I could do something like res.render('index', { data: 'someData' }); and then I could access data. In Koa I can't see how to do this. It mentions using context.state but I can't find any example of how to retrieve this in the client.
You can do something similar in Koa, you just need to use the right middleware. Try out koa-views if you're using one of the supported engines.
Here is a full example (this example assumes you're using Koa v1 and EJS as your templating engine):
app.js
const Koa = require('koa')
const views = require('koa-views')
const router = require('./routes')
const app = new Koa()
app.use(views(__dirname + '/views', { extension: 'ejs' }))
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000)
routes.js
const router = require('koa-router')()
router.get('/', function * () {
yield this.render('index', { title: 'Home' })
})
router.get('/about', function * () {
yield this.render('about', { title: 'About' })
})
module.exports = router
Just change the extension argument you pass to the middleware based on which templating engine you are using.
At my website.com/v2/bridge/:locationId/process endpoint, the incoming req.body looks like this:
{
choice: 'a',
data: [
{
...
},
...
]
}
I want to access a particular route depending on what the value of req.body.choice is. If req.body.choice === 'a' then I want to go on to website.com/v2/bridge/:locationId/process/choiceA with the same req being passed on.
I don't know what middleware I need to use to accomplish that. I don't know if that is even possible.
My extremely simplified routes:
// website.com/v2/bridge
const proc = require('./process');
router.use('/:locationId/process', proc);
module.exports = router;
// website.com/v2/bridge/56/process
router.use(function (req, res, next) {
// ?????????????????????????
next();
});
const choiceA = require('./choice-a');
const choiceB = require('./choice-b');
router.use('/choice-a', choiceA);
router.use('/choice-b', choiceB);
module.exports = router;
// website.com/v2/bridge/56/process/choice-a
router.post('/', function (req, res) {
res.send('I got here.');
return;
});
module.exports = router;
What middleware function do I need to include to conditionally route my request? I am trying to avoid one giant function with if statements that process different things according to the value of req.body.choice.
This will be little trickier for you...give it a try
router.use(function (req, res, next) {
req.path = "/" + "choice-"+req.body.choice
req.url = "/" + "choice-"+req.body.choice
next();
});
now it'will do the request to the end point you want
As part of finding the answer for the same question, I came across with this question, which didn't settle my mind by messing with the req.url, so here's how I got it done (I know it's a long delay, but better late than never):
When you're dealing with routers, and you want to make a condition to decide whether to use, you can do it with two ways (according to expressjs doc), and let's learn them by examples
1. Skipping between routes
function skipThisRouteMiddleware (req, res, next) {
if (true === isAmazingValidation) {
return next('route');
}
return next();
}
router.get('/user/:id',
skipThisRouteMiddleware,
getUserV1 // TBD - your old route
)
router.get('/user/:id',
getUserV2 // TBD - your new route
)
In the case above, when you have two routes, and you want to conditionally pick one of them, it can be done by specifying a middleware that makes the validation for the first route only, and when needed, it triggers next('route') which skip to the next matching route, please note that you must specify METHOD and not generally app.use()
2. Skipping between routers
// routers/index.js
const mainRouter = express.Router();
mainRouter.use(oldRouter);
mainRouter.use(newRouter);
// routers/old.js
const oldRouter = express.Router();
function canUpgradeToNewRouter (req, res, next) {
if (true === isAmazingValidation) {
return next('router'); // now it's 'router' and not 'route'
}
return next();
}
oldRouter.use(canUpgradeToNewRouter);
// routers/new.js
const newRouter = express.Router();
newRouter.use(...);
In this case, you have two different routers, and you want to conditionally pick one of them. for this case, you'll have to create a parent router (mainRouter) and two nested routers (oldRouter, newRouter).
The trick here is that the oldRouter tries to run a middleware validation that tries to "upgrade" the requester to the new shiny router, if the condition is true, it will skip the whole oldRouter, and pass the stick to the parent router mainRouter to continue matching routes to this request (the magic - next('router')), which eventually pick the upcoming newRouter
In both methods, we let the first route to make the logic and choose between itself and the others, that's a different perception (a bit)