Serving static files in node.js - 500 internal server error - javascript

I'm having a weird issue where our staging server is throwing a 500 error when trying to retrieve css or js assets. We are using broccoli to compile the assets to a distribution directory, so I have ~/dist/assets/app.css (as well as app.js and an img directory). Images seem to be served fine! Only the app.js and app.css files are throwing the 500 error. I've ensured the files definitely exist in their proper places.
We're using express.js and the serve-static module. Code is simply:
serveStatic = require('serve-static');
app.use(serveStatic('dist/assets'));
Then hitting 'http://url.com/assets/app.css' throws the 500.
Hitting 'http://url.com/app.css' WORKS. This seems like it would be okay (since I'm serving dist/assets so the request should be relative to /assets), but this was all working with the /assets prefix on the request a few days ago.
There is no error output produced in the logs anywhere. Stumped on this one.
I just want to make sure I'm not doing anything too dumb.

Have you tried this:
serveStatic = require('serve-static');
app.use(serveStatic('dist'));
serveStatic(root, options)
Create a new middleware function to serve files from within a given
root directory.
Based on that statement, you should expect that using "serveStatic('dist/assets')" will serve the app.css from http://url.com/app.css

Related

Node.js source code getting sent over to client

I'm building with Node.js locally and I came along a weird problem where if I typed localhost:8080/server.js, the whole server-side source code shows up in the browser (the server file's name is server.js). I guess what's happening is the server looks for server.js, finds itself in the directory and sends it over. That's a huge security risk right? Any way to solve it?
All my code files are present in the same folder; would changing that be the best way to fix the problem?
Since index.html and server.js are in the same folder then the server will send server.js when requested because it thinks it's javascript code for the client and not the server.
You should put the files you want to serve in sub folder (usually named public) like this:
public/index.html
public/style.css
then start the server using that folder with:
app.use(express.static("public"))

Why will my MEAN app only (partially) run when I set the Angular build directory to /src/ instead of /dist/?

I'm following Heroku's tutorial to create a contact list using the MEAN stack (Heroku's running example here). I'm able to deploy it to Heroku and it works there. But when I run it locally on my machine, the browser (Chrome 67.0.3396.87 on macOS High Sierra) only displays a "Cannot GET /" message.
I believe it's related to how the Angular build directory /dist/ referenced in line 12 of server.js does not exist (as far as I can tell). The beginning of server.js looks like this:
var express = require("express");
var bodyParser = require("body-parser");
var mongodb = require("mongodb");
var ObjectID = mongodb.ObjectID;
var CONTACTS_COLLECTION = "contacts";
var app = express();
app.use(bodyParser.json());
// Create link to Angular build directory
var distDir = __dirname + "/dist/";
app.use(express.static(distDir));
// Create a database variable outside of the database connection callback to reuse the connection pool in your app.
var db;
I looked into it and found that Angular deletes the /dist/ directory upon ng serve. I also found that there is a flag --delete-output-path whose default is true.
I set the --delete-output-path flag to false in .angular-cli.json as recommended by this answer as well as in /node_modules/#angular/cli/lib/config/schema.json. Despite those changes (trying to set the flag in one file, or the other file, or both files at the same time), I'm still getting the "Cannot GET /" message and the /dist/ directory still doesn't appear to be there.
The only way I've been able to even run part of the app is to change server.js's line 12 reference from /dist/ to /src/. This allows /src/index.html to begin loading at localhost:5000/ (the browser displays the text "Loading..." as specified in line 16 of index.html) and gets the contacts API up and running at localhost:5000/api/contacts/. But the Angular components (the list of contacts that is the purpose of the tutorial) don't load. Maybe because I changed the build directory to a totally different location.
Is there something with the /dist/ directory that I'm missing? Or does my issue with getting the app to run locally have nothing to do with /dist/ at all?
Notice that you don't have a way of handling requests to the route '/' since the line:
app.use(express.static(distDir));
only ensures that all bundled files generated in your "dist" folder are accessible when your index.html requires them, but you still have to serve the index.html itself. When using the MEAN stack one normally would do something like this:
app.use ('/api', yourApiRouter);
//and for everything else let the client-side routing handle the route:
app.get ('*', function(req, res) {
res.sendFile(distDir + 'index.html');
}
I recommend to use the native "path" module to join your __dirname with your "dist" folder and your index.html location rather than simple concatenation.
You can use an arrow function instead of a callback when using app.get function if you are using ES6

How can i get Express.js to serve after being Webpacked?

I'm trying to get a system together for transpiling my Node server (Express in this case) down, much in the same way as my client side scripts - with webpack.
The Express server is pretty basic. I import some node_modules and some local, relative files. Webpack seems to have no trouble parsing everything, importing the relative files and simply require()'ing node_modules (thanks to externals).
However, when I run the server (with node server.js) after webpacking, it get an error trying to access my index.html.
Error: ENOENT: no such file or directory, stat '/public/index.html'
at Error (native)
The server reports it is listening on 3000, but every attempted access logs this error and displays it in browser. I'm sending a premade HTML file with the following:
res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
I've searched and discovered people using the babel-cli for just using Babel (and presets) alone to just run that on designated Node code, but then I cannot resolve any of the module paths.
Has anyone else successfully transpiled a Node server application and gotten it to actually serve? Should I use a different function to serving my client-side? Should I be going about this in a different way rather than Webpack?
I had the same problem with webpacked Express and this fixed it:
response.sendFile(path.resolve('./public/index.html'), err => err && next(err));
In my case the server.js and server.bundle.js files are in the root folder of my project.
If that's different in your case you can try:
response.sendFile(path.resolve('./public/index.html'), { root: __dirname }, err => err && next(err));

Production Node Application Can't Find SVG Files

In my local development application the svg files show up just fine with the following code (The curly brackets embed Angular.js variables):
<img ng-src="img/servant_{{servant.personality}}.svg" draggable="false">
But when deployed on Heroku, the SVG files result in a 404:
Failed to load resource: the server responded with a status of 404 (Not Found)
The Angular variable is working on the Production site and the image addresses are accurate. So, that's not the problem.
Instead, I think my Node/Express application might not be able to serve SVG files. Perhaps it's a Heroku issue? FYI I'm using the MEAN stack.
Here is the configuration of my public folder:
//Setting the fav icon and static folder
app.use(express.static(config.root + '/public'));
The images are in
public/img
Any thoughts?
Ensure you have the correct mime-type configured to serve SVG files. Some servers simply respond with a 404 if the mime for the requested file type is not set.
image/svg+xml

Node.js /socket.io/socket.io.js not found express 4.0

So I'm trying to get chat working on my website, and when I was testing locally it worked great, because port 8080 on my localhost was available and all that good stuff. But now I pushed my code to my Heroku app, and when I try and load my chat page, I get the error stating that it can't get localhost:8080/socket.io/socket.io.js.
I've seen node.js /socket.io/socket.io.js not found
and tried the suggestions, but none worked, even moving the socket.io.js file into a resource file did not work. I'm guessing this is because I'm using express 4.0?
Any help would be appreciated
Thanks
Edit:
So to add more details, since my question could seem a little vague, here is my relevant app.js code:
var client = require('socket.io').listen(8080).sockets;
In my jade file for the chat page, I have:
script (src = `'http://localhost:8080/socket.io/socket.io.js`')
and later on
var socket = io.connect(`'http://localhost:8080`');
and all this works on localhost (I load up on port 5000, socket.io is connected to port 8080). I do this using 'foreman start' with the heroku toolbelt.
When I try and change these to work on heroku, it breaks and I'm not sure how to fix it. I hope this clarifies the question a bit.
Edit 2:
I'm running:
express 4.0.0
socket.io 0.9.16
node 0.10.x
Thanks
Do you have an explicit route in express which catches all other routes? Something like this perhaps:
app.get("/", handlers.home);
app.get("/..." ...);
...
app.get("*", handlers.error);
This might keep socket.io from being able to host it's own js file for the client. There is an easy way to fix this, since you probably already have a public or static folder setup in express. Something like:
app.use(express.static("public"));
Make a new folder called socket.io and copy over the appropriate socket.io.js file into said folder, and all should be well. However note that there are two files named socket.io.js!! So, if you see something like "Uncaught ReferenceError: require is not defined" it means you copied the "node-ey" server side file. Here is the correct client file to copy:
app_dir/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.min.js
Note #BHendricks: I would have just posted as a reply to your comment, but I currently lack the required reputation.
Edit:
The OPs question probably has more to do with the "localhost" issue. When connecting from a client (say your home IP), as far as your browser knows - localhost implies a connection with the machine which is locally hosting stuff. Since your home machine (or phone) does not host socket.io, this is failing.
What you need to do is have your server embed the socket connection information (either a fully qualified hostname, ip etc). This can be done when the server "renders" the page with the client connection.
What happens when you go to http://localhost:8080/socket.io/socket.io.js?
Does it 404? If it does you need to make sure you have it in a directory that Express is set to serve statically.
app.use(express.static(__dirname + '/public'));
Then put your socket.io.js file in public/socket.io/socket.io.js (relative to your app.js file)
Restart your server and see if that fixes it.
Basically, Express doesn't serve files statically from the file system unless you explicitly tell it where to map from.

Categories

Resources