Express App on Azure cannot load static file, status 500 - node.js

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.

Related

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.

Microsoft.WindowsAzure Exception: The remote server returned an error: (503)

After I deploy my web app to window Azure.I access my web app,the server return error 503.
it look like the server did not start, the file starter.cmd is empty(only #%*).
log:
2019-08-19T03:23:55.2310991Z,Using start-up script start.js from package.json.,,0
2019-08-19T03:23:55.2310991Z,The iisnode.yml file explicitly sets nodeProcessCommandLine. Automatic node.js version selection is turned off.,,0
2019-08-19T03:23:55.2467314Z,Selected npm version 6.4.1,,0
2019-08-19T03:23:55.2623494Z,The syntax of the command is incorrect.,,1
2019-08-19T03:23:55.2936133Z,The syntax of the command is incorrect.\r\nD:\Program Files (x86)\SiteExtensions\Kudu\84.10807.4030\bin\Scripts\starter.cmd deploy.cmd,,2
You could use Kudu console (https://yoursite.scm.azurewebsites.net) - Review the logs to fetch more on the error -Node.exe crashed – check d:\home\LogFiles\logging-errors.txt for stack trace and check win32 error code for more details.
In Azure App Service, the app is run in IIS using iisnode. To enable the app to run with iisnode, the root app directory contains a web.config file. The file is readable by IIS, and the iisnode-related settings are documented in the iisnode GitHub repository.
You could download the sample Node.js project from https://github.com/Azure-Samples/nodejs-docs-hello-world/archive/master.zip and extract the ZIP archive and change based on your requirement.
Open index.js and find the following line:
const port = process.env.PORT || 1337;
App Service injects process.env.PORT into your application, so the code uses the variable to know which port to listen.
NODE.exe has a setting called NODE_PENDING_PIPE_INSTANCES. On Azure App Service, this value is set to 5000. Meaning that node.exe can accept 5000 requests at a time on the named pipe. This value should be good enough for most node applications running on Azure App Service. You should not see 503.1003 on Azure App Service because of the high value for the NODE_PENDING_PIPE_INSTANCES.
Kindly let us know, I have answered your similar question here.

Node on Azure App Service how does it start up?

I have an Angular Universal app that I am deploying to Azure App Service (Windows).
When the app runs locally on my Windows 10 PC it works fine but in the cloud it seems like the process.cwd() is different than when I run it locally. This is causing Express.js to look in the wrong place for some view files.
The process pwc should be based on how I executed node, in my case I have a start script in my package.json that executes "node dist/server.js". But I can remove this script and Azure will still start my app. So I think the root of my pwc problem is in how Azure starts up my node app.
Unfortunately Microsoft thinks that some code snippets and a couple John Papa videos is good enough documentation for developers to resolve issues.
Questions
Does documentation exist that explains any configuration or
conventions that the App Service uses to init my node app? Where is
it?
Given the script "start": "node dist/server.js" why would process.cwd() be different on my local host versus Azure App Service? The file structure is the same in both places.
const DIST_FOLDER = join(process.cwd(), 'dist');
app.set('views', join(DIST_FOLDER, 'browser'));
Error: Failed to lookup view "index" in views directory "D:\home\site\wwwroot\dist\dist\browser"
root
package.json
dist
server.js
browser (client app)
server (server app)
Documentation: Not an exhaustive guide, but this is what I found useful on MSDN forums:
Windows Azure Websites uses IISNode to host the Node process inside of IIS. Your Node site is actually given a Named Pipe which receives the incoming requests, not a TCP port like you would use when running locally or hosting yourself.
...
As a node.js application running on Azure Web Apps, needs a server.js or app.js file as the entrance in the root directory with a web.config file to control the iis
Working Directory: When web.config and iisnode are used to run server.js, the rules rewrite the directory to point to where server.js resides. That is why it isn't able to find a subfolder 'dist'.
I had to change the line above to this, in order for it to work on Azure:
const DIST_FOLDER = process.cwd();
Another thing I found important was to set the right version of node for your App Service, using WEBSITE_NODE_DEFAULT_VERSION in App Settings. Here's a bit more info on that from a blog on MDSN - NodeJs and NPM versions on Azure App Services
Since I am used to hosting Node apps on Linux this totally slipped my mind. The answer is...
see web.config
If anyone else finds themselves here put this in your server.ts file to work both locally and on azure
import * as fs from 'fs';
const distFolderExists = fs.existsSync(join(process.cwd(), 'dist'));
const DIST_FOLDER = distFolderExists ? join(process.cwd(), 'dist') : process.cwd();
big thanks to KayS for their answer - really helpful.

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