Multiple routes for static html pages in Express - node.js

I am trying to serve 2 static HTML pages from Express but whilst the index.html is correctly served I get an error when I try to access the /about route:
Error: ENOENT: no such file or directory, stat
'/var/www/html/myapp/about.html'
at Error (native)
var express = require('express'),
app = express(),
http = require('http'),
httpServer = http.Server(app);
app.use(express.static(__dirname + '/html_files'));
app.get('/', function(req, res) {
res.sendfile(__dirname + '/index.html');
});
app.get('/about', function(req, res) {
res.sendfile(__dirname + '/about.html');
});
app.listen(3000);
I can update the '/about.html' to '/html_files/about.html' and then it works but whilst this solves the issue I can't understand why it wouldn't work as it is.

Looks correct.
app.get('/'... will be ignored, as server already has found static index.html matching this request.
app.get('/about'... fails because of incorrect url to file you're trying to send. If you ask for /about.html it'll be sent by static middleware correctly.

Related

bodyParser middleware not working when adding static route

I'm a newbie on express, and when I was creating a simple server demo I detected that POST requests were not sent. After doing some experiments I discovered that it was the express.static middleware, that somehow was interfering. I supposed it was a common error, but didn't manage to find a clue. My code is the following:
//jshint esversion:6
import express from "express";
import path from "path";
import { fileURLToPath } from "url";
import bodyParser from "body-parser";
import https from "https";
/* jshint ignore:start */
const __filename = fileURLToPath(import.meta.url);
/* jshint ignore:end */
const __dirname = path.dirname(__filename);
const app = express();
const port = 8080;
app.use(express.static(__dirname + "/public"));
app.use("/", bodyParser.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.post("/", function (req, res) {
let name = req.body.name;
let email = req.body.email;
let message = req.body.message;
res.send("POST request to the homepage");
console.log(req.body);
});
app.listen(port, () => console.log(`Listening on port ${port}!`));
I'll gladly appreciate any answer or commet :)
EDIT: Apparently this error doesn't occur on Firefox, but does on Chrome and Edge
Based on your symptoms of the POST not even being sent from the client when you added the express.static(), I would guess that when you go to the / route in your browser, that express.static() was picking up an index.html from your public directory rather than the index.html that you wanted from here:
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
You can fix that two ways. Either move this app.get("/", ...) route before the express.static() route or tell the express.static route to NOT serve index.html like this:
// set up static file handling, but don't serve index.html for the / request
app.use(express.static(__dirname + "/public", {index: false}));
Ok figured out what was really blocking this.
When adding express.static() it loaded the JS for the front-end, which has the following line:
$(".sendMessageBtn").attr("disabled", "true");
which disables the submit button. Turns out disabling it also means it can't send anything BUT only on chromium browsers. This does not happen on Firefox.
To disable it without causing this mess, you can replace with:
$(".sendMessageBtn").css("pointer-events", "none");
Instead of disabling it through HTML, it uses CSS
So the way express static file serving works is that you put a /path which you want to serve on, and the term express.static(/path/to/static/folder) which will be published to the api.
Otherwise your entire application will be static, due to the fact that everything start with /.
See the docs for more info.
In your case:
app.use("/your-static-endpoint", express.static(__dirname + "/public"));
One more thing about your code. Stuff like static serving, error handling, body parsing are called middlewares, so if you want to apply them through the application, you shouldn't specify a path, because it might interfere with how express handles routing.

Receiving 404 status when trying to load local files with NodeJS

I am relatively new to using Node and am trying to make a simple HTML page that can get images, stylesheets, and scripts locally. Every time I try to load a local file, it returns a 404 status. I have tried multiple solutions from StackOverflow and other sources and still cannot get this to work.
Here is my code in app.js:
const app = require('express')();
const http = require('http').createServer(app);
var portNumber = 8085;
app.get('/', function(reg, res) {
res.sendFile(__dirname + '/index.html');
});
http.listen(portNumber, function() {
console.log('Listening on port ' + portNumber);
});
I have a CSS file at public > stylesheets > style.css linked to my HTML document.
<link rel="stylesheet" type="text/css" href="public/stylesheets/style.css" />
I get a 404 error in my browser's console. I also get a MIME error:
The resource from “http://localhost:8085/public/stylesheets/style.css” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).
Any local images I try to load also give a 404 error.
I have tried adding app.use(express.static('public')); to make the public folder the root to serve static content as shown in the Express documentation, but I still got 404 errors.
const express = require('express');
const app = express();
const http = require('http').createServer(app);
var portNumber = 8085;
app.use(express.static('public'));
app.get('/', function(reg, res) {
res.sendFile(__dirname + '/index.html');
});
http.listen(portNumber, function() {
console.log('Listening on port ' + portNumber);
});
I am not sure what I am supposed to do. All I want is to be able to load local files in my HTML document. How do I get these files to be displayed publicly instead of giving a 404 error?
The reason for the mime error is actually confusing - it's due to the browser not being able to find that file.
Remove the /public part of the path location as that is the folder so it's being served from:
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css" />
Same for all your other static files: /assets/mypic.png etc
Update your location for the static path as follows:
app.use(express.static(path.join(__dirname, 'public'), {index: false}));
Then, update sendFile to use and absolute path as follows:
return res.sendfile(path.resolve('./index.html'));
// or
return res.sendfile(path.join(__dirname, 'index.html'));
You should try using
app.use(express.static(__dirname + "/public"));
That way express knows where to search for that public folder.

Why is expressjs returning the error "Cannot GET /" in the browser from code below?

Using the code below with nodejs, expressjs, socket io and pug
the browser response is Cannot GET /
Have had same or similar response to get in other code
Have index.pug file in root and views (just in case)
Tried various permutations such as "/", "./", "/views", "/views" etc
const express = require('express')
const socket = require('socket.io')
const app = express();
app.set('view engine','pug')
app.get("./", function(req, res){
res.render("home");
})
const runServer = app.listen(8585, ()=> console.log('server is running at 1 27.0.0.1:8585'))
Server runs at localhost:8585 in terminal (GIT bash) OK
Expected result: "Home" page in browser
Actual result: the browser when "./" response is Cannot GET /
If using "/" (vs "./") then terminal and browser either crash or respond with blank
Have you got a route for GET / set?
router.route('/').get(function (req, res) {
res.send('app successfully running.')
})
If you are rendering 'home' then why do you have index.pug inside views. You should have home.pug inside views folder. I tried the below code and it worked.
Folder structure:
- server.js
- views/home.pug
Code -
const express = require('express');
const app = express();
app.set('view engine','pug')
app.get("/", function(req, res){
res.render("home");
})
const runServer = app.listen(8585, ()=> console.log('server is running at 1 27.0.0.1:8585'))

Node.js + Express: What do I have to serve the specific folder's path to express.static?

I wrote the following code:
var express = require('express');
var app = express();
app.use('/', express.static(__dirname ));
app.get('/', function (req, res) {
res.sendFile('./dist/index.html');
});
app.listen(3000, function() {
console.log("Listening on port 3000");
});
which doesn't work. When open the browser and go to "localhost:3000" I get the error:
path must be absolute or specify root to res.sendFile
Of course the once I fix the line that starts with "app.use..." to:
app.use('/', express.static(__dirname + "./dist"));
then everything works right.
Can you please explain why? What's wrong with giving "express.static" a path of a parent folder of the direct folder of the file sent?
Try changing the order. Instead of:
app.use('/', express.static(__dirname ));
app.get('/', function (req, res) {
res.sendFile('./dist/index.html');
});
Try:
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, './dist/index.html'));
});
app.use('/', express.static(__dirname));
// OR:
app.use('/', express.static(path.join(__dirname, 'dist')));
Plus use path.join() to join paths. You need to require path first:
var path = require('path');
See this answer for more info on serving static files and why path.join is important:
How to serve an image using nodejs
Now, your problem was not about express.static but about res.sendFile. When you changed express.static path to a different one, then the file you previously wanted to send with res.sendFile was probably found by express.static and the handler with res.sendFile was not run at all. Before the change, the express.static wasn't finding the index.html file and was passing the request to the next handler - which had a bad res.sendFile invocation. That's why it appeared to solve the problem with the error, because the code causing the error was no longer called.

Need to understand why expressjs is redirecting to index.html

I have the following server file, using express:
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
app.listen(port);
console.log('Listening on port: ' + port);
// get an instance of router
var router = express.Router();
app.use('/', router);
app.use(express.static(__dirname + "/"));
// route middle-ware that will happen on every request
router.use(function(req, res, next) {
// log each request to the console
console.log(req.method, req.url + " logging all requests");
// continue doing what we were doing and go to the route
next();
});
// home page route for port 8080, gets executed when entering localhost:8080
// and redirects to index.html (correctly and as expected)
router.get('/', function(req, res) {
console.log("routing from route")
res.redirect('index.html');
});
// This gets executed when my url is: http://localhost:8080/test
// and redirects to index.html (the questions is why!? I thought
// all the requests to root route would be caught by the router instance
app.get('*', function(req, res){
console.log('redirecting to index.html');
res.redirect('/index.html');
});
Looking at the code above and my comments, I cannot understand why
app.get('*', function(){...})
does not get executed when URL is
localhost:8080/index.html but gets executed when URL is localhost:8080/test
Even though, this is the behavior that I was hoping for, I'm not sure why this works?
I don't have a "test.html" page in the root.
One other thing, the index.html does load other scripts, so I expected
app.get('*', function(){...})
to get executed for such get requests too, as it is supposed to be the catch all, but it does not.
Does app.use('/', router) mean that any route that has single character "/" should be handled by Router instance (as long as not a static file)? so "http:localhost:8080" gets interpreted as "http://localhost:8080/"?
I would appreciate any explanation.
This line-
app.use(express.static(__dirname + "/"));
will run first. It will see that index.html exists and serve that file statically.

Resources