I'm a PHP developer attempting node.js using express.js libraries for the first time. I've gotten a simple node.js static server running using express.staticand am now trying to move on to routing.
I have this routing rule:
app.get('/', function (req, res){
res.sendFile('index.html', {root: path.join(__dirname, '/finished')});
});
which returns index.html (url:localhost:port) fine, my problems are when I attempt to import from other directories in index.html's folder. I always get a 404 error.
Do I have to write rules for every file requested? Is there anyway to make a folder, or group of folders public?
Example (this works):
app.get('/components/webcomponentsjs/webcomponents.js', function (req, res){
res.sendFile('./components/webcomponentsjs/webcomponents.js');
});
There must be a way better way to do this. Any assistance and documentation appreciated, can't seem to connect the dots.
EDIT
express.static usage:
app.use(express.static(__dirname + '/root'));
Related
I'm learning Node.js with Express to get a little server running for studying. I'm getting response code 404 for all requests to files linked in my index.html file (e.g. the .css, .js, and image files).
The code I used to send index.html:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide/index.html"));
})
If I change the path to the whole folder instead:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide"));
})
I get in my browser the path from my hard drive to the folder, but I still can't view the files that way.
The clientSide folder contains index.html, app.js, style.css, and 2 or 3 images, all in the same folder. I can't view any of them.
I changed the filenames and folder name, and checked for capitalization to no avail.
SOLVED
I was using app.use(express.static(path.join(__dirname, "static/")));
With app = express();
That does not work, but using routes.use instead of app.use, while routes = express.Router();, is what solves that
The end
In your first code snippet, when you write:
routes.get('/', (req, res) => {
res.sendFile(path.join(__dirname, "/clientSide/index.html"));
})
You defined a new middleware function for requests to route /; that's what routes.get('/', ...) does. Assuming your server is running on port 3000, route / maps to http://127.0.0.1:3000/. For exactly that URL, and no other, Express executes your provided function, which replies with the the file clientSide/index.html. Thus, when your browser requests http://127.0.0.1:3000/, Express responds correctly.
But you've said nothing about the other files, such as http://127.0.0.1:3000/style.css, which would be route /style.css. You haven't defined any middleware for that route. So Express, not knowing what to do, by default responds with 404 and an error message. Thus, when your browser tries to load http://127.0.0.1:3000/style.css while fetching the resources referenced in index.html, the stylesheet fails to load.
Your second code snippet doesn't fix anything. It really makes things worse, because res.sendFile() can't send folders (how would that even work?) and that generates errors. You still haven't defined routes other than /, and now all your files are inaccessible.
To actually solve the problem, you could, theoretically, tediously define a route for every file, or more cleverly define one route with a route parameter. But serving a static folder with Express is a solved problem. You can simply offload the work to express.static by replacing all your code with:
routes.use(express.static(path.join(__dirname, "clientSide/")));
To go even further, you don't need Express or Node.js for a static file server. Try nginx. And for simple webpages, you don't need a server at all; just double-click index.html and let your browser open it.
I would like to show a custom 404 page (containing html, css, img, and ico). I know my 404 folder works when I replace the first public static homepage. However, I believe I am either not using routes the right way or it is not possible to set up two static folders.
I do not want to use template view engines at all. I want everything to be rendered on the frontend.
My project looks as follows:
404
--index.html
--error.css
--404.jpg
bin
--server.js
public
--index.html
routes
--index.js
package.json
app.js
app.js
...
var index = require(./routes/index); //works
...
app.use(favicon(__dirname + '/public/content/images/logo.ico'));
app.use(logger('dev'));
app.use(jsonParser);
app.use(urlencodedParser);
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public'))); //love it
app.use('/', index); //this is fine
...
index.js
var express = require('express');
const path = require('path');
var router = express.Router();
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});
router.use('/', express.static(path.join(__dirname, './404'))); // HALP!
module.exports = router;
I've played around with the directory (trying to use '404' vs './404'). I am testing this by entering "localhost:3000/error". So if my path is '/error', it should still use the parent path: '/'. The documentation states that as long as my route is placed last, it should still work. I tested it without express.static and used an anon function that prints error on console.
Is it impossible to use express.static() twice?
Moving some of my comments into an answer since this led to your solution.
For Express.js 4.x, is it possible to use express.static twice?
Yes, you can use express.static() as many times as you want. It is middleware and, if it does not find a file matching the request, it just calls next() and allows the middleware chain to continue. So, you can have as many of them as you want and they will each get to search for a matching file in the order you register them.
I would like to show a custom 404 page (containing html, css, img, and ico). I know my 404 folder works when I replace the first public static homepage. However, I believe I am either not using routes the right way or it is not possible to set up two static folders.
You are mistakenly trying to use express.static() to implement a custom 404 page. That is not what it does. The usual way to implement a custom 404 page is with the last middleware handler in the chain. When that gets hit, nothing else has found a match for the current request, therefore you send your custom 404 page.
That typically looks like this:
app.use(function(req, res, next) {
res.status(404).sendFile(localPathToYour404Page);
});
See the "How do I handle 404 responses" section of this Express starter FAQ.
And, here's an article on custom error pages that shows some other examples.
https://github.com/jekku/users/blob/master/server.js#L41
Here's how I route my static files on an ExpressJS app. I usually don't do it in the routes, but I consider it as an 'initialization' process. It is possible to use ANY middleware twice or even more - as much as you want, keep that in mind.
Is there a way to hide files that are being served by the Node server? I have tried to reroute certain files and directories, but nothing is working in Express 4.X. I have also tried to send 4XX HTTP responses when certain files are requested, but this only works for directory paths. No matter what I do, if there is a file that is being served by Node, then the user is going to be able to see the source code. Is this just how Express works? Is it meant to be a development framework over a production framework?
Right now I am trying to send bad responses.
full server.js
var path = require('path'),
express = require('express'),
var app = express();
app.use('/', express.static(__dirname));
app.use('/', express.static('dist'));
// not working
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
app.listen(3001, function() {
console.log('listening');
});
I am able to send a response if I specify a directory path, but not if I specify a full file path. This works:
app.get('/client/config/', function(req, res) {
res.sendStatus(400);
});
And this doesn't:
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
I've also tried routing with app.use. That didn't work either.
The best thing I can do right now to "hide" the source code is to uglify it with Gulp, but I imagine it's easy to unravel it with a JS prettifier.
one line culprit
app.use('/', express.static(__dirname));
That line is saying its ok to pull anything. You could replace it with:
app.use('/', express.static(__dirname + '/public'));
Then put stuff in the public directory you want viewed. For routes you want to have as priority, place them before the other declarations. So you would place:
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
above all else. However, seems like you may not need it if you just fix the first problem, then you are good. Also, see HTTP status codes. You would probably want 404 or 403 for that type of file.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
I finally got my node/express & mongodb running on Heroku...but how do I get at my frontend?
I am most familiar with a localHost setup, where I simply open my index.html, running localHost servers with MAMP..
When I load myapp.herokuapp.com, I see a JSON of my MongoDB docs (currently empty)
{
"docs": []
}
And when I go to myapp.heroku.com/index.html I get my 404 error..
Where.. 404
This all makes sense, according to my express code:
app.get('/', function (req, res) {
getAll(res);
});
app.get('*', function (req, res) {
res.send("Where.. 404", 404);
});
How do I get to my index.html frontend? Is there any more code that would be helpful to see..
what app.use() calls do you have?
In particular, if you want to serve static .html files you need to add something along these lines (assuming your static file are located in the ./public sub-dir):
app.use(express.static(__dirname + '/public'));
Further details: http://expressjs.com/api.html#app.use
I'm trying out a simple one page render and I'm obviously doing it wrong:
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.render('home.html');
});
app.listen(3000);
console.log('Listening on port 3000');
Error:
Error: Cannot find module 'html'
I want to load a page with CSS/images and wanted to know where to store the CSS/images/scripts/HTML and how to load it. I have yet to find many example express apps.
When using res.render, you are rendering a defined view. The documentation state:
Render a view with a callback responding with the rendered string.
When an error occurs next(err) is invoked internally.
For specific HTML, you either have to load the file with fs.readFile, or have Express use a rendering engine, such as Jade or EJS. For example, this code sample would apply the EJS render engine to all files with the extension .html.
app.engine('html', require('ejs').renderFile);
Then you can render a file like this. This is an example of passing variables to the HTML file, because that's what embedded JavaScript is used for.
app.get('/', function (req, res) {
res.render('/file', {
pass: 'arguments',
to: 'the file here'
});
});
That is more convenient than having to read the file on each load like so:
app.get('/', function (req, res) {
fs.readFile('/index.html', 'utf8', function (err, data) {
res.send(data);
});
});
Although this is aside from your question, this is how passing variables to EJS works. It even works with if statements and loops, since it accepts all JavaScript. Putting console.log in the file would log each time the file was rendered.
<span><%= pass %></span>
<!-- after rendering -->
<span>arguments</span>
If you need to serve other resources, such as CSS, JavaScript, or other html files, you could use Express' directory function.
app.use(express.static('/'));
Then you wouldn't need to render your HTML at all. It would be statically served.
I want to load a html with css/images and wanted to know what is the layout of where to store the css/img/js and the html and load it? I am yet to find many example express js apps.
Assuming that you have installed express, within your express project you will find public folder. within public folder you will find three folder - images, javascripts, and stylesheets . As the names suggest place your css/img/js in their respective folders.
You place static HTML files not using any templates in the in the express project public folder and invoke it using:
app.get('/', function(req, res) {
res.redirect('/home.html');
});