I want to access to app.routes from my controller or EJS view, but app var don't exists there.
Do you know how can I access to all the routes that I defined myself in config/routes.js?
Thank you.
PS: I'm using sails.js, based on express.js.
You can use request.app:
app.get('/foo', function (request, response, next) {
console.log(request.app.routes);
next();
});
Here is the final solution:
module.exports = {
index: function (req, res) {
return res.view({
layout: 'layout',
title: 'Trip Analyzer',
routes: req.app.routes
});
}
};
EJS view in Javascript:
console.log(<%- JSON.stringify(routes) %>);
Thanks!
Related
I want to change the URL for mobile. www.example.com to m.example.com
I use isMobile function to detect device type.
I do not know what to do for routing.
for example: m.example.com/index
please help me
in app.js
function isMobile(req, res, next) {
if ((/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(req.headers["user-agent"]))) {
res.redirect('//m.' + req.host+ req.path);
} else {
next()
}
}
app.get('/',isMobile,routes.index);
If device is a mobile,i want to run routes.mobileindex. How?
If you want to render a separate view for mobile devices in the same application then it would be pretty straigh forward. it is a just a matter of creating another view file and you can apply your separate layout and CSS style to design it.
var express = require("express");
var router = express.Router();
function isMobile(req, res, next) {
if (
/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(
req.headers["user-agent"]
)
) {
// Instead of redirecting to another view you can also render a separate
// view for mobile view e.g. res.render('mobileview');
res.redirect("/mobile/device");
} else {
next();
}
}
/* GET home page. */
router.get("/", function(req, res, next) {
res.render("index", {
title: "Express"
});
});
router.get("/device", isMobile, function(req, res, next) {
res.json("normal view is rendered");
});
router.get("/mobile/device", function(req, res, next) {
res.render("mobile");
});
module.exports = router;
I have set a redirection here but this is not the best way if you are in the same application, because you can directly hit /mobile/device view, in that case you also need a middleware or can reuse the isMobile middleware to redirect to normal view. I would rather suggest to use res.render('yourviewname')
Hope this gives you an idea to proceed futher!
Does anyone know if it's possible to get the path used to trigger the route?
For example, let's say I have this:
app.get('/user/:id', function(req, res) {});
With the following simple middleware being used
function(req, res, next) {
req.?
});
I'd want to be able to get /user/:id within the middleware, this is not req.url.
What you want is req.route.path.
For example:
app.get('/user/:id?', function(req, res){
console.log(req.route);
});
// outputs something like
{ path: '/user/:id?',
method: 'get',
callbacks: [ [Function] ],
keys: [ { name: 'id', optional: true } ],
regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
params: [ id: '12' ] }
http://expressjs.com/api.html#req.route
EDIT:
As explained in the comments, getting req.route in a middleware is difficult/hacky. The router middleware is the one that populates the req.route object, and it probably is in a lower level than the middleware you're developing.
This way, getting req.route is only possible if you hook into the router middleware to parse the req for you before it's executed by Express itself.
FWIW, two other options:
// this will only be called *after* the request has been handled
app.use(function(req, res, next) {
res.on('finish', function() {
console.log('R', req.route);
});
next();
});
// use the middleware on specific requests only
var middleware = function(req, res, next) {
console.log('R', req.route);
next();
};
app.get('/user/:id?', middleware, function(req, res) { ... });
I know this is a little late, but for later Express/Node setups req.originalUrl works just fine!
Hope this helps
This nasty trick using prototype override will help
"use strict"
var Route = require("express").Route;
module.exports = function () {
let defaultImplementation = Route.prototype.dispatch;
Route.prototype.dispatch = function handle(req, res, next) {
someMethod(req, res); //req.route is available here
defaultImplementation.call(this, req, res, next);
};
};
req.route.path will work to get the path for the given route. But if you want the complete path including the path of the parent route, use something like
let full_path = req.baseUrl+req.route.path;
Hope it helps
You can take a look at Router().stack, which has all the routes defined. In your middleware you need to manually compare the available routes with the one called to define actions.
I am working with nodejs/express. I want to do the same thing for a route, for GET and POST http requests.
I am doing this:
app.get('/', function(req, res) {
// Some code
});
app.post('/', function(req, res) {
// Same code
});
Is there a way to refactor get and post in the same callback ?
Thanks
Or you can use all, if your site doesn't use any other methods in particular:
app.all('/', handler)
This seems like a very odd requirement. If the behavior is exactly the same just specify one function to handle both:
function myHandler(req, res) {
// Some code
}
app.get('/', myHandler);
app.post('/', myHandler);
A bit old question but still facing today.
If you want to expose the api for all method with the same handler:
function sameHandler(req, res) {
// do something here
}
app.all('/', sameHandler);
If just wanna use the same route but with different handlers:
function getHandler(req, res) {
// do something here
}
function postHandler(req, res) {
// do something here
}
function deleteHandler(req, res) {
// do something here
}
app.route('/').get(getHandler).post(postHandler).delete(deleteHandler);
I've just made an Node.js app modular by splitting up data models and routes into separate files.
My routes are exported by express.Router(). In these routes I would like to import queried values from my app.js to be rendered with the templates.
How would I in the easiest way save things lets say with app.locals or req.variableName?
Since the route using express.Router() ties it together with app.js, should I be using app.params() and somehow make these values accessible?
Using globals seems like a worse idea as I'm scaling up the app. I'm not sure if best practice would be saving values to the process environment either using app.locals.valueKey = key.someValue...
Big thanks in advance to anyone
If I understand the question correctly, you want to pass a value to a later middleware:
app.js:
// Let's say it's like this in this example
var express = require('express');
var app = express();
app.use(function (req, res, next) {
var user = User.findOne({ email: 'someValue' }, function (err, user) {
// Returning a document with the keys I'm interested in
req.user = { key1: value1, key2: value2... }; // add the user to the request object
next(); // tell express to execute the next middleware
});
});
// Here I include the route
require('./routes/public.js')(app); // I would recommend passing in the app object
/routes/public.js:
module.export = function(app) {
app.get('/', function(req, res) {
// Serving Home Page (where I want to pass in the values)
router.get('/', function (req, res) {
// Passing in the values for Swig to render
var user = req.user; // this is the object you set in the earlier middleware (in app.js)
res.render('index.html', { pagename: user.key2, ... });
});
});
});
Does anyone know if it's possible to get the path used to trigger the route?
For example, let's say I have this:
app.get('/user/:id', function(req, res) {});
With the following simple middleware being used
function(req, res, next) {
req.?
});
I'd want to be able to get /user/:id within the middleware, this is not req.url.
What you want is req.route.path.
For example:
app.get('/user/:id?', function(req, res){
console.log(req.route);
});
// outputs something like
{ path: '/user/:id?',
method: 'get',
callbacks: [ [Function] ],
keys: [ { name: 'id', optional: true } ],
regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
params: [ id: '12' ] }
http://expressjs.com/api.html#req.route
EDIT:
As explained in the comments, getting req.route in a middleware is difficult/hacky. The router middleware is the one that populates the req.route object, and it probably is in a lower level than the middleware you're developing.
This way, getting req.route is only possible if you hook into the router middleware to parse the req for you before it's executed by Express itself.
FWIW, two other options:
// this will only be called *after* the request has been handled
app.use(function(req, res, next) {
res.on('finish', function() {
console.log('R', req.route);
});
next();
});
// use the middleware on specific requests only
var middleware = function(req, res, next) {
console.log('R', req.route);
next();
};
app.get('/user/:id?', middleware, function(req, res) { ... });
I know this is a little late, but for later Express/Node setups req.originalUrl works just fine!
Hope this helps
This nasty trick using prototype override will help
"use strict"
var Route = require("express").Route;
module.exports = function () {
let defaultImplementation = Route.prototype.dispatch;
Route.prototype.dispatch = function handle(req, res, next) {
someMethod(req, res); //req.route is available here
defaultImplementation.call(this, req, res, next);
};
};
req.route.path will work to get the path for the given route. But if you want the complete path including the path of the parent route, use something like
let full_path = req.baseUrl+req.route.path;
Hope it helps
You can take a look at Router().stack, which has all the routes defined. In your middleware you need to manually compare the available routes with the one called to define actions.