File path not found when code is deployed on a remote server - node.js

I have the following directory structure for my node/express app:
/
/client_side_code
- object00.png
/server_side_code
- server.js
When running a local server on port 3000, my server.js script accesses object00.png successfully with the following code:
var pathToImage = __dirname + "/../client_side_code/original_object_images";
fs.readdirSync(pathToImage).forEach(function(file,e) {
console.log(file);
});
Now, when I upload my application to a remote server (Heroku), the console says that this path can't be found. Specifically, I get the following error message in the console:
Error: ENOENT: no such file or directory, scandir '/app/server_side_code/../client_side_code/original_object_images
As you can see, the object00.png image can no longer be found. I thought using __dirname would also work on a remote server since it begins a relative path. Any thoughts as how I can allow this image to be accessed when it's hosted on a remote server?

Related

Express App on Azure cannot load static file, status 500

I am deploying an Node.js Express App on Azure and the app failed to load static css/js file. The static file works fine under my localhost:3000. But when running on Azure, it throw out Internal Server Error 500.
The error in my chrome looks like:
GET https:///resources/css/style.css net::ERR_ABORTED 500 (Internal Server Error). The directory tree for this css file is /public/resources/css
I assume that my static file path is correct, otherwise I would see a 404 error instead of 500
app.use(express.static(path.join(__dirname, 'public')));
Per my experience, I think the incorrect deployment cause the error code 500 of Internal Server Error in Node.js on Azure. So to fix it, please first check the content of your web.config file in the path site/wwwroot. And there is a standard sample web.config from Kudu wiki page Using a custom web.config for Node apps which you can refer to.
If your Node app deployed successed, you will see a 404 Not Found error code for a non-exist static file instead of 500 as you said.
However, there is a difference for the variable __dirname between local and Azure. On local, the value of __dirname variable is always the full path name where you start up a node process, such as print __dirname will return D:\home if run node in CMD at D:\home. But on Azure, you will see the __dirname value in any path which be . if you try to run the command node -e "const path = require('path'); console.log(__dirname);" in the Kudu console, as the figure below.
Therefore, the path.join(__dirname, 'public') value is always public which not be related to the current path of node started up by IIS. So to fix it, please use an absolute path like D:\home\site\wwwroot instead of __dirname variable in path.join method or just directly use D:\home\site\wwwroot\public in express.static method.
Solved!
I checked the DetailedErrors log files from Azure Diagnostic Tool. And it was showing the 500 error was due to the following:
HTTP Error 500.0 - Internal Server Error
D:\Python34\python.exe - The FastCGI process exited unexpectedly
In fact, in my Azure App Service application setting, I turn on the python 3.4 version and which somehow azure trying to handle my static request using python. I simply turn off the python version in my application setting and now I can successfully load my static file.

pug.compileFile('./views/transactions/html.pug'); Heroku Node Express. Error: ENOENT: no such file or directory, open

Error: ENOENT: no such file or directory, open './views/transactions/html.pug'
Running my application locally I don't have a problem, once I push to Heroku I get the above error. Locally I am using nodemon to serve my express server. I'm using pug to compile some html to send emails. This is the function that is causing the problem.
pug.compileFile('./views/transactions/html.pug')
Using node Express, with React, serving the static/build files from the same server.
My suspicion is that I need to serve the 'views' directory as when I am running locally my nodemon will be doing this, however, I 'm not sure how to do this.
This is a view of my server.js file.
I have a solution to the error message. I got this from this post about node/heroku filepaths.
The issue was that locally my file path was pointing to the correct file but the online/heroku server needed a different filepath. I have included a picture of the file structure for what it's worth.
function createEmailFilePath(filename) {
const newpath = process.env.NODE_ENV === 'production' ?
path.resolve('emails', 'transactions', filename) :
path.resolve('..', 'emails', 'transactions', filename);
return newpath;
}

readFileSync throws error when server launched as linux service

i'm trying to make a simple api for myself using a node/express server running on digital ocean. in the server file i have something like this:
var data = fs.readFileSync('path/to/data.json','utf8');
which works perfectly fine when i launch the server manually from the cmd line
node server
but what i have setup is a linux service so that everytime i restart my digital ocean machine it will automatically launch the server, the service ( kept in etc/init/ ) looks like this:
start on filesystem and started networking
respawn
exec node /path/to/server.js
the issue is that when I make the request to the server that runs the readFileSync call it works fine if the server had been launched manually from the cmd line, but when the server was launched via the service then the readFileSync throws the following error:
Error: ENOENT, no such file or directory 'path/to/data.json'
at Error (native)
at Object.fs.openSync (fs.js:500:18)
at Object.fs.readFileSync (fs.js:352:15)
the file and the directory do exist ( if i make a request for the data.json file directly in my browser i can see it )
what am i missing? is there something about launching the server as a service that conflics with using readFileSync? is there an alternative approach to what i'm trying to do? should i use some kind of request/fetch resource module for accessing that json file?
You're using a relative path but the process is not being started from where you think it is. Instead of using relative paths, use absolute paths.
So if your layout looks like:
server.js
path/
to/
data.json
Then inside your server.js, you can just do something like:
var path = require('path');
// ...
var data = fs.readFileSync(path.join(__dirname, 'path/to/data.json'), 'utf8');

trace logs of 404 on serving static content by nodejs

I set up a nodejs server in a file named 'server.js' as follow:
var connect = require('connect'),
serveStatic = require('serve-static');
var app = connect();
app.use(serveStatic(__dirname + "/angularjs"));
app.listen(1000);
I ran the code by executing command "node server.js" in cmd (windows 10).
I was be able to reach the 'app.html' file by browsing 'http://localhost:1000/app.html' but now it respond by 404 (not found) error.
I'm not sure what's changed.
How could I trace the logs of nodejs to find the problem?
I found the problem\solution myself:
I executed the 'server.js' inside the 'angularjs' folder so there was no 'angularjs' folder beside the 'server.js' to serve, I moved the 'server.js' to parent folder beside the 'angularjs' folder and it worked correctly.
Yet I curious about:
how to trace the "connect module" and\or "serve-static module" and\or nodejs itself.

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