Access Root directory using Node - node.js

Is there any way to access the Linux root ('/') directory through node? Right now, I have something like this:
multipart = require('connect-multiparty')
app.use(multipart({
uploadDir: config.tmp
}));
...
var file = req.files.file;
fs.renameSync(file.path, ".", function(err) {
if(err) console.error(err.stack);
})
but the problem is that file.path is refering to a folder inside the Linux root rather than the project's root.

The most literal answer to your question
Is there any way to access the Linux root ('/') directory through node?
Is yes, by using /. Node.js shouldn't be giving any special treatment to it. Root is a directory just like any other.
On to your code...
fs.renameSync takes a source first and destination second.
You are renaming a file to ., which represents the current working directory. I'm not even sure if you can rename something to .. I would extract the filename from the path, then set the destination to the root directory plus that file name.
How to access the root directory, which as you said, is /, well, use /.
By the way, why are you using renameSync with a callback and nothing after it? According to the documentation, this is not valid. It's either async with a callback, or sync without a callback. So your callback is probably not firing.
var file = req.files.file;
fs.rename(file.path, '/' + path.basename(file.path), function(err) {
if(err) console.error(err.stack);
});
By the way, I have to advocate strongly against an application writing files to the Linux root directory, for a number of reasons:
Requires root privileges, which opens a can of worms.
Nobody would ever think to look there
The slightest bug could cause irrevocable damage. What if the desired file name is "etc" or "boot"?
There are a million better locations for storing files uploaded from a web server.

Related

Node.js + Express.js: How to use the root (/) for serving static files?

how do we serve a static file located in the root of the directory (/) and not in a folder of it?
I am using Node.js with Express.js, I have tried the following JavaScript code in my index.js file which is located in / (the root of the directory).
Attempt 1
const path = require('path');
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
})
Attempt 2
const path = require('path');
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, '/'));
})
Same output as Attempt 1
Attempt 3
app.use(express.static('/'));
Didn't work, showed an error: "Cannot GET /".
Attempt 4
app.use(express.static(''));
Didn't work, showed an error: "Path cannot be empty".
Please assist, I have refered to many other possible questions similar to this, and one of the questions didn't have an answer, so I am re-asking.
The argument you pass to express.static needs to be the path to the directory where the file is.
It shouldn't be / which is the root of the entire file system (you might intend it to be the URL path / and not the file system path / but that isn't what it means).
The special variables __dirname will give you the directory the JS file you are currently running is in. You probably want that (assuming a directory structure like this):
.../
|-server.js
|-index.html
So
app.use(express.static(__dirname));
Note that it is generally better to separate out your server-side code and the files you sent to the client. It makes it much easier to maintain the project in the long run and prevents your server side code (which might contain secrets) being exposed over HTTP by the static module.
There isnt any difference if you use / and no / in the script
for express use
app.use(express.static(process.cwd() + '/'));
try this it might be helpful
app.use(express.static('/'));
you do not need the "/" before "js" because it is already included above:
<script src="test.js"></script>

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/)

Err. ENOENT when renaming a file in node.js

I'm trying to upload a file in my node/express app, but everytime I've got the ENOENT error when renaming the file. My code is that:
var tmp_path = req.files.file.path;
fs.rename(tmp_path, target_path, function (err) {
if(err) throw err;
...
});
where target_path will be the destination path. If I do:
console.log('exists ' + fs.existsSync(tmp_path));
then my server logs:
exists true
Also, listing the contents of tmp directory shows that the file is there. What's the problem?
FS methods like fs.rename which create, move or rename files expect that any directories in the path already exist. When they do not, you'll get an ENOENT. Since very often what you mean is "make this file -- and any directories in the path I specify for it" you may want to consider using an NPM library that abstracts access to fs with methods that take care of such things.
There are quite a few options. For example fs-extra is one of the better-tested libraries. Using fs-extra you can use ensureDir in that operation to make the directory structure first if it does not yet exist.

NodeJitsu error: Error: ENOENT, stat '/opt/run/snapshot/

My app’s folder structure for NodeJitsu is as follows (i.e., when i do a jitsu deploy, I'm in the folder that contains "server.js" - i.e., the "server" folder).
Root server
|___server.js
|___package.json
client
|___www
|___index.html
|___css
|___js
|___etc.
So at the root is the folder "server", containing the starting script, “server.js”. Then there’s a folder called “client”, parallel to "server", with a folder within that called “www”, and within “www” is the main “index.html”.
In my “server.js” file, I have the following code:
app.get(‘/’, function(req,res)
{
var aPath = path.resolve(“../client/www/”, “index.html”);
res.sendFile(aPath);
});
I don’t have a app.use(express.static(__dirname + '/somefolder'). And when I start the app, I get this error:
Error: ENOENT, stat '/opt/run/snapshot/client/www/index.html'
My process.cwd() is /opt/run/snapshot/package. Obviously the above path isn’t pointing to the location where “index.html” resides. But I thought the way I do the path.resolve(…) should point to “index.html”. I can’t see where the problem is. If “server.js” is in the root, then to get to “index.html”, which is in “client/www/index.html”, then I should need to write “../client/www”, relative to the excuting script, to get to “index.html”, right?.
Do you have any insights as to where the path is not set up correctly? What should /opt/run/snapshot/ be pointing to? Or, what changes do I need to make in the get(‘/’) handler to correctly point to my “index.html”?
EDIT
I incorrectly drew the folder structure. Now it's correct.
I also turned off the app.get() and turned on the app.use(express.static(__dirname + '/../client/www/'). But to no avail: now i get a Cannot GET / error.
What I'm ultimately after is to have the "server.js" file be the Node server that, mostly, just serves AngularJS HTML files to the browser, with attendant images, stylesheets, etc., from the "client" folder. This is the server's main role, with an additional role of authenticating the app's users, employing the very nice Satellizer module. And that's it. I have a MongoDB attached, but otherwise this is a very common and straightforward Node.js server app.
Thanks!
Try it without rooting, resolving and log out to double check:
// notice no leading / which is root. __dirname should be the dir of current file running
var staticPath = path.resolve(__dirname, '../client/www');
console.log(staticPath);
Then pass that into express.static
app.use(express.static(staticPath);
I would probably recommend following the layout and convention of express generated apps with app in the root and static files under public
/public
<static files>
app.js
Then do what the generated app does:
app.use(express.static(path.join(__dirname, 'public')));

why I can't sendFile() in node.js express when deployed to AWS?

I am using node.js express to serve some static file like svg and json to the client, so I used sendFile() to send the files directly.
so here is my server file structures,
/root // the root of the server
/maps // put some static files
/routes/api // put the web API
in the web API
app.get('/buildings/map',function(req,res){
var mappath = 'maps/ARM-MAP_Base.svg';
res.sendfile(mappath);
})
It works perfectly on my local server to send files to the client, so it means the server could locate the file and send it. but when the server is deployed to the AWS, this methods would encounter a error - 242:Error: ENOENT, stat node.js, looks like it can't open the file in that path
I read some solutions like combining the __dirname with mappath, it didn't work since it would bring to the path of /routes/api/maps/...
so far I have no idea why it works on my local computer but fail to work on the AWS
Relative fs paths like mappath will be resolved from the current working directory, which isn't guaranteed to be consistent. It works locally because you're executing your application with /root as your working directory.
This is why you're finding recommendations to use __dirname, which an be used to resolve paths relative to the current script.
Though, along with it, you'll want to use ../ to resolve parent directories.
var mappath = 'maps/ARM-MAP_Base.svg';
res.sendfile(__dirname + '/../../../' + mappath);
This assumes the current script is located in and __dirname would be /root/maps/routes/api as the indentation in your directory tree suggests.

Resources