Problem:
I quite confused to why my render is not loading my css and images from uploads.
When I do not try to log in, every page loads it's images and css applies it's styles..
But when I try to render my page like so:
if(!results.length){
res.status(401).render('home/login', {
message: 'The email or password is incorrect'
});
}
I get this error:
I realized it says ...:3000/auth/css/.. - it's not suppose to load auth?
This is my tree:
Index.js
|
├───controllers
├───helpers
│
├───public
│ ├───css
│ ├───javascript
│ └───uploads
├───routes
│ └───home
└───views
├───home
├───layouts
└───partials
└───home
index.js
const express = require('express');
const path = require('path');
const exphbs = require('express-handlebars');
const bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
const app = express();
// Public path
app.use(express.static(path.join(__dirname, './public')));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//Parse URL encoded bodies
app.use(express.urlencoded({ extended: false }));
//Parse JSON bodies as sent by API clients
app.use(express.json());
app.use(cookieParser());
// View engine
app.engine('handlebars', exphbs({defaultLayout: 'home-index'}));
app.set('view engine', 'handlebars');
// Routing
app.use('/', require('./routes/home/page_routes'));
app.use('/auth', require('./routes/auth'));
app.listen(3000, () => {
console.log('Listening');
});
views/layouts/home-index.handlebars
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/home.css">
<title></title>
</head>
<body>
{{> home/home-nav}}
{{{body}}}
</body>
</html>
routes/auth.js
const { db } = require('./db');
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
var { promisify } = require('util');
// Login
exports.login = async function(req, res) {
try {
var {email, password} = req.body;
if(!email || !password) {
return res.status(400).render('home/login', {
message: 'Please provide an email and password' ///////////////// This is the problem
});
}
db.query('select * from users_website where email = ?', [email], async function(error, results){
console.log(results)
if(!results.length){
res.status(401).render('home/login', {
message: 'The email or password is incorrect' ///////////////// This is the problem
});
}
else{
var id = results[0].id;
var token = jwt.sign({ id }, 'SuperSecretPassword9981998', {
expiresIn: '90d'
});
console.log("The token is: " + token);
var cookieOptions = {
expires: new Date(
Date.now() + 90 * 24 * 60 * 60 * 1000
),
httpOnly: true
}
res.cookie('jwt', token, cookieOptions);
res.status(200).redirect("/");
}
});
} catch (e) {
console.log(e);
}
}
routes/home/page_routes
const express = require('express');
const router = express.Router();
const auth_controller = require('../../controllers/auth');
// Home router
router.get('/', auth_controller.isLoggedIn, (req, res) => {
res.render('home/index');
});
// Login
router.get('/login', (req, res) => {
res.render('home/login');
});
module.exports = router;
Question
How do I get rid of the error - when trying to render the page?
The reason for this is that you are loading assets using relative URLs in your handlebars file, which means that the assets are loaded relative to the page's URL, which, in your case, is :3000/auth. To fix this, use an absolute URL instead.
Like this:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<!-- Notice the leading slash. -->
<link rel="stylesheet" href="/css/home.css">
<title></title>
</head>
<body>
{{> home/home-nav}}
{{{body}}}
</body>
</html>
Related
(noob alert) Sup guys. I'm an extreme beginner and this will be my first question so I'd be grateful if someone could lend me a hand with this. I just started learning express today and I'm not sure yet where to put what but I'm pretty sure that's why this isn't working properly. It only returns message = "" and inserts a blank into the database instead of the message typed inside the textarea. Sorry for the noob question
const express = require('express')
const path = require('path')
const app = express()
const mysql = require("mysql")
const bodyParser = require('body-parser');
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "......",
database: "chat_database"
})
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, "public")))
app.listen(3000)
app.post('/', (req, res) => {
const data = req.body.message
console.log(data);
let sql = `INSERT INTO chats(content) VALUES (?)`
connection.query(sql, [data], (err, result) => {
if (err) throw err
console.log(result);
console.log("data has been successfully inserted into the database!");
})
})
const mainChatBlock = document.querySelector("#main-chat-block")
const mainInputArea = document.querySelector("#main-input-area")
const mainSendButton = document.querySelector("#main-send-button")
mainSendButton.addEventListener("click", () => {
let newMessage = document.createElement("div")
newMessage.innerHTML = mainInputArea.value
mainChatBlock.append(newMessage)
mainInputArea.value = ""
mainChatBlock.scrollTop = mainChatBlock.scrollHeight
})
mainInputArea.addEventListener("keyup", function(event) {
if (event.keyCode === 13) {
event.preventDefault();
mainSendButton.click();
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>my chat</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<main>
<div id="outermost-main-div">
<div id="outermost-chat-div">
<div id="main-chat-area">
<div id="main-chat-block">
</div>
</div>
<form action="/" method="post" id="outer-input-area">
<textarea name="message" id="main-input-area" placeholder=">>> Enter your message here"></textarea>
<button type="submit" id="main-send-button">Send</button>
</form>
</div>
</div>
</main>
<script src="script.js"></script>
</body>
</html>
I figured it out guys. turns out the culprit was the clear value in the client side js mainInputArea.value = ""
but to clear the entry, I did something like this
mainSendButton.addEventListener("click", () => {
let newMessage = document.createElement("div")
newMessage.innerHTML = mainInputArea.value
mainChatBlock.append(newMessage)
mainChatBlock.scrollTop = mainChatBlock.scrollHeight
setTimeout(del, 100)
})
function del() {
mainInputArea.value = ""
}
I need some assistance in passing the MYSQL query results to an HTML select list. I was able to pass some data from a JSON list from here - http://jsonplaceholder.typicode.com/todos, but am unable to pass my own data that is sent to localhost:7002/getJson. Is it a formatting thing, please take a look at my code and data and see what can be changed. Thanks!
route.js
module.exports = function(app, passport) {
app.get('/', function(req, res){
res.render('index.ejs');
});
app.get('/login', function(req, res){
res.render('login.ejs', {message:req.flash('loginMessage')});
});
app.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile',
failureRedirect: '/login',
failureFlash: true
}),
function(req, res){
if(req.body.remember){
req.session.cookie.maxAge = 1000 * 60 * 3;
}else{
req.session.cookie.expires = false;
}
res.redirect('/');
});
app.get('/signup', function(req, res){
res.render('signup.ejs', {message: req.flash('signupMessage')});
});
app.post('/signup', passport.authenticate('local-signup', {
successRedirect: '/profile',
failureRedirect: '/signup',
failureFlash: true
}));
app.get('/profile', isLoggedIn, function(req, res){
res.render('profile.ejs', {
user:req.user
});
});
app.get('/logout', function(req,res){
req.logout();
res.redirect('/');
})
//-SQL QUERY
var express = require('express')
, http = require('http')
, mysql = require('mysql'); // <---- HERE
var app = express();
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: "password",
database: 'testdb'
});
connection.connect(); // <---- AND HERE
// all environments
app.set('port', process.env.PORT || 7002);
app.get('/getJson',function(req,res){
connection.query('SELECT * FROM testtable', function(err, result, fields){
if(err) {
console.log(err);
res.json({"error":true});
}
else {
// console.log(result);
console.log(JSON.stringify(result));
res.json(result);
}
});
} );
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
};
//-SQL QUERY END
function isLoggedIn(req, res, next){
if(req.isAuthenticated())
return next();
res.redirect('/');
}
signup.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Login Register</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<link rel="stylesheet"
href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<style>
html{
padding:50px;
}
</style>
</head>
<body>
<div class="container">
<div class="col-sm-6 col-sm-offset-3">
<h2>Register</h2>
<% if(message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
<form action="/signup" method="post">
<script>
fetch('http://localhost:7002/getJson')
.then(response => response.json())
.then(json => {
console.log(json);
let select = document.getElementById("test");
json.forEach(e=>{
var opt1 = document.createElement("option");
opt1.text = e.title;
opt1.value = e.id;
select.add(opt1);
});
})</script>
<script>
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => response.json())
.then(json => {
// console.log(json);
let select = document.getElementById("hi");
json.forEach(e=>{
var opt1 = document.createElement("option");
opt1.text = e.title;
// opt1.value = e.id;
select.add(opt1);
});
})</script>
<div class="form-group">
<select id="test">
</select><br>
<select id="hi">
</select><br>
</div>
<button type="submit" class="btn btn-succcess btn-lg">Register</button>
</form>
<hr>
<p>Need an account Register</p>
<p>Go Back Home.</p>
</div>
</div>
</body>
</html>
from: http://localhost:7002/getJson
from: http://localhost:8080/signup
from console
Your request is being blocked by CORS (Cross Origin Resource Sharing) policies, because your hosts are different (localhost:8080 and localhost:7002) and there is no Access-Control-Allow-Origin header in the responde from the express server.
You can add support to CORS from the origin site (localhost:8000) adding some HTTP headers to the express server:
var app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "localhost:8000"); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
I've an problem with evaluating an HTML Form using NodeJs and express.
This is my Java Script Code
My goal is to handle HTML Form in nodeJs using express.
const express = require('express');
const http = require('http');
const fs = require('fs');
const app = express();
var warehouses = [];
app.use(express.urlencoded({extended: true}));
app.use("/warehouse", (req, res, next) => {
fs.readFile("./addWarehouse.html", function(err, data) {
res.write(data);
next();
});
});
app.post("/warehouse/add", (req, res) => {
console.log("ADDED");
// warehouses.push(req.body.nWarehouse);
console.log('Request Type:', req.method);
res.end;
});
app.listen(8080);
And this is my HTML Form
<!DOCTYPE html>
<!-- <head>
<meta charset="utf-8" />
<title>Coole Seite</title>
</head> -->
<body>
<h1>Warehouses</h1>
<form method='POST' action="/warehouse/add">
<input type="text" name="nWarehouse" id="nWarehouse"/>
<input typse="submit" value="bitte sende" />
</form>
</body>
</html>
I tried to debug it with the console output and I figured out that it never access the app.use("/submit/add/" ... " part.
I would be happy to get some advice.
Here if the intent is to evaluate the form that is there in addWarehouse.html which should render when you go to /warehouse and the form should submit to /warehouse/add.
The middleware concept used via app.use(...) here is not required at all.
Express code:
const express = require('express');
const http = require('http');
const fs = require('fs');
const app = express();
var warehouses = [];
app.use(express.urlencoded({extended: true}));
//show addWareHouse.html for /warehouse
/* serving the HTML via fs */
app.get("/warehouse", (req, res, next) => {
fs.readFile("./addWarehouse.html", function(err, data) {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(data);
res.end();
});
//add warehouse form submit for /warehouse/add
app.post("/warehouse/add", (req, res) => {
console.log("ADDED");
console.log("REQUEST PARAM::", req.body);
//do you adding of ware-house stuff here
console.log("Request Type:", req.method);
return res.end();
});
app.listen(8080, () => console.log(`app listening on port 8080!`));
Note:
There are other handy ways to serve views (HTML) in express like template engines, res.sendFile() etc.
I have a web calling several scripts, images, styles, etc., in different folders (inside and outside the main folder):
File tree
- /
- website
- scripts
- data.js
- customJquery.js
- styles
- animate.css
index.html
main.css
back.jpg
- otherFunctions.js
index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat:400,400i,800,800i">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Faster+One">
<link rel="stylesheet" href="styles/animate.css">
<link rel="stylesheet" href="main.css">
</head>
<body>
<img class="fondo" src="back.jpg">
<div class="content">
<!-- stuff... -->
</div>
<script src='scripts/data.js'></script>
<script src='scripts/customJquery.js'></script>
<script src='../otherFunctions.js'></script> <!-- Here's the conflict... -->
</body>
</html>
All paths are routed ok, except for ../otherFunctions.js. It seems that NodeJS/Express skips de relative part .. and only receives /otherFunctions.js which is handled wrongly.
Here's my server side:
index.js
const express = require('express');
const https = require('https');
const fs = require('fs');
const app = express();
const config = require('./config');
var webId;
var options = {
key: fs.readFileSync(config.paths.certificate.key),
cert: fs.readFileSync(config.paths.certificate.crt),
requestCert: false,
rejectUnauthorized: false
};
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");
res.setHeader("Access-Control-Allow-Headers", "Accept, Access-Control-Allow-Headers, Access-Control-Request-Headers, Access-Control-Request-Method, Authorization, Content-Type, Origin, X-Requested-With");
next();
});
app.get('/favicon.ico', function(req, res) {
res.status(404).send('No favicon found');
});
app.get('/:id', function(req, res, next) {
id = req.params.id;
if (id.search(/\w+\.[A-z]+$/g) < 0) {
webId = id;
res.sendFile('index.html', {root: config.paths.webs + id});
} else {
res.sendFile(id, {root: config.paths.webs});
}
});
app.get('/:folder/:file', function(req, res) {
let folder = req.params.folder;
let file = req.params.file;
res.sendFile(file, {root: config.paths.webs + webId + '/' + folder});
});
app.get('*', (request, response) => {
response.send('GET request not found: ' + request.url);
});
app.use((err, request, response, next) => {
response.status(500).send(err.message);
});
https.createServer(options, app).listen(443, function() {
console.clear();
console.log("NodeJS secure server started at port 443");
});
Unless you have a specific need to serve your static files this way, I'd suggest using the express built-in static file serving.
Regarding the use of '../otherFunctions.js' in your HTML, I'm afraid the browser tries to resolve the path relative to the position of the HTML file itself, so for example, if the HTML file was my.domain.com/foo/bar/index.html, the browser would be looking for my.domain.com/foo/otherFunctions.js. Ideally, all the static files you want to serve to the client should be in one folder that is then used by the express.static(...) call.
I want to read an HTML file.
My HTML content:
<html>
<hear>
<title>Learn NodeJS</title>
</head>
<body>
<center>
<h1>Learn NodeJS with Khuong Pham</h1>
<img width="400" src="/nodejs.png" />
</center>
</body>
</html>
I've tried:
const http = require('http')
const fs = require('fs')
const express = require('express')
const app = express()
const folderPath = __dirname + '/public_files'
app.use(express.static(folderPath))
http.createServer(function(request, response) {
var filePath = folderPath + '/index.html'
console.log(filePath)
fs.access(filePath, fs.F_OK | fs.R_OK, function(err) {
if (err) {
response.writeHead(404, { 'Content-Type' : 'text/html' })
response.end('<h1>File not found</h1>')
} else {
fs.readFile(filePath, function(err, contentFile){
if (!err) {
response.writeHead(200, { 'Content-Type' : 'text/html' })
response.end(contentFile)
} else {
response.writeHead(500, { 'Content-Type' : 'text/html' })
response.end('<h1>Can not read this content</h1>')
}
})
}
})
}).listen(3500)
But when I access http://localhost:3500/, it says:
You are mixing two methods here. Firstly you are trying to use express, but later you are starting your own server using http.createServer Instead you should use express to do so.
Your js should be something similar to below. Have not tested below code. Edit it approiately. This is just to show the idea.
const http = require('http')
const fs = require('fs')
const express = require('express')
const app = express()
const folderPath = __dirname + '/public_files'
//mount your static paths
// renders your image and index.html
app.use(express.static(folderPath))
// renders your index.html
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
//mount your other paths
// in this case render 404.
app.get("*",function (req, res) {
res.status(404).send(''<h1>File not found</h1>'');
});
//start the server.
app.listen(3500, function () {
console.log('Example app listening on port 3500!');
});