Learning Node - Express Public folder not working - node.js

So I'm new to node and trying to learn how to use the express library with it. However, the problem I'm trying to figure out is why the files in my /public folder do not seem to be served as static content.
Here's my code:
var http = require('http');
var port = process.env.port || 1337;
var express = require('express');
var handlebars = require('express3-handlebars');
var path = require('path');
var application = express();
application.use(express.static(path.join(__dirname, 'public')));
application.engine('handlebars', handlebars({ defaultLayout: 'main' }));
application.get('/', function(req, res){
res.render('index.handlebars', { someProp: 3 });
});
application.listen(port);
And my directory structure:
/
- server.js (the above referenced file)
/ Views
- index.handlebars
/ Layouts
- main.handlebars
/ public
- ServeMe.txt
My understanding was that application.use(express.static(path.join(__dirname, 'public'))); was supposed to configure the server to respond to any request under the public folder with that resource if found. What am I doing wrong? Funnily enough, it was easier to configure handlebars as the view engine than to get this public folder working =D
EDIT: The full URL I am trying to request:
http://localhost:1337/public/serveme.txt
I've tried case sensitivity (which should be a non-issue), and that also did not work.

The full URL I am trying to request: http://localhost:1337/public/serveme.txt
That's your problem. Anything inside the directory you designate as static content is made available directly from the base URL. You need to request http://localhost:1337/serveme.txt instead.
If you want to only serve static files from /public you can pass a string as the first argument:
application.use("/public", express.static(path.join(__dirname, 'public')));

From the Express API reference
app.use(express.static(__dirname + '/public'));
This line serves your public folder at your app's root URL, meaning the following requests are valid and don't give a 404 error.
// GET /javascripts/jquery.js
// GET /style.css
// GET /favicon.ico
app.use takes an optional first argument as well that allows you to specify which request URL you want to serve content at. This first argument defaults to "/", meaning your static content will be served at the base URL. If you want your static content to be served not at the root level, like your code currently does, check out the following example (again taken from the docs)
app.use('/static', express.static(__dirname + '/public'));
This line serves your public folder again, but at your app's /static URL, making the following requests valid without a 404 error.
(Example URL: http://localhost:1337/static/anythingInYourPublicFolder)
// GET /static/javascripts/jquery.js
// GET /static/style.css
// GET /static/favicon.ico

What URLs are you trying to load? You should not include "public" in your URLs, so curl -v 'http://localhost:1337/ServeMe.txt'.

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

Reaching html file in another subfolder express.js

My folder hierarchy is as follows;
public
----index.html
src
----server.js
when I run the code
var express = require('express');
var app = express();
var serv = require('http').Server(app);
var net = require('net');
var path = require('path');
var port = 3000;
app.use('/../public/', express.static(path.join(__dirname + '/../public/')));
app.get('/', function(req,res){
res.sendFile(__dirname + '/../public/index.html');
});
serv.listen(3000, function(){
console.log('port ' + port + ' is started to being listened')
});
var io = require('socket.io')(serv,{});
it returns forbidden error. How can I reach a file in another subfile?
First of all, what I thought solved it actually didn't solve because I am running multiple projects to understand the basics and I was confused. But now everything is clear. What I am actually trying to do is trying to use express to divide everything to folders. As I didn't know much about http, I watched a lot of videos and finally, I figured it out after watching official introduction video of express on youtube.
Here again what I am trying to accomplish;
-localhost
--public
---index.html
--src
---all server js files and other files that will concern game programming.
As I was trying to reach above, I couldn't manage to do it. What did actually do the trick is;
creating a variable that specifies 'public' directory which is another sub directory under localhost and use it as static which was simple from the beginning but as I didn't know much, I wasn't able to use it after studying few tutorials. As Michael mentioned above, I didn't even need following lines;
app.get(publicDir, function(req, res){
res.sendFile('index.html');
})
All I did was;
var publicDir = require('path').join(__dirname, '/../public');
app.use(express.static(publicDir));
app.use('/../public/'
doesn't really make sense. This parameter is representing the request URL. You can't listen for request URL's which are in the hierarchy somewhere else but not inside your root folder.
Remember that app.use('/' equals a request URL like http://localhost:3000 - meaning this is the absolute basis of the website - the so called root. So where should '/../public' point to? There is no URL with which you could reach such an address.
If you write app.use('/public' it will listen for requests on http://localhost:3000/public
But of course you can send files located in a file structure like you have. So probably what you wanted is:
app.use(express.static(__dirname + '/../public'));
in order to search the static files in a folder structure like:
public
-styles.css
-script.js
-index.html
server
-currentscript.js
where you could access static files like http://localhost:3000/styles.css
You can also completely remove this controller:
app.get('/', function(req,res){
res.sendFile(__dirname + '/../public/index.html');
});
static files like HTML are already served by the Express static files controller mentioned above.
This is enough to access your index.html by calling http://localhost:3000

Access to mountpath variable from inside a template using express

Is there a clean, recomended way to access the mountpath from inside a template, so an express app can be run both standalone and as a part of another app (by means of app.use), with the paths pointing to the correct destination either way?
Something like:
{{mountpath}}route/to/file
So in the case that the app is running standalone, mountpath will be /, and in case is running as a submodule, mountpath could be /foo/
Note: I'm using handlebars.
express.static middleware is responsible for serving the static assets of an Express application.
How it works:
Serve static content for the app from the "public" directory in the application directory
// GET /style.css etc
app.use(express.static(__dirname + '/public'));
Mount the middleware at "/static" to serve static content only when their request path is prefixed with "/static"
// GET /static/style.css etc.
app.use('/static', express.static(__dirname + '/public'));
Serve static files from multiple directories, but give precedence to "./public" over the others
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/files'));
app.use(express.static(__dirname + '/uploads'));
In your case you can use the second case i.e.; mounting files on path '/static', so whatever files are under the folder public can be accesses with src='/static/filename.xyz'
Create a folder name public with sub folders css, js, images
Or if you want your css to be mounted on path /css then you do :
app.use('/css',express.static(path.join(__dirname, 'module1/css')));
Now you can use all your css files in your entire application as :
<link href="css/style.css" rel="stylesheet">
There is an event that is fired after the module is mounted, so I can do:
app.locals.modulePath = "/";
app.on('mount', function (parent) {
app.locals.modulePath = app.mountpath;
});
The locals are directly accessible from inside all the views, so this will be accessible like {{modulePath}}
I had the same issue - needed to use mountpath from inside a template.
Solution that works for me is based on 2 facts
mountpath is available in request - req.baseUrl
response locals object gets exported to the template - res.locals
First, create a one-line middleware - this will apply to all routes inside the module/subapp
router.use(function (req, res, next) {
res.locals.baseUrl = req.baseUrl;
next();
});
Then inside the template use #{baseUrl}/some/route - note that this is jade syntax, but I suppose it works the same way with handlebars.

expressjs - not sending the file from view config

In my node app, I configured the views folder, later simply I am passing the html name alone. now the html file need to load from using the views config + html file right. ( am I wrong!)
But it's not working. any one give me the suggestion please?
here is my code :
var express = require('express'),
http = require('http'),
jade = require('jade'),
app = express();
app.set('view engine', 'jade');
app.set('views', __dirname + '/views'); // i configured the path so i am passing file name alone on get.
app.get('/', function(req,res){
res.sendfile('index.html'); //it's not working
res.sendfile('views/index.html') //it works
});
http.createServer(app).listen(3000, function () {
console.log('Express server listening on port ');
});
thanks in advance
You appear to have a misconception about what the view engine is. The view engine takes some non-HTML code, and transforms it into HTML. Here, you have it set to use jade.
The view engine is only good with the res.render() function. res.sendfile() merely sends a file from the current directory -- not the views directory.
Using express if you want to serve some static HTML files. You can just put those files directly in public folder.
When server will get a GET request of / it will search for /public/index.html serve that as response. You don't have to add router for that /.
Other wise if you want to use some template views then you have to use some views engine.

How does express know the difference between a static and a dynamic request?

This is the code that I see everywhere for a simple static web server using node.js and express:
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(8080);
My question is how does express know when the request is for a static page vs. a dynamic page? For example, why would /index.html be served from the public folder and not from dynamic templates?
Thanks.
You can think of the routes you define as a chain of checks on the path defined in the URL. Express iterates one by one through each check looking for a match; once it finds one, it executes that callback.
In this case, express.static is defining a bunch of path checks for each file in the public directory. If you app.use(express.static(__dirname + '/public')); before your app.get('/index.html', function(req, res) { ... code, and there is an index.html file in there, it will use the static file over the dynamic one.
That's basically it.

Resources