Express res.sendfile throwing forbidden error

node.jsExpress

node.js Problem Overview


I have this code:

res.sendfile( '../../temp/index.html' )

However, it throws this error:

Error: Forbidden
at SendStream.error (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/send/lib/send.js:145:16)
at SendStream.pipe (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/send/lib/send.js:307:39)
at ServerResponse.res.sendfile (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/response.js:339:8)
at exports.boot (/Users/Oliver/Development/Personal/Reader/server/config/routes.js:18:9)
at callbacks (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:161:37)
at param (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:135:11)
at pass (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:142:5)
at Router._dispatch (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:170:5)
at Object.router (/Users/Oliver/Development/Personal/Reader/node_modules/express/lib/router/index.js:33:10)
at next (/Users/Oliver/Development/Personal/Reader/node_modules/express/node_modules/connect/lib/proto.js:199:15)

Can anyone tell me why this might be?

node.js Solutions


Solution 1 - node.js

I believe it's because of the relative path; the "../" is considered malicious. Resolve the local path first, then call res.sendfile. You can resolve the path with path.resolve beforehand.

var path = require('path');
res.sendFile(path.resolve('temp/index.html'));

Solution 2 - node.js

This answer gathers together the info from the other answers/comments.

It depends whether you want to include something relative to the process working directory (cwd) or the file directory. Both use the path.resolve function (put var path = require('path') at the top of the file.

  • relative to cwd: path.resolve('../../some/path/to/file.txt');
  • relative to file: path.resolve(__dirname+'../../some/path/to/file.txt');

From reading the link from @Joe's comment, it sounds like relative paths are a security risk if you accept user input for the path (e.g. sendfile('../.ssh/id_rsa') might be a hacker's first try).

Solution 3 - node.js

The Express documentation suggests doing it a different way, and in my opinion it makes more sense later than the current solution.

res.sendFile('index.html', {root: './temp'});

The root option seems to set ./ as the root directory of your project. So I cannot fully tell where you file is in relation to the project root, but if your temp folder is there, you can set ./temp as the root for the file you're sending.

Solution 4 - node.js

Also, you can use path.join

const path = require("path");

router.get("/", (req, res) => {
  let indexPath = path.join(__dirname, "../public/index.html");
  res.sendFile(indexPath);
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1082754View Question on Stackoverflow
Solution 1 - node.jsJoeView Answer on Stackoverflow
Solution 2 - node.jsderekdreeryView Answer on Stackoverflow
Solution 3 - node.jstenor528View Answer on Stackoverflow
Solution 4 - node.jsLalit VavdaraView Answer on Stackoverflow