Serving static files via Express - endpoint specific? - javascript

Beginner here, please point me in the right direction! So, I used express static and can see all my static files correctly in "sources" and the CSS applies via localhost:5050. However, when I directly open my endpoint e.g. http://localhost:5500/users, I cannot see the files anymore and no more CSS is applied. I wrote requests for each specific endpoint too, of course. Does this have anything to do with the way I serve static files in my code? I can't for the life of me figure out why there are no errors in the console and network tab but the styles do not apply and the classes set in my script also do not show up via the elements page in the dev tools when I open any of my endpoints. What could be the problem if everything is working via index? Do I need to configure static files for each API endpoint somehow too?
note: I also console.logged the path and could see the path is correct - / also serves the static files correctly so I assume the issue lies somewhere else? I also tried app.use('/users',express.static(path.join(__dirname, '..', '..', 'public')));
and could then see all static files via that endpoint but the whole endpoint functionality I set later in the code broke & app.use(express.static(path.join(__dirname, '..', '..', 'public'))); should normally allow public folder access from all endpoints, right?
HTML tags:
<link rel="stylesheet" href="/css/style.css" type="text/css">
<script src="./js/bundle.js"></script>
--> also tried with js/bundle.js & other paths.
server.js:
import express from 'express';
import path from 'path';
import axios from 'axios';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
const app = express();
const port = 5500;
// Serve static files from the public folder
app.use(express.static(path.join(__dirname, '..', '..', 'public')));
// Route for serving the index.html file
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '..', '..', 'public', 'index.html'));
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
This is my folder structure:
public/
index.html
css/
style.css
js/
bundle.js
src/
client/
script.js
server/
proxy.js
server.js

When you use code like this:
app.use(express.static(path.join(__dirname, '..', '..', 'public')));
Means that every request goes through express.static middleware.
Static middleware get path from the URL and tries to match a static file in public directory to this path. Let's consider several examples:
GET https://localhost:5500/foo/bar.html -> would be converted to /public/foo/bar.html
GET https://localhost:5500/ -> public/index.html
GET https://localhost:5500/users/ -> public/users/index.html
If you replace app.use(express.static(...)) on app.use('/users', express.static(...)) then express.static would be called only on /users/... requests:
GET https://localhost:5500/foo/bar.html -> not called
GET https://localhost:5500/users/ -> public/index.html. Note, /users prefix is removed when express.static convert URL's path to file path.
So this should explain:
I also tried app.use('/users',express.static(path.join(__dirname, '..', '..', 'public'))); and could then see all static files via that endpoint
Goes next:
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '..', '..', 'public', 'index.html'));
});
applies only on / request, so if you make request on /users express returns 404. If you want fallback on index.html every request that didn't match any previous middleware you should use:
app.use((req, res) => {
res.sendFile(path.join(__dirname, '..', '..', 'public', 'index.html'));
});
And the last ./js/bundle.js:
<script src="./js/bundle.js"></script>
this is relative URL it means if you open page /users/index.html and render such HTML then browser will make request on /users/js/bundle.js. In you case I guess you want to make request always on /js/bundle.js so you should replace it on absolute path /js/bundle.js like you did for CSS

Related

Express.js just won't serve static files

I am trying desperately to get it working that my express server serves statics files but I just can't get it to work... I already tried multiple attempts at solving it but none of it worked.
So my folder structure is the following:
App
- Web
-- public
--- images
--- css
-- Server.js
The code from my server is the following
const express = require('express');
const app = express();
app.use('/static', express.static('./public'));
const server = app.listen(80, function() {
const host = server.address().address;
const port = server.address().port;
console.log(`Server is running on ${host}:${port}`);
});
It just won't serve the files..
No matter how I change the usage of the public folder. I already tried with path.join and __dirname but none of it worked. I only get the express error Cannot GET /static ...
This can happen when the current working directory is not what you think it is and hence ./public doesn't resolve to the right path. The safer way to do this is to use __dirname, the directory of the current file:
app.use('/static', express.static(path.join(__dirname, 'public')));

Some expressjs Static Files being served while others are not

I have an odd situation what is particularly troublesome is that I have done this many times before it has to be something simple I am missing.
Please help I feel like I am loosing my mind...
Problem/Symptoms
I can load any js files from the lib folders
I can load any of the png files in the folder root/public/art under the web location //art/foo/bar.png
Can't load anything from the CSS nor js no mater what I do it all gives me 404 errors this is driving me totally crazy.
Same behavior with line 13 commented out
Same with various forms of lines 14-16
Same with and without using router
Folder Structure
Root
server.ts
public
art
art in subfolders
css
canvas.css
js
js files in folders and not
Code
import * as express from "express";
import * as path from "path";
//const express = require("express")
//const path = require("path")
let app = express()
let port = 3000
let router = express.Router();
router.use('/lib/framework', express.static( path.join(__dirname, 'node_modules','framework')));
router.use('/lib/redactedLib2', express.static(path.join(__dirname, 'node_modules', 'redactedLib2')));
router.use('/lib/redactedLib3', express.static(path.join(__dirname, 'node_modules', 'redactedLib3')));
router.get('/', (req, res) => res.sendFile(path.join(__dirname, 'index.html')))
//app.use('/art/*', express.static(path.join(__dirname, 'public', 'art')));
//app.use('/css/*', express.static(path.join(__dirname, 'public', 'css')));
//app.use('/js/*', express.static(path.join(__dirname, 'public', 'js')));
router.use('/', express.static('public'))
app.use('/', router)
app.listen(port, () => console.log(`Go to http://localhost:${port} to view.`))
Solution (Edit)
Incase anyone finds this later I was fixing it the whole time I just needed to do an empty cache and reload... If you are in chrome open dev tools F12 then click and hold on refresh and select it.
I see two issues, based on what you're showing here. First is your directory structure. Is that accurate to what your structure actually is? Because in your application you're telling Node to translate /art/* to the /public/art/ directory, but that directory is actually at /art.
Second, it's the formatting of your virtual path prefix. Drop the /*; there's no need to declare a wildcard value. It'll just mess up the pathing. The trailing / is unnessary too, though it shouldn't cause a problem. Either way, restructuring your routes to:
router.use('/lib/framework', express.static( path.join(__dirname, 'node_modules','framework')));
router.use('/lib/redactedLib2', express.static(path.join(__dirname, 'node_modules', 'redactedLib2')));
router.use('/lib/redactedLib3', express.static(path.join(__dirname, 'node_modules', 'redactedLib3')));
app.use('/art', express.static(path.join(__dirname, 'public', 'art')));
app.use('/css', express.static(path.join(__dirname, 'public', 'css')));
app.use('/js', express.static(path.join(__dirname, 'public', 'js')));
router.get('/', (req, res) => res.sendFile(path.join(__dirname, 'index.html')));
And either fixing the path joins in the app, or fixing the physical file structure, will solve the issue of loading resources that don't actually exist.

Cannot GET /blah.html - .ejs can't load html?

I'm using Nodejs and Express to create a dynamic webpage.
I have a home.ejs file that has this iframe:
<iframe id="newstable" src="/news_tables/2018-08-04.html" height="1000" width="100%"></iframe>
My folder directory is:
News_Aggregator (includes app.js)
News_Aggregator/news_tables (includes a bunch of html files, e.g. `2018-08-04.html`)
News_Aggregator/views (includes my `home.ejs` file)
And my app.js:
const express = require('express');
const app = express();
app.set("view engine", "ejs");
app.get('/', function(req, res){
res.render('home.ejs');
});
app.listen(8000, () => {
console.log('Example app listening on port 8000!')
});
However, when home.ejs is rendered, my iframe doesn't load the html page:
This works in "normal" HTML. What am I missing to get the .ejs file to find this and render correctly?
You get the error because the server dosen't know where to get the files from.
First You must define where the static .ejs files will be. Lets say something like this. if your files are in a public folder(ejs,css etc) and you will get them from there. Setup both with:
app.use(express.static(__dirname + '/public'))
app.set('views', path.join(__dirname, '/public'));
from here you can just in your response if you have a home.ejs file
res.render('home', {});
You should look over Express static() from here and learn how to serve files
The fact your HTML is generated from a .ejs file is irrelevant.
Your HTML says the browser should ask the server for the URL /news_tables/2018-08-04.html.
Your HTTP server has a route app.get('/', and no other routes.
Your HTTP server doesn't know about the URL /news_tables/2018-08-04.html, so it returns a 404 Not Found.
You need to write code which will serve up all the URLs you want it to.
You should probably look at the Express static() middleware if you want to serve static files.
The only thing that works is removing ".html" from address "localhost:3000/index.html".

Express, Wildcard-Subdomains, and sendFile()

I'm using Wildcard Subdomains on my Express server so that when users go to name.example.com, or request something from the API from that subdomain it all works well. (Navigating to name.example.com/api works correctly)
However, actually navigating to name.example.com needs to serve an index.html file; I'm using the code below as a catchall, but any files that are linked to inside the HTML file (like a stylesheet or JS file) are being served with the contents of index.html.
// routes/routefile.js
router.get('/_sub/:name/*', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'public', 'index.html'));
});
My file structure:
Project/
|_ routes/
|_ public/
|_ server.js
If there's a better package I should be using, please let me know!
Thanks!
This works:
app.use('/_sub/:name/', express.static(path.join(__dirname + '/public/')));

Serving static files from Node.js

I'm trying to serve static files from Node.js the only problem I'm having, is if I keep going into sub paths, like so:
localhost:3000/foo/bar/baz/quux
Then I have to step up the same amount of times, like this:
../../../../public/javascripts/whatever.js
As you can see that gets really annoying, is there a way to make Express v3 just know so that I can just do /public/javascripts/whatever.js instead of having to step up? Thanks in advance
This is my current static middleware for Express`
app.use("/public", express.static(__dirname + '/public'));
If you reference your static files from the root (i.e. src='/some/path/to/file.js'), the url should not matter.
Example Website using Static Routing
Directory Structure
/public
/css/style.css
/js/site.js
/vendor/thoughtbrain/js/awesome-town.js
/views/view.html
/app.js
view.html
<!DOCTYPE html>
<html>
<head>
<!-- These files are served statically from the '/public' directory... -->
<link href="/css/style.css" rel="stylesheet" >
<script src="/js/site.js"></script>
<!-- ... while this is "mounted" in virtual '/public' -->
<script src="/public/js/awesome-town.js"></script>
</head>
<body><p>Express</p></body>
</html>
app.js
var express = require('express'),
http = require('http'),
path = require('path'),
app = express();
// Remember: The order of the middleware matters!
// Everything in public will be accessible from '/'
app.use(express.static(path.join(__dirname, 'public')));
// Everything in 'vendor/thoughtbrain' will be "mounted" in '/public'
app.use('/public', express.static(path.join(__dirname, 'vendor/thoughtbrain')));
app.use(express.static(path.join(__dirname, 'views')));
app.all('*', function(req, res){
res.sendfile('views/view.html')
});
http.createServer(app).listen(3000);
With this application running,
http://localhost:3000
and
http://localhost:3000/foo/bar/baz/quux
both serve view.html and all referenced assets resolve.
Express Framework has a section on the use of static middleware here.
With that static() configuration, Express is already at least capable of finding /public/javascripts/whatever.js.
Though, it does depend on whether your public folder is in the same directory as your script (due to the use of __dirname when specifying the path).
If it is, the URL prefix /public should map to the file-system prefix of ./public (with . being __dirname) so that:
A URL of `/public/javascripts/whatever.js`
Maps to `./public/javascripts/whatever.js`

Categories