Node Js Express Static File fails when URL get - node.js

I am new to Node Js and doing some practice examples. Static files doesn't serve properly when sending get request as url id.
app.use(express.static('public'));
// It works. Static files loaded properly from http://localhost:3000/themify-icons.css
app.get('/about', (req,res) => {
res.render('about', {
title: 'About'
});
});
// It opens productdetail.ejs but Static files failed here.
// When I check the 'css' from view page source, Its locating to http://localhost:3000/product/themify-icons.css
app.get('/product/:id',(req,res) => {
// console.log(req.params.id);
res.render('productdetail', {
title:'Product Details'
});
});
app.listen(3000);
app('/product/:id') opens productdetail.ejs but Static files failed here. When I check the 'css' from view page source, Its locating to http://localhost:3000/product/themify-icons.css.
I understand its adding 'product' in the path. How do I resolve this even in this url id get method also?

If the browser is requesting http://localhost:3000/product/themify-icons.css, but you want it to just request http://localhost:3000/themify-icons.css, then change the url in the tag to have a leading /. So, instead of
"themify-icons.css"
use:
"/themeify-icons.css"
In your <style> or <link> tag. This should be true for all static resources that you don't want the path from the page URL to be added to.
When you have only a filename, the browser takes the path from the page URL and adds that to the filename. When you have a leading /, then the browser just takes the protocol, host and port from the page URL, not the path.

If your 'public' folder is directly in the project root, write
app.use(express.static(path.join(__dirname, 'public')));
instead of
app.use(express.static('public'));
to get the correct path relative from the project root.
__dirname will refer to the folder in wich your current script is executed.
Note: you need to require the "path" module:
let path = require('path');

Related

Express JS serve public folder via GET endpoint

I have a folder called my-folder, and inside it, many other folders. I'm trying to serve HTML and assets like JS and CSS when I go to a route using Express JS. I'm trying:
router.get('/serve/test', (req, res) => {
app.use(express.static(path.join(__dirname, 'my-folder/test/public')))
})
Inside of my-folder is various folders, and in each of those is again different folders, and I'd like to be able to serve the folder's public directory from any folder within my-folder in order to link to JS, HTML and CSS when going to: http://example.com/serve/test
Right now, I've hard-coded a folder of test, but this would be changed via a param...
Any thoughts as to why this doesn't work?
If you know the parent folders beforehand. You could use multiple express.static outside router.get. Like this:
app.use(express.static(path.join(__dirname, 'my-folder/test/public')))
app.use(express.static(path.join(__dirname, 'my-folder/test2/public')))
...
app.get(...)
If you don't know the folder names beforehand then you will need to build it as a route and return files with res.sendFile:
app.get('/my-folder/:uid/*', function(req, res){
var uid = req.params.uid, path = req.params[0] ? req.params[0] : 'index.html';
res.sendFile(path, {root: `./my-folder/${uid}/public/`});
});
The example above will serve the requested path file or "index.html" if no path is provided.

How to serve a static site within keystone?

I have one keystone based site and a completely static one.
I would like to integrate the static one into the first one.
All the requests to "/" will serve the static one but requests under "/resources" would serve the keystone site.
basically:
"/" would serve the static folder 'site'
"/resources" would serve the keystone app
At the moment my structure is:
public
| - keystone
| - site
And my keystone static option is set on 'public'
'static': 'public'
How would I go to set up these routes?
I was thinking of using a middleware in this way:
app.use("/", express.static(__dirname + "/site"));
app.use("/resources", express.static(__dirname + "/keystone"));
But how would I do it in keystone?
You don't need any extra middleware.
With the option 'static' : 'public', any static content placed in the public folder within your project folder will be served as static content.
It is also possible to define more than one directory by providing an array of directories like this 'static' : ['public','site'] this way everything in the directory site will also be served.
I assume you want some kind of index.html to be loaded when someone hits your sites root. You can achieve tha by adding a redirect to your /routes/index.js.
Simply add keystone.redirect('/', '/index.html'); or whatever the filename is you want to get served. You also have to remove the keystone route to '/'
I achieved this by just editing one line in the routes/index.js file, and adding the directory name in the keystone.init() "static" setting. Now all files in "client" directory get served under the root of my site URL, and Keystone lives at www.yoursite.com/resources
Step 1
Edit routes/index.js:
Change:
app.get('/', routes.views.index);
To:
app.get('/resources', routes.views.index);
Step 2
edit keystone.js:
Change
keystone.init({
...
'static': 'public',
...
To
keystone.init({
...
'static': ['public','client']
...
```
Step 3
Add site files, including index.html, into a new folder called "client".
Keep in mind that Node will also load files that are in the "public" folder. For example, currently keystone has a file called "logo-email.gif" in public/images. This means that www.yoursite.com/images/logo-email.gif will load that image. It turns out that if there is both a file public/images/logo-email.gif and client/images/logo-email.gif, then the image in public takes precedence. If you reverse the 'static' attribute in keystone.init() so that it says ['client','public'] then the image in "client" takes precedence
KeystoneJS v5, I used this way:
module.exports = {
keystone,
apps: [
new GraphQLApp(),
new StaticApp({path:"/", src:'public'}), // for your static site
new StaticApp({path:"/resources", src:'static'}), // Keystone uploaded resources
new AdminUIApp({
enableDefaultRoute: true,
authStrategy,
})
]}

serve a 404 when a locale file is missing in express

I'm using DaftMonk's generator-angular-fullstack, which has been great, except for one small problem I'm having...
I'm using i18next to handle localization, and the way the library works is it attempts to load a locale file from your specified path for the user's given localization setting, ie: /locales/en-US/app.json -- if that doesn't exist, it tries /locales/en/app.json (and in my case finds the file here).
The problem is the way the generator works is it has a route catchall which redirects all 404s to the index.html (the entry point for an angular app). This allows dynamic routing for the single page app.
When this happens, i18next chokes because it was expecting either a 404 or a json locale file, but instead got the index.html page.
I need a way to exclude the /locales path from being handled by this wildcard catch all and serve a 404 rather then the index.html page if a file is missing.
Here is what the express wildcard does:
//is there anyway to write an exclusion to this `/*` wildcard?
app.route('/*')
.get(middleware.setUserCookie, index.index);
/**
* Send our single page app
*/
exports.index = function (req, res) {
res.render('index', {
name: pkg.name,
version: pkg.version,
env: config.env
});
};
//in dev mode
app.use(express.static(path.join(config.root, '.tmp')));
app.use(express.static(path.join(config.root, 'app')));
//in production mode
app.use(express.static(path.join(config.root, 'public')));
How can I write a rule that will redirect /locales/* to serve a 404 if the file isn't found, rather than redirect to index.html?
What about
if (/\/locales\//.test(req.originalUrl) {
send404function()
}
Maybe it's not app.use(), but hopefully you wouldn't have to do this too much.

Deleted route function still serves old version of EJS file in Node/express App

I cannot reach modified version of my resource that is a html template, index.ejs, in uri '/' in my node-express app.
I have tried clearing and disabling Safari cache, restarting node server, even completely copy all the projects files to a new project dir, start server in another port etc.
Strange is that the version of the index.ejs file my browser shows in localhost:8080/ is non-existent. I have deleted it put the new one with new content. But I cannot view the new document in the browser in the '/' path, but only in another path, say '/i', if I set in server to respond with the same template, index.ejs.
Even if I delete the route function that serves index.ejs in path '/', it still serves it! How can this happen?
What can be the cause of this?
Old route to serve index.ejs that is deleted and still works when browser visited:
app.get('/', function(req, res) {
res.render('index.ejs');
});
New route to the modified version of the file index.ejs is not served with '/' path but only the old version of it is visible when '/' is visited. Following is the new route I have defined to be able to view the modified version of the index.ejs:
app.get('/i', function(req, res) {
res.render('index.ejs');
});
This issue occurred to me a few weeks ago when I was working on Node.js + Express + TS application. So apparently, I put some html files inside the public/ directory that I marked as static using express.static() because I was converting them to EJS so that I can later put those ejs files inside the views/ directory. Deleting those HTML files fixed my issue.

Learning Node - Express Public folder not working

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'.

Resources