Express assets served through wildcard route - node.js

I've got a strange bug in my MEAN application whereby asset files are being served through my wildcard route.
I want to serve a single HTML file via express and let Angular take care of all the routing etc. That route is setup like so (defined after middleware):
app.get('*', function (req, res) {
res.sendfile('./app/www/index.html');
});
I'm using the express static middleware which is setup like this:
app.use(express.static(__dirname + './app/www'));
My project structure (simplified):
app
-- /www
---- /assets
---- index.html
app.js
When I load assets/app.js in the browser I see the code inside index.html. Why is the static middleware being ignored?

Related

Express App Serving Unwanted Static Files

I have a react app that is served by express. The entire app is included in public/index.html.
Right now my server.js looks like this:
1 const express = require('express');
2 const path = require('path');
3 const port = process.env.PORT || 8080;
4 const app = express();
5
6 // the __dirname is the current directory from where the script is running
7 app.use(express.static(__dirname));
8
9 app.get('*', (req, res) => {
10 res.sendFile(path.resolve(__dirname, 'public/index.html'));
11 });
12
13 app.listen(port);
However, somehow, files like package.json and /.ssh/known_hosts are being served, things that obviously shouldn't be avaialible.
I'm not sure why app.get('*', (req, res)... isn't catching all requests, and why app.use(express.static(__dirname)); seems to be the only configuration that allows my app to server ANY static files.
I haven't had any luck with app.use(express.static(__dirname+'/public')); or
app.use( '/', express.static(__dirname + '/public'));
or anything else I can find.
EDIT---
My project directory looks like:
/myproject
package.json
server.js
/public
index.html
I want ALL requests to simply serve index.html
What I'm still not understanding is why
app.use('*', express.static(path.resolve(__dirname,'/public/index.html')));
does not serve anything.
Also, why in the above example, res.sendFile() does nothing without first having called express.static(). If I delete line 7, then nothing is served.
So, never ever do this:
app.use(express.static(__dirname));
in your main server directory. That exposes ALL your server files to be viewed.
When using express.static() to serve a whole directory, you should create a directory that contains ONLY files intended for public consumption and then point express.static() at that.
I'm not sure why app.get('*', (req, res)... isn't catching all requests
Because that app.get('*', ...) is AFTER your express.static() so if the express.static() finds a matching file, the app.get('*', ...) never even sees the request. It's already handled and routing doesn't continue any more.
As always with express.static() to advise on exactly what you should do, we need to know the precise configuration you have. Where are the public files in your file system relative to your main server directory and what URLs are you intending to use in the client to refer to those publicly available files.
Here's a theoretical example (since you haven't provided your specifics):
Let's suppose you have files like this:
/myproject
app.js
/public
main.css
And, suppose you want to be able to use /main.css as the URL from the client. For that, you would just do this from within app.js:
app.use(express.static(path.join(__dirname, "public")));
In this first example, where you're serving these static files at the top level path, then you have to make sure there are no naming conflicts between these top level resources and any actual routes you want to serve.
If you wanted the client-side URLs to be /assets/main.css, then you would do this:
app.use("/assets", express.static(path.join(__dirname, "public")));
In this example, you must make sure that the /public sub-directory (and any sub-directories it might have) contains only files intended to be publicly accessible.
Adding a path to the public URL such as /assets removes the chance of a naming conflict between your static assets and your top level routes. This can be a good thing because in any multi-person project, it's not uncommon that the person working on the static assets (like CSS files) is different than the person working on server routes so the two main not be directly aware of what names each other is using. In a single person project, you would certainly just keep it all in your head and avoid accidental naming conflicts that way.
FYI, my preference for folder organization is more like this:
/myproject
/server
app.js
/public
main.css
Where it's 100% obvious which are server files and which are public files. Then, to serve the public files from within app.js with a URL of /assets/main.css, I'd do this:
app.use("/assets", express.static(path.join(__dirname, "../public")));
From your comments:
I just want to serve public/index.html for all ('*') GET requests. All other data comes from separate apis. it seems that res.sendFile() doesn't work without first using express.static. The above code resides in server.js
If all you want to do is to serve public/index.html for all requests (where public is a sub-directory below where app.js is located), then remove the express.static() middleware entirely.
Just use this from app.js:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
});
remove app.use(express.static(__dirname));
as that tells express to load all files that exist
app.use(express.static(__dirname)); will make your app insecure.
Always print out the URLs in the console like path.resolve(__dirname, 'public/index.html') to find out if there is something wrong in it. Seems aiming to the root directory for static files makes problem. Put them in the conventional public directory then try it out again

How to create a node based server to serve REST API and also deploy the application.

I am new to nodeJS server area, need help in understanding how to work with REST API (using express) and deploy the angular application over a singe node server and same ports.
By deploying i want to understand if user hit below url http://localhost:8000/<page_name> then the specified page should open.
And is user hit below url using get or post request
http://localhost:8000/api/<api_name> then a json or a text will be returned.
How to run both the thing over a single node server.
Lets assume, you have all your static files in the /public folder of you app. Generally spoken, if you are using express.static, you should also get your index.html because this is handled by default for each directory.
In your case, as you are using Angular, the routing is handled from the client side (SPA). You should only have one single index.html after building your Angular app. All files from your dist folder should then be placed into your /public folder. Then you need to make sure, that initial file serving provides your index.html like so:
In this example static files are served first, then your API and if nothing is found, you are getting back you index file.
const express = require('express');
const app = express();
// serve static files
app.static(__dirname + '/public'));
// serve your API
app.get('/api/welcome', function (req, res) {
res.send('Welcome');
});
// fallback routing (server side handling)
app.get(/.*/, function (req, res) {
res.sendFile(__dirname + ‘/public/index.html‘
});
app.listen(3000);
Next time please make sure, to give all necessary information in your question ;-)
With the help from Sebastian, so far I can find a solution but its not working when i am hitting URL for different pages.
const express = require('express');
const app = express();
app.use(express.static('public'))
Please provide your suggestions.

Angularjs4 with express generator

Just developed a simple angular 4 application with this tutorial
https://scotch.io/tutorials/mean-app-with-angular-2-and-the-angular-cli
But how can i integrate angular 4 app to a express application that generated with express generator??.
One approach is REST API's method that is express JS app use as API provider and the angular application communicate with REST api.
But i would like to serve the angular application from express application itself..
I think this will helpful to you. First I assume, you use express server to handle some api request and let's say those routes are begin with /api. they can be differ from yours.
First build your angular application by ng build and it will create a folder called /dist in your project folder.
Copy that folder in to your express project /public folder. You have to put them in an static routed folder. /public folder is a default static route folder. That is why I put it there. If you have your own one, you can put there too.
edit your app.js file as follows
// Set our api routes
app.use('/api', api); // API router definitions.
// Catch all other routes and return the index file
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
Hope you will help this way. Thanks.
You can serve it through your server like this:
// Catch root route and return index.html
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'app/index.html'));
});
// Catch all other routes
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'app', req.originalUrl));
});
But be careful to set the right path to your index.html.
There is a technology stack called MEAN which means (coincidence :) MongoDB, Express, Angular and Nodejs. So this is basically what you are looking for.
Altough you can create you own file structure, there is a mean-cli similar to Express-generator and the angular-cli. You can find it here.
In order for Angular to work properly (like requesting a site like example.com/something and then also activate the route something) I always return my index.html for any request and setup express to return all static files as well. Then I create a route /api which handles all my REST api requests.
Make sure to first setup your /api route, then your other static files from angular like bundle.js and finally index.html as route **.

Angular in a NodeJs Server

I'm beginner in Angular. I have a nodejs server and I have Angular for the front end. Now I would like to know if it's possible to have just one server for both ?
Because in some videos from youtube, they had one server for node and one server for angular.
Thank you, bye
At a basic level you'd need to set the static path for your built, static Angular files and if you are using Angular routing you'd probably want to direct all requests to your index.html of the Angular project so that Angular can handle all client side routing.
For example, setting the static path for a built Angular CLI project that sits in the default public folder created by express-generator. The example uses dist as that is the default destination of the Angular CLI project when you execute ng build.
app.use(express.static(path.join(__dirname, 'public', 'dist')));
Catch-all route to direct any requests not caught by your Express application route definitions, such as RESTful routes returning JSON data or similar, to the Angular project's index.html:
// some routes
var users = require('./routes/users');
app.use('/users', users);
// other routes
var todos = require('./routes/todos');
app.use('/todos', todos);
// catch-all route
// needs to go AFTER all other express server route definitions
app.use('*', (req, res) => res.sendFile(path.join(__dirname, 'public', 'dist', 'index.html')));
If using Angular CLI, during development you can run the projects separately, using a proxy.
Hopefully that helps!
Yes, it's possible to have one server for both.
You can serve your AngularJS files via your favourite HTTP server (e.g. express) on your NodeJS server as static files like so:
app.use(express.static(path.join(__dirname, 'client')))
Where client is the directory containing your front-end content.

Express: Redirect '/' to specific route

I'm asking for help after being unable to find a solution through other SO questions.
I'm doing some modular express app. This is the regarding part of my server.js file.
var app = express();
var login = require('./lib/login');
app.use(login);
app.use(express.static(path.join(__dirname, 'public')));
If I hit localhost:3000 It goes straight to public/index.html. But I want it to go to the login route. I've tried something like:
app.get('/', function(req, res){
res.redirect(__dirname + '/lib/login');
});
But it's not even being called since it always goes to index.html. Guess the line app.use(express.static(path.join(__dirname, 'public'))); is doing that from the get go. And Even if I comment that like for testing server's not redirecting to the route so I guess my code's not accurate.
I should add that inside the login route there's a jade template.
Any ideas?
More Information
Structure
/node_modules
/public
/javascripts
/stylesheets
/lib
/login
/views
server.js
Inside the public folder there's the index.html file that's being called. It's there just for testing, it has nothing to do with the real jade files I want to render.
I first added the app.use(express.static(path.join(__dirname, 'public'))); line so I can load my javascripts and my stylesheets in my jade templates with something like script(src='/javascripts/jquery.dataTables.js'). If I remove that original line from my server.js it DOES route / to login but then I can't seem to load those libraries inside javascripts and stylesheets, even if I change script(src='/javascripts/... to script(src='/public/javascripts/...

Resources