Express: How to serve font-awesome as static content? - node.js

I use express to serve static content on my site and I want to incorporate FontAwesome (npm install font-awesome). However in Font-Awesome's css the links to the font files are appended with a query-string containing versioning information witch express doesn't understand.
Has anyone encountered this and found a fix? Is there a simple way to make express ignore the qs for static content?
var express = require('express')
var app = express()
app.use('/static', express.static('./node_modules/font-awesome/css'))
app.use('/static', express.static('./node_modules/font-awesome/fonts'))
// response 200 | /static/font-awesome.min.css
// error 404 | /static/fontawesome--webfont.woff?v=4.6.3
Update
As #Denys Séguret points our it's not the qs as I had thought. The actual request is for /fonts/fontawesome--webfont.woff?v=...
Solution
app.use('/fonts', express.static('./node_modules/font-awesome/fonts'))

When your browser requests /static/fontawesome--webfont.woff?v=4.6.3, the server is free to ignore the ?v=xxx part. And that's what is done by the express.static module. The point of that part is to prevent browsers and proxies from using an old version of the file.
So the problem isn't where you think it is. The problem is you map the static route to two servers. The first one doesn't find the file and issues a 404.
(Dirty) Solution 1:
Change your mapping
app.use('/static', express.static('./node_modules/font-awesome'))
and change the URLs:
/static/fonts/fontawesome--webfont.woff?v=4.6.3
I say it's dirty because you're serving the unchecked content of a node modules (which is updated when you do a npm update). You should never do that.
 Solution 2:
Create a static directory (the name doesn't matter) and put inside the contents of the ./node_modules/font-awesome/css and ./node_modules/font-awesome/fonts directories then just map it using
app.use('/static', express.static('./static'));

Related

Uncaught ReferenceError: require is not defined

I have a project by Three.js.
Like below pic, i have an index.html that uses js codes from scripts.js (in sub-Directory of js).
also, this scripts.js , uses three and OrbitControls libs of package of three.js.
PROBLEM:
after running my project, browser, shows HTML and CSS fine, but it do not works by javascript and gives this error:
i can't find any solution, after half a Day searching & manipulating!
can any one help please?
1)project structure:
root
|------server.js
|------/public
| |---index.html
| |---/js/scripts.js
| |---/css/index.css
2)root/public/index.html:
3)root/public/js/scripts.js:
4)root/server.js:
const express = require("express");
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, '/public')));
app.get('/',function(req,res) {
res.sendFile("public/index.html")
});
app.listen(3000, () => {console.log("listening on port 3000");});
Multiple things going on here. First, require() is nodejs ONLY, is not present in the browser. You are trying to load and run js/scripts.js in the browser and thus cannot use require() in that script.
Separately, when you use type="module" in a script tag, that means the module is an ESM module which can use import to load other modules, but import needs to specify a URL that your express server will handle and serve the right file with.
I'm also guessing that you will have a problem loading the script files because they need to be served by express.static() in your server and need to have the appropriate URL paths in your web page so that express.static() will work. You don't show the server-side file structure for all those scripts so it's hard for us to know exactly what the URLs should be.
And, in the future, please don't ever post screen shots of code. That makes it a lot harder for us to use your code in tests or in answers (because we have to retype it all from scratch) and it can't be searched, is harder to read on mobile, etc... Don't put code in images.

Serve static files with ExpressJS Typescript NodeJS

I'm trying to serve static file uploaded using ExpressJS and NodeJS with Typescript but getting 404 error.
the file I want to read is ./src/data/uploads/test.txt and I'm trying to access it from web browser directly.
Note: When I do it in Javascript it worked but not in Typscript.
index.ts file (app entry point)
import express from 'express';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import {cdg, config} from './utils';
import {Mongoose} from './db/monogdb';
import { setRoutes } from './routes/route.decorators';
import cors from 'cors';
import './routes';
const app = express();
app.use(helmet());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/ftp', express.static('data/uploads'));
setRoutes(app);
app.listen(config.server.port, () => {
cdg.konsole("Server connected! :: " + config.server.port + "!");
});
Is there a specific way to serve static file with Typescript ?
Here's how express.static() works. You are apparently missing one of these steps, but your question is short of the details to identify exactly which step is not correct.
First, you define an express.static() middleware that contains some parameters. In your case, you've defined this:
app.use('/ftp', express.static('data/uploads'));
There are four elements that determine how this works:
The /ftp that must be at the start of any URL for this middleware to match.
The incoming URL request and how it was formed by the browser based on how you specified it in your HTML.
The current working directory that is combined with data/uploads to make a full path reference or you could build your own absolute path and not depend upon the cwd.
The files in cwd + /data/uploads that express.static() will attempt to match to the path of the incoming URL.
Let's look into these further:
Your middleware will first only look at URLs that start with /ftp. And, then for any URL it sees that does start with /ftp, it should take the rest of the URL and append it to data/uploads and see it finds a matching file in your local file system. It will use the current working directory in your server process at the time of the request to try to resolve the relative path data/uploads. That current working directory (if you haven't programmatically changed it) will depend upon how your app was started.
So, if you started your app with node index.js, then the current working directory will be the directory where index.js is located and express static will be looking in the data/uploads sub-directory below where 'index.js` is.
Then, we need to look at how the HTML tag that specifies this static resource is specified.
Let's say this is an <img> tag for example. If you specify something like this:
<img src="/ftp/hello.jpg">
Then, the browser will create a request to your server for /ftp/hello.jpg. Since that does start with /ftp, your express.static() middleware will take the rest of the path /hello.jpg and append that to data/uploads and build a path that looks like this:
path.join(process.cwd(), 'data/uploads', '/hello.jpg')
And, it will look for that resulting file in your local file system. If it finds that file, then it will serve that file and return it as the response. If it doesn't find that exact file, then it will call next() and continue routing to your other route handlers.
There are a number of common mistakes (things that can go wrong):
You don't specify the correct URL in your web page that lines up with your express.static() middleware line (including the /ftp prefix that your middleware specifies).
Your middleware isn't quite pointing at the right directory in your file system so it never finds anything.
You are using relative URLs in your web page which the browser combines with the path of your web page causing it to request something different than you want. Static resource URLs in your web page should nearly always start with / so they are not dependent upon the path of the parent page.
The files aren't quite properly located in the file hierarchy you are pointing to with your middleware (often off by one level).
One other thing I will mention. Since you're using TypeScript, that means you have to compile/build your script into a regular .js script before it can be run. This will typically be in a different directory location.
This different directory location creates opportunities for you to not be referencing the proper directory where your static resources are, since they are probably located relative to your TypeScript files, not the built Javascript files that you're running (that depends upon your build script).
Again, if you show us where everything is in your file system (TypeScript files, built JS files, static resources) and what the HTML tag that references the static resource looks like, we can help you debug that more specifically.
In my case I solved my problem like this: in the parameter relative to the directory path I used path.resolve and in its first parameter I used __dirname as the first parameter and the relative path of the target directory as the second one.
app.get('/', express.static(path.resolve(__dirname, '../static/'))); –

cannot reach a file on server though I exposed using express

In my project I need to store some text files dynamically and end user should be able to download them from browser. I know the best way is using object store like MINIO or S3 but unfortunately the only way I have is to use in memory storage. So what I am trying to do is: I made a public folder and I exposed it using the following code:
var express = require('express');
var app = express();
//setting middleware
app.use(express.static( 'public')); //Serves resources from public folder
var server = app.listen(5000);
it is as simple as that. Then for testing just to make sure I can download and reach a file I created a public folder with t.txt file in it and when I try:
http://localhost:5000/public/t.txt
I get
So why am I not getting it? Also is what I am trying to achieve will be a good match to scenario and is it doable at all?
When you're not specifying a path in app.use(), your app will serve the contents of the directory you're pointing to in express.static() on the root path. Try this:
http://localhost:5000/t.txt
That said, if you want it to be accessible at /public/t.txt, just specify the path:
app.use('/public', express.static('public'))
At first use the following line of code:
app.use(express.static(__dirname+'/public'));
This means that your home directory for static HTML pages is in the "public" folder. Note that the "__dirname" points to the directory of the current js file.
After that, call the following URL from the browser or POSTMAN:
http://localhost:5000/t.txt
As you can see, there is no need to write http://localhost:5000/public/t.txt referring to the "public" folder because you have already specified that in the app.use line.

ExpressJS static file serve always serves the same file

I have a expressJs setup which looks like this:
// Imports...
const app: express.Application = express();
const port: number = 3001;
const listener = new StatementListenerAPI();
app.use('/listen', listener.getRouter());
app.use('/welcome', router);
if (fs.existsSync('./client')) {
// Running in prod environment with pre built client directory. Serve this.
app.use(express.static('./client'));
}
app.listen(port);
So I have some routers connected to the express app, and at the bottom I declare that the directory client should be served statically. This directory contains an index.html as well as lots of JS, CSS and PNG files. However, no matter which URL I try to access from the express server, it always shows the code of the index.html within the statically served directory. The references to the JS and CSS files used inside the index.html also just return the code of the index.html.
I am using ExpressJS 4.16.3
What am I doing wrong?
Edit: So technically it works if using __dirname + '/client' instead of ./client. What I am now getting is that, when making GET requests from e.g. Postman (therefore "hand-crafting" the HTTP requests), I am always getting the correct results. If I call the resources from within my web browser, it still always shows the website (resolves the index.html). However, now all resources like JS and CSS scripts are being resolved properly, so apperantly Chrome resolves those dependencies properly, I am just wondering why I am still getting the contents of index.html as result when requesting some of the assets or some of the express endpoints via Chrome. API calls via code are working fine, so its only why manual chrome requests show this weird behaviour, at this point I am only asking out of curiosity.
Answer to your original question:
The path supplied to express.static should be relative to the directory from where you launch your node process or an absolute path. To be safe construct an absolute path (ie from the current directory or file). For example:
app.use(express.static(__dirname + '/client'));
Regarding your followup question:
I assume this is because Chrome uses heavy caching and it thinks this folder should return the html file. You can try and reset all caches in Chrome, or just for the page.

nodejs express not to intercept messages for a folder with static content

I've a node, express system installed working on a host.
All requests are going through in the app.get('/path'... format
however in the domain I've html folder with static content that I want to serve
http://domain.com/html/attendee
http://domain.com/html/sponsors
and don't want node/express to intercept these requests and let them go through directly, not even serve through nodejs, otherwise relative linking problem.
Please suggest a solution.
You can't do it that way. node doesn't serve ANY content by default - it is not like some other web servers in that regard.
Instead, you specifically configure express to serve content from certain paths directly from the file system by inserting the right middleware commands early in the middleware stack.
For example, in one of my node apps, I use this middleware:
// static routes that get no further processing
app.use('/img', express.static(__dirname + '/img'));
app.use('/lib', express.static(__dirname + '/lib'));
This tells express that any content that starts with "/img" should be served directly from the appDirectory + "/img" directory. Same for elements in "/lib". One nice thing about this is that the paths you expose to the outside world do not have to be the same as the paths you use on your server and, in fact, by changing a few characters in your code, you can easily map to different directory.

Resources