Detect IE in expressjs, but can't get static files - node.js

I've tried to detect IE by using expressjs, the code surely redirect me to the error page.
But the problem is that it won't render css files and get image files in my folder.
I think the problem is that expressjs redirect to error_page before the static path is set.
So I put app.all('*', ieRedirecter);, after
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'));
The problem is still occur... could someone help me out, thanks!
My settings
function ieRedirecter(req, res, next) {
if(req.headers['user-agent'].indexOf("MSIE") >= 0) {
var myNav = req.headers['user-agent'];
var IEbrowser = parseInt(myNav.split('MSIE')[1])
if(IEbrowser < 9) {
res.render('error/browser_error', {title : 'not supporting your browser'})
} else {
next();
}
} else {
next();
}
};
app.configure(function(){
app.set('port', process.env.PORT || 3000);
...
...
...
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'));
app.all('*', ieRedirecter);
})

This order doesn't work:
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'));
app.all('*', ieRedirecter);
app.router is the middleware that handles all your routing requests, including app.all(), even though you declare that route after your other middleware (fun fact: at any moment you declare a route – using app.{get,post,all,...} – the app.router middleware is inserted into the middleware chain automatically).
If possible, the easiest solution would be to move the static and IE middleware to before your routes (but I realize that might cause problems with your application setup):
// static middleware first...
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'))
// ...followed by the IE check
app.use(ieRedirecter);
// ...followed by your routes
app.get('/', ...);
...
Another solution would be filter out requests for static resources in your ieRedirecter middleware by looking at req.path, but that assumes that you can easily identify those requests (like if they start with /css or /js).

Related

How to remove the preference for index.html in nodejs?

In my public folder I have the index.html file and my route handler is like this
router.get('/', function (req, res, next) {
// res.send('index.html');
if (req.user)
res.redirect('home');
else
res.redirect('login');
});
As you can see , I have commented out the serving of index.html file , but nodejs still serves the index.html from the public directory instead of redirecting to home or login. But if I remove/rename the index.html file then it works fine.
So How can I configure nodejs so that it invokes the route handler , not the serve index file on request ?
The express.static() middleware includes an index option that allows you to change the default file name.
Or, for your intentions, to disable the feature entirely:
app.use(express.static(path.join(__dirname, 'public'), {
index: false
}));
This is due to ordering of the app.use , previously it was
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
changing this to
app.use('/', index);
app.use(express.static(path.join(__dirname, 'public')));
Solves the problem.

Node.js catch-all route with redirect always renders index page with Angular regardless of url

Essentially when I use a catch-all route and use res.redirect('/') regardless of the url I enter it will always render the index/home page (ie Angular does not seem to 'see' the full url) however if I place res.render('index') in the catch-all route everything works fine. I don't want repeat code and redirecting to '/' should work, I have probably made a stupid mistake somewhere here and any help would be much appreciated!
Angular routing:
app.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/',
{
templateUrl: 'partials/home.jade'
})
.when('/about',
{
templateUrl: 'partials/about.jade'
})
.otherwise( {redirectTo: '/'});
});
This will correctly render the about page when entering site-address/about:
app.get('/', function (req, res) {
res.render('index');
});
app.get('/partials/:name', function (req, res) {
res.render('partials/' + req.params.name);
});
app.get('*', function (req, res) {
res.render('index');
});
This will always just show the index page:
app.get('/', function (req, res) {
res.render('index');
});
app.get('/partials/:name', function (req, res) {
res.render('partials/' + req.params.name);
});
app.get('*', function (req, res) {
res.redirect('/');
});
Configuration if it helps:
// Configuration
app.configure(function () {
app.set('port', process.env.PORT || 1337);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
});
This is by design.
When you use res.redirect('/'), Node/Express is sending an HTTP redirect, which will change the URL in the browser, thus when your index template is rendered, and when the angular code is run, the URL is /, regardless of what the user entered (the whole point of the redirect).
When you omit the redirect and just send the template as a response, NodeJs responds with an HTTP 200 (success) along with HTML content. Since the URL didn't change, when your application runs, the angular routing properly routes.
EDIT TO ADD: Address Comment
Rather than have two routes render the same template, I would get rid of the / route all together, and just have the catch-all render the index template, which will then turn control over to the Angular router.
Otherwise, I would consider splitting your routes conceptually: All your application routes are specifically sent to angular router, and you render static routes via nodejs, and use your catch all to render a more appropriate page for a missing or unknown resource (more helpful for your users).
You can use regex-like languages to specify a single handler:
app.get('/()|(about)|(contact)/',function(req,res) {/* handle */});
For folder structure:
root
-web.js
-dist/index.html
-dist/rest of the page
Just paste the following snippet to your web.js
nodeApp.use('/', express.static(__dirname + '/dist'));
nodeApp.get('/[^\.]+$', function(req, res){
res.set('Content-Type', 'text/html')
.sendfile(__dirname + '/dist/index.html');
});
I have a problem where when I use the catch-all routing, all of my static assets (stylesheets, javascript files etc) don't load:
app.use(app.router);
app.use(express.static(path.join(__dirname, frontend.app)));
// when this is removed, I can load static assets just fine
app.get('*', function(req, res){
res.render('main');
});
When the app.get('*', ...) part is removed, I can load the static assets just fine (i.e. I can type in 'examplejavascript.js' and see the javascript file. When it is there however, express catches the assets.
$locationProvider.html5Mode(true);
are you sure your requests are hitting the nodejs server. using this means, angularjs will try to search for urlmapping inside browser.
try by commenting
$locationProvider.html5Mode(true);

Express 3 - Serving static scripts/styles - Error: Failes to load resource (404)

I am new to node and server-side development in general and started having a look at it today so mind my question. I have looked for suiting answers in previous post, yet somehow every suggested solution was criticized by many users.
I can't serve static scripts/styles due to the following error:
Failed to load resource: the server responded with a status of 404 (Not Found)
I am using express 3.1.0.
Here is my code:
app.js
var express = require('express');
var app = express();
var routes = require('./routes');
app.configure(function () {
app.set('view engine', 'jade');
app.use(express.static(__dirname + '/public'));
});
app.get('/', routes.home);
app.get('/about', routes.about);
app.get('/blog', routes.blog);
app.get('/faq', routes.faq);
app.get('/terms', routes.terms);
app.get('/privacy', routes.privacy);
app.get('/jobs', routes.jobs);
app.get('/press', routes.press);
app.listen(8080);
index.js (routes)
exports.home = function(req, res){
res.render('home', { title: "Home"});
};
exports.about = function(req, res){
res.render('about', { title: "About" });
};
etc...
layout.jade
doctype 5
html
head
title= title
link(rel='stylesheet', href='public/styles/bootstrap.css')
body
block content
br
a(href='../') Home
br
a(href='../about') About
br
etc...
home.jade
extends layout
block content
p Home
When you setup server middlewere it looks for requests at the root unless specified otherwise if you are looking for a stylesheet in "public/styles" you request it at just "/styles"
to make the middlewere answer to requests to /public change it to
app.use('/public', express.static(__dirname + '/public'));
I tried using
app.use('/public', express.static(__dirname + '/public'));
instead of
app.use(express.static(__dirname + '/public'));
and it worked.
However according to the first answer in this post: express.js not serving my image it is not considered good. I can't understand why? And what else would be a better solution?

Using express.static middleware in an authorized route

I'm using node with express and passportjs to restrict access to files located in a private folder. I have reduced my code to the following.
Everything in the public static folder works great but route targeting the private folder through the use of the staticMiddleware returns 404 errors.
var express = require('express')
, util = require('util');
var app = express.createServer();
var staticMiddleware = express.static(__dirname + '/private');
app.configure(function() {
app.use(app.router);
app.use(express.logger('dev'));
app.use('/public',express.static(__dirname + '/public'));
});
app.get('/private/:file', function(req, res, next){
console.log('about to send restricted file '+ req.params.file);
staticMiddleware(req, res, next);
});
app.listen(16000);
I was using the following references that seems to work for others, so I must be missing something.
It won't work for me showing only 404 responses for the content located in the private area.
Node.js module-specific static resources
NodeJS won't serve static files, even when using express.static
Redirecting to a static file in express.js
I could have sworn I had this working before, maybe it was broken in a new version of something.
Node v0.8.1
npm 1.1.12
express#2.5.11
connect#1.9.2
sheesh staring at me the whole time
app.get('/private/:file', function(req, res, next){
console.log('about to send restricted file '+ req.params.file);
req.url = req.url.replace(/^\/private/, '')
staticMiddleware(req, res, next);
});
Edit 11-29-2014
So after someone posted to the question I came back to this answer to find that even though I mention passportjs I never showed how I ended up using this function.
var staticMiddlewarePrivate = express['static'](__dirname + '/private');
app.get('/private/*/:file', auth.ensureAuthenticated, function(req, res, next){
console.log('**** Private ****');
req.url = req.url.replace(/^\/private/, '');
staticMiddlewarePrivate(req, res, next);
});
You can also add express.static(__dirname + '/private'); to your app.config.
app.configure(function() {
app.use(app.router);
app.use(express.logger('dev'));
app.use('/public',express.static(__dirname + '/public'));
app.use('/private',express.static(__dirname + '/private'));
});
The private path middleware would be executed anytime a path began with private.

Why do I to have prefix all my route handlers

I'm creating an application using Expressjs running on node under IISNode (i.e on windows).
I start by setting things up very much like all the expressjs examples I've seen:
backend.configure(function() {
backend.register('html', {
compile: function(str, options) {
return function(locals) {
return str;
};
}
});
backend.set('views', __dirname + '/views');
backend.set('view engine', 'html');
backend.set('view options', {
layout: false
});
backend.use(express.bodyParser());
backend.use(backend.router);
backend.use(express.static(__dirname + '/public'));
});
Lets say my site is running at localhost://mysite. I'm having to create all my route handlers as follows.
backend.get('/mysite/index', function(req, res, next) {
return res.render('index');
});
i.e. I'm having to prefix them all with "mysite". Non of the examples I've seen require this. Is this something to do with IISNode or something else I haven't configured?
I was looking for this feature but for API routes, not for static files. What I did was that when I initialized the router, I added the mount path. So my configuration looks like this
//Default configuration
app.configure(function(){
app.use(express.compress());
app.use(express.logger('dev'));
app.set('json spaces',0);
app.use(express.limit('2mb'));
app.use(express.bodyParser());
app.use('/api', app.router); // <---
app.use(function(err, req, res, callback){
res.json(err.code, {});
});
});
Notice the '/api' when calling the router
Out of the box, this is indeed how you have to do it. You could look into express-resource, enabling resourceful routing - but that comes with it's own caveats, at least when it comes to route-specific middleware.
If it's just one path, I think you can handle that with app.set("basepath", "mysite").
To avoid having to modify your express app when deploying in IIS using iisnode, you need to deploy to the root of the IIS WebSite rather than a virtual directory under a site.

Resources