Nginx/Nodejs/Handlebars static files 404 - node.js

I have a nodejs app with handlebars, and an nginx reverse proxy sitting on an ubuntu server. No matter what combination of app.use(express.static('public')) and linking stylesheets I use, I only get a 404 on the stylesheet. Here's my code:
const express = require('express')
const path = require('path');
const hbs = require('hbs');
const app = express();
app.set('view engine', 'hbs');
app.use(express.urlencoded({ extended: true }))
app.use(express.static('public'));
hbs.registerPartials(path.join(__dirname, 'views/partials'));
app.get('/', async (req, res) => {
if (req.query.prompt) {
prompt = req.query.prompt;
}
res.render('index', {
prompt: prompt,
});
})
app.listen(8080, () => console.log('Listening on port 8080.'))
And this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<img src="profile.jpg" alt="photo">
</body>
</html>
Any help would be much appreciated! And yes, there are a lot of potential duplicates to this question but nothing has helped me :/
I've tried all combinations of /public, /index.css, /public/index.css etc.
My file structure looks like this:

I found the fix, and it wasn't nodejs or handlebars--it was removing the following line in my server block:
try_files $uri $uri/ =404;
I'll leave this here for anyone who might find this useful.

Related

Express Javascript file won't including with get method with parameters

I'm trying render the index file with Express Node.js successfully, but if I'm using namespaces with parameter, without parameter render twig file and included own scripts, if I use try with parameter, render ok bu problem with script files path so script files in head in html cannot including while path not correct
for example, without parameter, in html file style.css look like
<link rel="stylesheet" href="style.css"> path http://127.0.0.1:3000/style.css
with parameter, in html file style.css look like <link rel="stylesheet" href="style.css"> path http://127.0.0.1:3000/mynamespace/style.css <--- and this not found!
say browser path not found!
Server.js
const port = 3000;
const express = require('express');
const app = express();
const http = require('http');
const socketIO = require('socket.io');
const server = http.Server(app);
server.listen(this.port, () => {
console.log(`Server running on: http://127.0.0.1:${port}`);
});
const io = socketIO(server);
app.set('view engine', 'twig');
app.set('views', "views");
app.use(express.static('public'));
app.use(express.static('scripts'));
app.use(express.static("styles"));
/// Routing
/**
* This work fine
* Render client.twig
* Including Scripts in head
*/
app.get('/mynamespace', function (req, res, next) {
res.render("client");
});
/**
* This work with error
* Render client.twig
* don't Including Scripts in head
*
*/
app.get('/mynamespace/:id', function (req, res, next) {
res.render("client");
});
io.of("/mynamespace").on('connection',(socket)=>{
socket.on('online_users', (data) => {
console.log(`Online Users ${data}`);
});
});
client.js
let url = `http://127.0.0.1:3000/mynamespace`;
console.log("Url", url);
this.socket = io(url);
this.socket.on("connect", ()=>{
try{
this.socket.emit('welcome', {
message:"Welcome guest"
});
} catch (e) {
alert(e.message);
}
});
client.twig
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" const="text/html;charset=UTF-8"/>
<title>RestoCommend</title>
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="style.css"
</head>
<body>
<h3>Client</h3>
<script src="helper.js"></script>
<script src="client.js"></script>
</body>
</html>
From your code it looks like the style.css file is in the same directory as client.twig which is the views directory. But you have told express that the static directories are public, scripts and styles. There is no instruction for express to know where to serve the css from. Try moving the style.css file into styles directory.
Good luck.
Sounds like you want to serve your static files under a relative path. Try the following:
app.use('/mynamespace', express.static('public'))
app.use('/mynamespace', express.static('scripts'))
app.use('/mynamespace', express.static('styles'))
And also
<link rel="stylesheet" href="mynamespace/style.css" />
My hierarchy of files
I Solved my problem, but not good idea
Server.js
app.get('/mynamespace1', function (req, res, next) {
app.use(express.static('public'));
app.use(express.static('scripts'));
app.use(express.static("styles"));
res.render("client1");
});
one parameter based namespace!
app.get('/mynamespace2/:clientId', function (req, res, next) {
app.use(express.static(path.join( __dirname + "/../", 'public')))
app.use(express.static(path.join( __dirname + "/../", 'scripts')))
app.use(express.static(path.join( __dirname + "/../", 'styles')))
res.render("client2");
});
more as one parameter based namespace!
app.get('/mynamespace3/:roomName/:clientId', function (req, res, next) {
app.use(express.static(path.join( __dirname + "/../", 'public')))
app.use(express.static(path.join( __dirname + "/../", 'scripts')))
app.use(express.static(path.join( __dirname + "/../", 'styles')))
res.render("client3");
});
client1.twig
<link rel="stylesheet" href="style.css">
<script src="helper.js"></script>
<script src="client.js"></script>
Everything normal
client2.twig
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="../style.css">
<script src="../helper.js"></script>
<script src="../client.js"></script>
with one prameter, script paths defined to parent
client3.twig
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="../../style.css">
<script src="../../helper.js"></script>
<script src="../../client.js"></script>
with more prameters, parent folder defined, until number of parameter
My Problem solved, but I don't like it so

Serving static files in express net::ERR_FILE_NOT_FOUND

My folder structure is :
APP
-public
main.js
-views
index.html
index.js
I am trying to serve the static file to express server but its not working. The code for this in my index.js file is:
const express = require('express'),
app = express();
app.use(express.static(__dirname+'/public'));
I have also tried using path.join syntax
In my index.html file in the views folder , I am using the src tag as 'main.js'
<script type="text/javascript" src="main.js"></script>
I get the error net::ERR_FILE_NOT_FOUND.
I can also see that path src is referring to is wrong.
It is looking for main.js file in views directory instead of looking in public directory.
I have looked at other answers. I understand the syntax theoretically but am not able to find what I am doing wrong
Please point out the issue in my code. Thanks
Here is a working example:
index.js:
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
app.use(express.static(__dirname + '/public'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, './views/index.html'));
});
app.listen(port, () => console.log(`server is listening on port ${port}`));
./public/main.js:
window.onload = function() {
console.log('onload');
};
./views/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="main.js"></script>
</head>
<body>
This is template
</body>
</html>

rendering in nodejs using express to html

I'm trying to get values from nodejs into HTML. I've seen lot of answers, but none of them is working.
here what I've done so far:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
<div>
<a id="test" name="test"> <%=name%></a>
</div>
</body>
</html>
app.js
const express =require('express')
const app = express();
var os = require( 'os' );
var path = require('path')
const PORT = process.env.PORT ||2000;
app.engine('html', require('ejs').renderFile);
app.get('/',(req,res)=>{
res.sendFile(path.join(__dirname+'/index.html'))
})
app.get('/test', (req, res)=> {
var name = 454;
res.render( "/index.html", {name:name});
});
app.listen(2001)
I don't get what I'm doing wrong. but it doesn't work as expected.
any idea how may I solve this ?
thanks in advance !
First, create a folder views and put your index.ejs right there (though, I am not sure, the extension have to be .ejs).
Then set the engine with:
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
And change your routing to:
app.get('/', (req,res) => {
res.render('index', { name: 'Test' });
});
Edit: I have used the express application generator and also checked Using template engines with Express.
Edit: According to the extension .ejs:
One thing to note is that all files in which ejs syntax are used in
must be saved with a .ejs extension [...]
Taken from Using EJS as a Template Engine in your Express App, not from the official docs.

app.get('/') data doesn't show in same url using app.use('/') in express

This Link is explaining difference with app.use and app.get. But not explaining about same route problem. So I want to ask my question.
I made react project with create-react-app and make server inside src folder. I want to show text in the index.html when url is root. So I write codes like this.
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<p>Html test</p>
</body>
</html>
src/server/server.js
import express from 'express';
import path from 'path';
const app = express();
const port = 4000;
app.use('/', express.static(path.join(__dirname, '../../public')));
app.get('/', (req, res) => {
return res.send('<p>Hello index</p>');
});
app.get('/hello', (req, res) => {
return res.send('Hello CodeLab');
});
app.listen(port, () => {
console.log('Express is listening on port', port);
});
package.json
"babel-node": "babel-node src/server/server.js --presets es2015"
I test,
localhost:4000/hello --> Hello CodeLab
localhost:4000/ --> Html test (not Hello index)
I thought app.use is just static file which called every time when same url is called by app.get. Why app.get('/')doesn't show <p>Hello index</p> in this project?
Why app.get('/') doesn't show <p>Hello index</p> in this project?
It depends on the order. Re-write like this:
app.get('/', (req, res) => {
return res.send('<p>Hello index</p>');
});
app.use('/', express.static(path.join(__dirname, '../../public')));
You will get <p>Hello index</p> for sure!
The reason is under the hood, app.use() and app.get() both behave just like middlewares, they are treated equally in the Express app. The appear order decides which one is executed first.
an app is an object initialized on the start of express. app.use is for setting midleware More info
to resolve this problem just remove match for a route:
app.use(express.static(path.join(__dirname, '../../public')));
With '/' in app.use you must use next() method then express will go to next controller.

How to resolve "Unresolved variable or type data" warnings when using EJS?

I'm using EJS as Template engine. Everything looks like working fine, but I have these weak "Unresolved variable or type data" warnings in IntelliJ. How to get rid of these warnings? Is anything wrong with the code?
app.js:
var express = require('express');
var app = express();
var hostname = 'localhost';
var port = 3000;
app.set('view engine', 'ejs');
app.use('/static', express.static('static'));
app.get('/', (req, res) => {
res.sendFile(`${__dirname}/index.html`);
});
app.get('/profile/:id', (req, res) => {
var userData = {
id: req.params.id,
firstName: 'John',
lastName: 'Peterson',
age: 23,
active: true,
interests: ['Design', 'Web', 'Acting']
};
res.render('profile', { data: userData });
});
app.get('*', (req, res) => {
res.sendFile(`${__dirname}/404.html`);
});
app.listen(port);
console.log(`Server running at http://${hostname}:${port}`);
views/profile.ejs:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My Profile</title>
<link rel="stylesheet" href="../static/style.css">
</head>
<body>
<h2>My Profile Template</h2>
<p>ID: <%=data.id%></p>
<p>Name: <%=data.firstName%> <%=data.lastName%></p>
<p>Age: <%=data.age%> years</p>
<p>Active: <%=data.active%></p>
</body>
</html>
I solved this problem, by adding spaces between %=%.
<p>Name: <%= data.firstName %> <%= data.lastName %></p>
It looks like you need to export the data object somewhere in your code.
Try to add module.exports = { data: {}; } to the end of your app.js file.
To make autocomplete work correctly, you should either export a real object (userData) instead of an empty one, or use TypeScript.

Resources