res.render('index.html', {layout : null}) generating error - node.js

following demo project Here and blog post Here.
He is using jade engine which I don't want to use instead using Angularjs templating and routing.
Root folder is
client > js (contain all js files)
> views > partials > html files
> index.html
After changes in his code I am stuck with the below code
I am unable to send proper response.
if I use res.render('index.html', {layout : null}); than get error when refresh page
ERROR :
Error: Cannot find module 'html'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
if I use res.redirect('/') than refresh the page always send me root (/) defined in app.js.
Needed : I want to send response or not to be on the same page even if I refresh the browser.
{
path: '/*',
httpMethod: 'GET',
middleware: [function(req, res) {
var role = userRoles.public, username = '';
if(req.user) {
role = req.user.role;
username = req.user.username;
}
res.cookie('user', JSON.stringify({
'username': username,
'role': role
}));
//res.render('index.html', {layout : null});
//res.redirect('/');
}],
accessLevel: accessLevels.public
}

If you're not using a backend template language (like jade), then you want to use res.sendfile instead of res.render. Render will look for a template engine matching the extension of the file (such as .jade) and then run the file through it. In this case, it assumes there must be a rendering engine called html, but there is not. SendFile will simply transfer the file as-is with the appropriate headers.
EDIT:
I'm still not 100% sure what you're asking, but I think what you're saying is you want your wildcard route to redirect people to the homepage if they aren't logged in, but if they are, then let other routes take over.
If that is the case you just need to put in a check in your "middleware" function for the /* route.
Instead of:
function(req, res) {
res.redirect('/');
}
Use some type of conditional logic:
function (req, res, next) {
if (/* !req.cookie.something or whatever */)
res.redirect('/');
else
next(); // continue on to the next applicable (matching) route handler
}
That way you won't always get caught in the redirect loop. Obviously, the above conditional logic could be asynchronous if necessary.
I still believe res.sendfile is the correct answer to the other portion of your question, just as the github members also suggested.

Related

Node.js REST API - URI Sanitizing?

I would like to require pages in my Node.js server based on the requested URI.
However I concern that this could be a severe security issue since user can inject some malicous chars into the url, something like ../../ and reach to my root server point and reveal all of the code.
So just like throwing a bottle of water to a big fire, I have eliminated the option to send . to the request.
This is not a silverbullet, probably :)
Maybe is there some standard/best practice/guide or keypoints about URI sanitizing in REST API based on Node.js?
Edit - here the code uses the require
// app.js
app.use(require('./services/router')(app));
// router.js middleware
function router(app) {
return function(req, res, next) {
try {
// checking for . in the url
if (req.url.indexOf(".")!=-1) cast.badRequest();
// req.url.split('/')[2] should be customers, users or anything else
require('../../resources/' + req.url.split('/')[2] + '/' + req.url.split('/')[2] + '-router')(app);
next();
} catch(err) { cast.notFound(); }
}
}
module.exports = router;
// rides-router.js (this could be users-router.js or customers-router.js)
module.exports = function(app) {
// GET ride - select a ride
app.get("/v1/rides/:id", dep.verifyToken(), require('./api/v1-get-ride'));
// POST ride - insert a new ride
app.post("/v1/rides", dep.verifyToken(), require('./api/v1-set-ride'));
app.use((req, res, next) => {
cast.notFound();
});
}
You asked how to do it safer. My recommendation is that you put all the resources in an array and run all the app.use() statements with one loop that pulls the resource names from the array at server startup.
I don't like running synchronous require() during a request and I don't like loading code based on user specified characters. Both are avoided with my recommendation.
// add routes for all resources
const resourceList = ['rides', 'products', ...];
for (let r of resourceList) {
app.use(`/${r}`, require(`./resources/${r}/${r}-router`));
}
This seems like less code and 100% safe and no running of synchronous require() during a request.
Advantages:
Fully whitelisted.
No user input involved in selecting code to run.
No synchronous require() during request processing.
All routes installed at server initialization time.
Any errors in route loading (like a missing route file) occur at server startup, not during a user request.

Node express api routes for multilingual directory like url

Does any one knows an example or could explain here how node.js and express would have to route for a multilanguage site? I'm using i18n-node for translation and folder like routing ( /es/, /de/ , etc ) for different languages. This all are static routes but I also have routes like apiRoutes.route('/user/profile') using 'app' at the begining ( app.get('/app/user/profile') so please consider this in your answer so is NOT necesary route to : app.get('/es/app/user/profile') .
having 15 routes like this now:
app.get('/terms', function(req, res) {
res.render('terms',{
...
});
});
how it have to be set for routes like:
app.get('/es/terms', function(req, res) {
res.render('terms',{
...
});
});
Should I duplicate this routes and add for example a locale for
each like:
app.get('/es/terms', function(req, res) {
res.render('terms',{
...
});
});
Or Should do something like:
if cookie['lang'] && cookie['lang'] is in locales
// then redirect to /:lang/terms
else
// show default language in /terms
if req.headers["accept-language"] && req.headers["accept-language"]
// then redirect to /:lang/terms
else
//show default language in /terms
Or there is another way I should approach this that follows good practices or is better respecting standards?
Miro's Answer in :
How can I get the browser language in node.js (express.js)? says I should use app.all('*', ...
Is this all I need?, ..still, it might have a syntax error or i'm not understanding well this two parts
var rxLocal = /^\/(de|en)/i;
...
app.get(/\/(de|en)\/login/i, routes.login);
thanks in advance
You need to consider 2 things :
1. How get the local :
Accept-Language
The HTTP protocole define the Accept-Language header to manage the local. This is a normalized method. You can access it with the req.acceptsLanguages method of express.
+Normalized
+Natively support by brower
-Not easy to by passe by the end user
Path / Cookies
You can get the local from the path. In express it can be do with a parameter patter like /:local/rest/of/path and retrieve in the request object with the req.param method.
You can also get the information from the cookies with the req.cookies properties (don't forgot to set it).
Both
To increase the user experience you can mix the both method. For exemple get the default language from the HTTP header send by the browser but permite to the user to override this in you application and store this parameter in the cookies.
2. Use the local:
Each methods to get the local can be used from different way. I will
use random of them in exemple but they are all compatible.
Top level configuration.
In case of you use a template Engine and you controller can be local agnostic. You can use a middleware to get the local information and configure the render engine.
app.use('/:local' (req, res, next) => {
let localKey = req.param('local');
res.locals = // Some ingenious method to get the locales from localKey
next();
}
Check res.locals and your engine documentation.
Use it in controller.
If the local is part of the contoller process. You can get directly is value in controller.
In case of you use a complexe method to determine the final value of the local, you can also use a middleware to determine this value and enrich the request with it.
app.use((req, res, next) => {
let local = req.cookies.local;
if(!local) local = req.acceptsLanguages();
if(!local) local = 'en-US';
req.local = local;
}
Both
You can use both method too. It depend of what you need. Find the best way to get a maintainable code and avoid replication for your use case.
When you use middle where witch impact the controllers, be sure you declare them before your routes.
You can use a route parameter to get the locale from the URL, like this:
app.get('/:lang/terms', function (req, res) {
if (req.params === 'es') {
res.send('¡Hola!');
else {
res.send('Hi!');
}
});
The colon character tells Express to put whatever is between the first to slashes of the path in req.params.lang.
See express routing documentation for details.

use dynamic subdomains with nodejs

hello i am new to Nodejs. I want to use dynamic subdomains to access my API and through subdomain prefix I can manage my API data.
Suppose I gave domain like domain:3000 and sub-domain could be a.domain:3000 or b.domain:3000 or anything prefixed to domain:3000.
I used wildcard-domains. but still unable to undersatnd the flow and how to use it and allow organisation listed in DB (Consider prefix as organisation name).
I have used following code:
var wildcardSubdomains = require('wildcard-subdomains')
var checkUser = subdomain('*.localhost:3000', function(req, res,
next) {
console.log(req.session.user.valid);
if(!req.session.user.valid) {
return res.send('Permission denied.');
}
next();
});
app.use(checkUser);
I am also using angularjs and using ui.router to change my states or urls.
I used this module
npm i vhost --save
Here you can see information
http://expressjs.com/en/resources/middleware/vhost.html
wildcard-subdomains
As you can see in https://www.npmjs.com/package/wildcard-subdomains
app.use(wildcardSubdomains({
namespace: 's', // __NAMESPACE_FROM_WILDCARD_CONFIG__
www: 'false',
}))
If you follow, example, link foo.localhost:3000 Express will process this middleware
app.get('/s/foo/', function(req, res){
res.send("Meow!")
})
That is to say
app.get('/__NAMESPACE_FROM_WILDCARD_CONFIG__/__SUBDOMAIN__/', function(req, res){
res.send("Meow!")
})
You can try to write app.get('/s/:subdomain', ...

how to get id from url in express, param and query doesnt seem to work

I have a url, i'm trying to get id but none of it is working req.params nor req.query
app.get('/test/:uid', function testfn(req, res, next) {
debug('uid', req.params.uid); // gives :uid
debug('uid', req.query.uid); // gives undefined
});
I'm doing an ajax call like this
$(document).on('click', 'a.testlink', function(e) {
$.ajax({
type: "GET",
url: '/test/:uid',
success: function(var) {
console.log('success');
},
error: function() {
alert('Error occured');
}
});
return false;
});
I'm using
app.use(express.json());
app.use(express.urlencoded());
instead of body parser
Your code is working as expected: The ajax call specifies url: '/test/:uid' which is what puts :uid in req.params.uid.
Try sending something else: url: '/test/123' and req.params.uid will contain 123
Here is an example that will work. I will give step by step instructions from the start:
express myproject
cd myproject
npm install
Open app.js and add in the following somewhere in the file - maybe right before the line app.get('/test/:uid',test);
var test = function(req,res,next) {
// do whatever logic is needed
res.end('Displaying information for uid ' + req.params.uid);
}
app.get('/test/:uid',test);
Now, open up a new terminal, make sure you are in the myproject directory and enter:
node app.js
Now you can visit http://localhost:3000/test/45 on the local machine and you should see:
Displaying information for uid 45
If you are not accessing from your local machine make sure to change the url above to match whatever server your node app is running on.
Also, this is just a simple example. You might be better off organizing everything by placing the routes in files similar to the routes directory example setup in a new install of an express app. You can find more detailed examples of this on the web like this one and this one. Also, one of the best explanations of organizing/reusing code in Node this I have seen is in the book NodeJS in Action.

NodeJS + Express: How to secure a URL

I am using latest versions of NodeJS and ExpressJS (for MVC).
I usually configure my rest paths like this, for example:
app.get('/archive', routes.archive);
Now i want my /admin/* set of URLs to be secured, I mean I need just simple authentication, it's just a draft.
When a user tries to access, for example, /admin/posts, before sending him the corresponding view and data, I check for a req.session.authenticated. If it's not defined, I redirect to the login page.
Login page has a simple validation form, and a sign-in controller method: if user does send "right user" and "right password" I set the session variable and he's authenticated.
What I find difficult, or I don't understand, is how to actually make the "filter" code, I mean, the auth check, before every /admin/* path call.
Does this have something to do with "middleware" express functions?
Thank you
Yep, middleware is exactly what you want. A middleware function is just a function that works just like any other Express route handler, expept it gets run before your actual route handler. You could, for example, do something like this:
function requireLogin(req, res, next) {
if (req.session.loggedIn) {
next(); // allow the next route to run
} else {
// require the user to log in
res.redirect("/login"); // or render a form, etc.
}
}
// Automatically apply the `requireLogin` middleware to all
// routes starting with `/admin`
app.all("/admin/*", requireLogin, function(req, res, next) {
next(); // if the middleware allowed us to get here,
// just move on to the next route handler
});
app.get("/admin/posts", function(req, res) {
// if we got here, the `app.all` call above has already
// ensured that the user is logged in
});
You could specify requireLogin as a middleware to each of the routes you want to be protected, instead of using the app.all call with /admin/*, but doing it the way I show here ensures that you can't accidentally forget to add it to any page that starts with /admin.
A even simpler approach would be to add the following code in the App.js file.
var auth = function(req, res, next) {
if(isAdmin) {
return next();
} else {
return res.status(400)
}
};
app.use('/admin', auth, apiDecrement);
As you can see the middleware is being attached to the route. Before ExpressJS goes forward, it executes the function that you passed as the second parameter.
With this solution you can make different checks before displaying the site to the end user.
Best.
Like brandon, but you can also go the connect route
app.use('/admin', requireLogin)
app.use(app.router)
app.get('/admin/posts', /* middleware */)

Resources