FirstOfMany FirstOfMany - 1 year ago 274
Node.js Question

ForBiddenError in Node.js/Express.js/Angular2

I am modifying this GitHub sample app to use Express instead of KOA. But I am getting an

Access Denied
error when the
route in Express tries to load the
. What specific changes need to be made to the code below so that the new
route can successfully serve the

The only changes made to the sample app are to modify
, to replace
, and to modify
. I will show the changes as follows:


Here are the new relevant parts
, with the old content omitted for brevity. Noet that I added a
route to handle requests for
and I added
module.exports = function(app)

'use strict';

// expose the routes to our app with module.exports
module.exports = function(app) {

//other routes omitted for brevity

app.get('*', function(req, res) {
console.log('inside / route!');
res.sendfile('../client/index.html'); // load the single view file (angular will handle the front-end)


Here is the new

// set up ======================================================================
var express = require('express');
var app = express(); // create our app w/ express
var port = process.env.PORT || 8080; // set the port
var morgan = require('morgan'); // log requests to the console (express4)
var bodyParser = require('body-parser'); // pull information from HTML POST (express4)
var methodOverride = require('method-override'); // simulate DELETE and PUT (express4)

app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use('/scripts', express.static(__dirname + '/node_modules/'));

// load the routes

// listen (start app with node server.js) ======================================
console.log("App listening on port " + port);


The new package.json is:

"name": "angular2-esnext-starter",
"version": "1.0.0",
"main": "server/index.js",
"scripts": {
"start": "node server/index.js",
"test": "COVERAGE_ENABLED=true gulp test",
"webdriver-update": "webdriver-manager update"
"repository": {
"type": "git",
"url": "git+"
"author": {
"name": "blacksonic",
"email": ""
"license": "ISC",
"keywords": [
"description": "Angular 2 development in Javascript with ES6/ES7 syntax powered by Babel.",
"engines": {
"node": "4.4.2"
"dependencies": {
"express": "^4.13.4",
"jsonwebtoken": "7.0.1",
"morgan": "^1.1.1",
"method-override": "^2.1.3",

"node-uuid": "1.4.7"
"devDependencies": {
"@angular/common": "2.0.0-rc.4",
"@angular/compiler": "2.0.0-rc.4",
"@angular/core": "2.0.0-rc.4",
"@angular/forms": "0.2.0",
"@angular/http": "2.0.0-rc.4",
"@angular/platform-browser": "2.0.0-rc.4",
"@angular/platform-browser-dynamic": "2.0.0-rc.4",
"@angular/router": "3.0.0-beta.2",
"babel-core": "6.10.4",
"babel-eslint": "6.1.1",
"babel-loader": "6.2.4",
"babel-plugin-__coverage__": "11.0.0",
"babel-preset-angular2": "0.0.2",
"babel-preset-es2015": "6.9.0",
"bootstrap": "3.3.6",
"codeclimate-test-reporter": "0.3.3",
"del": "2.2.1",
"es6-promise": "3.2.1",
"es6-shim": "0.35.1",
"gulp": "3.9.1",
"gulp-cssnano": "2.1.2",
"gulp-delete-lines": "0.0.7",
"gulp-eslint": "3.0.1",
"gulp-less": "3.1.0",
"gulp-nodemon": "2.1.0",
"gulp-protractor": "2.4.0",
"gulp-util": "3.0.7",
"gulp-watch": "4.3.8",
"jasmine-core": "2.4.1",
"json-loader": "0.5.4",
"karma": "1.1.1",
"karma-coverage": "1.1.0",
"karma-jasmine": "1.0.2",
"karma-phantomjs-launcher": "1.0.1",
"karma-sourcemap-loader": "0.3.7",
"karma-webpack": "1.7.0",
"localStorage": "1.0.3",
"mini-lr": "0.1.9",
"phantomjs-polyfill": "0.0.2",
"phantomjs-prebuilt": "2.1.7",
"protractor": "3.3.0",
"raw-loader": "0.5.1",
"reflect-metadata": "0.1.3",
"run-sequence": "1.2.2",
"rxjs": "5.0.0-beta.6",
"validate.js": "0.10.0",
"webpack": "1.13.1",
"zone.js": "0.6.12"

Error Message

Here is the complete error message which prints in FireFox:

ForbiddenError: Forbidden
at SendStream.error (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/send/index.js:275:31)
at SendStream.pipe (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/send/index.js:508:12)
at sendfile (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/express/lib/response.js:1051:8)
at ServerResponse.res.sendfile (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/express/lib/response.js:481:3)
at ServerResponse.eval [as sendfile] (eval at wrapfunction (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/depd/index.js:413:5), <anonymous>:4:11)
at /home/user/nodejs_apps/angular2_oauth_seed_app/server/router.js:94:17
at Layer.handle [as handle_request] (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/express/lib/router/layer.js:95:5)
at next (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/user/nodejs_apps/angular2_oauth_seed_app/node_modules/express/lib/router/layer.js:95:5)

Answer Source

The error comes from res.sendfile(../); you cannot sendFile with a relative path as express considers this a security concern. To solve this, require the path module and use path.resolve('/wherever/youre/going') instead of a relative path.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download