NodeJS/CloudFoundry - failed: The app upload is invalid: Symlink(s) point outside of root folder - node.js

I'm testing CloudFoundry on IBM and are running NodeJS.
When trying to cf push my application I get the following error:
failed: The app upload is invalid: Symlink(s) point outside of root folder
In my appllcation I have the following code:
return res.sendFile(path.join(__dirname +'/tvshows/'+ guide +'.html'));
When not using path.join and simply use:
return res.sendFile(path.join('./tvshows/'+ guide +'.html'));
I get this error instead:
TypeError: path must be absolute or specify root to res.sendFile
What to do?
I've also tried stuff like path.join((process.env.BUILD_DIR || __dirname), and return res.sendFile('index.html', { root: path.join(__dirname, 'tvshows', guide) }); but no luck.

The fail came from my node_modules folder.
Adding .cfignore with node_modules/ fixed the issue.

You didn't mention the version of the cf cli that you're using, but I think that this is expected behavior starting with version 6.34.0.
push now preserves relative symlinks in app files. This makes it easier to work with Node.js apps using npm link, but note that it now errors when it detects a symlink pointing outside the app folder (e.g. a node_modules folder containing external symlinks).
https://github.com/cloudfoundry/cli/releases/tag/v6.34.0
I think you're running into the second part, "how errors when it detects a symlink pointing outside the app folder". It's nothing to do with the code in your app, but rather somewhere in your project folder there is a symlink which references another file that is not under the root of your project.
If you're on a unix-like system you can run find . -type l to find all the symlinks under the current directory. Then you just need to figure out which one is pointing outside of the project root.
Options are to remove that symlink, point it to something under your project root or use .cfignore to ignore that file (which is what you ended up doing).
Hope that helps!

Related

Error finding CACerts on the relative path in the CACertPathList option of IDaaSOIDCStrategy in passport-ci-oidc on Cloud Foundry

I attempted to create an IDaaSOIDCStrategy. In the options I specify a relative path for the CACerts that begins with "/", in my case "/local/".
const Strategy = new openIdConnect.IDaaSOIDCStrategy(
{
...
addCACert: true,
CACertPathList: [
'/local/<certificate-name>.pem',
'/local/<another-certificate-name>.pem',
}
The path is supposed to be resolved relative to the app root. However, when I deployed the app to Cloud Foundry, it crashed with an error that the first file in the CACertPathList couldn't be found:
ENOENT: no such file or directory
Instead of looking under the app root,the strategy creation code is looking under the root folder of the passport-ci-oidc package, which is where node_modules is installed. In my Cloud Foundry deployment, the root folder of node_modules is not the app's root, it's in a different place, under /home/vcap/deps/0/. The app root is in /home/vcap/app.
What can I do to ensure that the path of the CACerts is resolved properly?
The solution that worked for me is a workaround, but a resolution nonetheless. (The behavior of the strategy code in which it finds the relative path from the root of the passport-ci-oidc package does not match the description in the documentation, which states that it uses the app root, so it may be a defect).
When Cloud Foundry builds dependencies, if there is a node_modules directory under the app root, it will find it, and look for dependencies there, instead of creating a node_modules directory in another location.
In my case, I had originally included node_modules in the .cfignore file, so node_modules was not being pushed to Cloud Foundry. When I removed node_modules from .cfignore, the local node_modules folder, which is under the app root, is pushed directly under the app root. As a result, the root of the passport-ci-oidc package is the same as the app root, so the relative path is expanded from the app root.

Serving static files with Express.js on heroku. Where do files reside in Heroku?

The issue is Heroku can not find the files of my node project. This prompts the 404 Not found error. The question is how does the generic node Heroku file structure look like? If so, where do the files of my project actually reside in the heroku?
The scenario:
With the express library, I put all files needed to serve a frontend template, in a folder called 'public'. The absolute path leading to 'public' is needed and'_dirname' is the variable that contains that.
app.use(express.static(_dirname+'/public');
Now, Heroku always makes a GET request to the root of the application. As a response I send the
index.html file as the starting template. I also provide its absolute path as '{root:_dirname}'.
app.get('/', function(req, res) {
res.sendFile('public/index.html'{root:_dirname});
});
When the server is run, I get a 404 Not found error. Which means Heroku cannot find the files.
Heroku root folder is named app/. So as expected, providing the local '_dirname' is wrong since the application is now running on Heroku server not locally.
2020-09-10T15:28:12.127567+00:00 app[web.1]: Error: ENOENT: no such file or directory, stat '/app/C:/Users/...
But, pointing at the public folder alone(only /public), assuming app/ is root, still prompts the 404 error not found.
2020-09-10T15:31:23.630358+00:00 app[web.1]: Error: ENOENT: no such file or directory, stat '/index.html'
The Question
Which leads to the question, what does heroku file structure look like? where do project files reside in the heroku file structure, so i can provide the correct path on the GET request?
My file structure
After Bergur suggestion:
It prompts a 404 Not found. However, the path is now theoretically correct.
This is what I changed:
app.use(express.static(path.join(__dirname+'/public')));
app.get('/', function(req, res) {
res.sendFile('index.html',{root:__dirname+'/public'});
});
The 404 error comes from the 'app.get('/,function(req,res){});'. Without this handler, my heroku application shows a 'cannot GET' message on the template.
Have you tried to log out the full path just to see if there's something off?
I have several heroku projects with nodejs and react/vue/angular dist folder without problems.
I would change your code a little bit to:
use nodes __dirname
Use path.join instead of inserting the '/' yourself. It might cause some problems.
So final version might look like:
app.use(express.static(path.join(__dirname, 'public')));
This assumes the project structure is
-index.js
-public/index.html
There should be no need to use sendFile, serving the public folder is enough. Just make sure that the public folder is being deployed/pushed to heroku.
If you share with us your folder/project structure we might help you you better.

NodeJS - Paths break after deployment

I deploy my NodeJS Projects with supervisord. Strangely most of the paths, which are paths
inside the served index.html: links to static files (stylesheets and js files)
inside javascript files, require statements to other files(e.g.: require('./scripts/'))
I believe the reason for that to be the command node "path/to/my/application/app" since it runs the application from a different directory.
How can i avoid changing the paths whenever i push a new version of my application to production?
Can you recommend any tools to solve this problem? Is there a clean way of setting the paths so that the application works so i can run it from anywhere(my local machine/my webspace)?
Use a relative path. For example if index.html is in a directory as same as a .js file referring it u can use ('./index.html'). If it were in a parent directory u could use (../index.html)

How to share npm modules across projects?

I'm using windows 10 x64.
I'm using dropbox to hold all my projects, and having a 'node_modules' folder inside a dropbox folder is a disaster.
First of all not all npm packages work in a way that would allow this method , because as it says in line one " does not begin with '/', '../', or './' ", so that won't work I think.
So, I tried to make syslink, but as I figured out, windows doesn't allow creating true hard links for folders, only files.
My method to create a folder junction was to have this bat file inside each project folder, and run it as administrator.
SET dest=%~dp0node_modules
SET src=F:\work\node_modules
MKLINK /J %dest% %src%
The bat file works, it creates the syslink, but 3 problems occur.
Dropbox sees it as a real folder and starts syncing it.
That folder doesn't show in the selective syncing to prevent syncing it.
npm can't use it for some reason and when I run 'npm install', It creates a new real 'node_modules' folder to replace the syslink, I get this error output:
I would not try to use junctions, they are pretty hard to work with and can lead to data loss if you don't know what you're doing.
Instead, you could go with the following approach.
Create a json config file containing the path to your modules:
{"modules_root": "F:/work/node_modules/"}
In your code, load this json and require your modules by prepending the path from your config file:
var fs = require("fs");
var modules_root = JSON.parse(fs.readFileSync("modules_root.json")).modules_root;
var express = require(modules_root + "./express")
If you ever decide to use local modules, you could just change the config file to:
{modules_root: "./node_modules/"}

Nodejs difference between ./folderpath vs ../folderpath

I'm new in nodejs. I try to use some file in my filesystem. I would like to get them through some realtive path. Here is the structure:
-app
-resources
-tmp
-file1
-file2
-common
-common.js
-etc
So, I would like to reach the file1 and file2 in my resources/tmp folder from the common.js file in int common folder. I used two relative path methodic:
// First , wrong one
var tmpfolder = '../resources/tmp';
// Second, good one
var tmpfolder = './resources/tmp';
The file absolute path is something like this:
C:\Users\xy\Documents\work\nodejs\projects\project_wrapper_folder\project_folder\resources\tmp
If I log the first relative path I got this result:
C:\Users\xy\Documents\work\nodejs\projects\project_folder\resources\tmp
which is wrong, because it does not contains the wrapper folder.
But the second works fine.
Can somebody explain me this behaviour?
UPDATE
I see the meaning if '../', thanks your explanations!
I have tried #Lissy answer: "So baring that in mind ./ will resolve to the value of your project root..." that sounds great, but the result is not.
I have this logic in my app:
var tmpfolder = require('./otherFolder/orhetFile');
where otherFolder is the subfolder of my project_folder. So, when I used this here, I got an error called Cannot find module ...
But if I use this './' in fs module, here: /project_folder/otherFolder_2/otherFile_2 like:
var path = `./resources/tmp`;
fs.mkdirsSync(path);
It works!
these is strange for me. If './' means the current folder, than the example above sould not work (but it's works).
But if the './' means path of the project root, the example with require should work (but does not work).
Strange for me, is there some meaning of require or fs??
In Summary
./my-file means look at the root, whereas ../my-file, means come out of the current directory, and look in the parent folder.
Explanation of Relative and Absolute Paths in Node.js
The default document root is set with the NODE_PATH environment variable (however it would be terrible practice to modify that). So baring that in mind ./ will resolve to the value of your project root.
And so let tmpfolder = require('./resources/tmp'); would resolve to
C:\Users\......\project_wrapper_folder\project_folder\resources\tmp as you have seen
A relative path is denoted by not starting with ./, so for example let tmpfolder = require('my-scripts/some-script'); would look in the current directory for another folder called my-scripts.
Following on from that ../ is relative to the current directory, but goes out one (to it's parent) and looks from there. You can go out two directories by doing ../../my-dir and so on (this is not great practice though, as it can get hard to manage if you have ../../../../../../)
Better method
You can use the __dirname constant in Node to locate the directory name of the current module.
e.g.
fs.readFile(__dirname + '/../foo.bar');
Useful Links
I think you'll find this article on Better local require() paths for Node.js very useful.
Also, for a bit of further reading, here is the official Node.js documentation on paths
The .. means the previous dir. So you are getting out from project_wrapper_folder and then add to the script dir resources\tmp and that way the project_wrapper_folder is no longer in the relative path.
Lets assume you are inside a folder called app.
when you use ../resources/tmp, it will come out of the app folder and will search for tmp inside resources folder.
when you use ./resources/tmp, it will look within the app folder for resources folder and tmp inside it.
../ points to the parent directory while ./ points to current working directory.
A dot basically means "go one folder back in the path"
So:
'./' points at the folder you are in.(in your case the folder common/)
'../' points at the folder that contains the folder you are in. (in your case the folder app/)

Resources