I am currently towards the end of my project but there is one error I am receiving still. I cannot seem to figure out why I am receiving the error:
"Failed to load resource: the server responded with a status of 404
(Not Found)".
Below is my file layout, server.js and the script tag. I have my layout the same as all the other projects I have made in the past but for some reason this error keeps popping.
server.js
"use strict";
// DEPENDENCIES
require("dotenv").config();
const express = require("express");
const session = require("express-session");
const passport = require("passport");
const path = require("path");
const ejs = require("ejs");
const logger = require("morgan");
var createError = require("http-errors");
var cookieParser = require("cookie-parser");
const flash = require("connect-flash");
const favicon = require("serve-favicon");
// ROUTES REQUIRED
const main = require("./routes/main");
const about = require("./routes/about");
const contact = require("./routes/contact");
const profile = require("./routes/profile");
const pricing = require("./routes/pricing");
const help = require("./routes/help");
const login = require("./routes/login");
const signup = require("./routes/signup");
const forgot_password = require("./routes/forgot-password");
// PORT
const port = 3000;
const app = express();
// COOKIES AND SESSION
app.use(
session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: true,
})
);
app.use(passport.initialize());
app.use(passport.session());
// DATABASE
require("./config/database.js");
// PASSPORT AUTHENTICATION
require("./config/passport.js");
// VIEWS SETUP
app.set("views", path.join(__dirname + "/views"));
app.set("view engine", "ejs");
app.set("view cache", false);
// MIDDLEWARE
app.use(favicon(__dirname + "/public/favicon.ico"));
app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use("/public", express.static(path.join(__dirname + "/public")));
app.use(flash());
// ROUTES
app.use("/", main);
app.use("/about", about);
app.use("/contact", contact);
// PRICING
app.use("/pricing", pricing);
// PROFILE
app.use("/profile", profile);
app.use("/help", help);
app.use("/login", login);
app.use("/signup", signup);
app.use("/forgot-password", forgot_password);
// Logout
app.get("/logout", function (req, res) {
res.clearCookie("connect.sid");
res.redirect("/");
});
app.listen(process.env.PORT || port, (err, done) => {
if (!err) {
console.log({ message: "success!" });
} else {
return err;
}
});
home.ejs(home page layout with scripts.)
--------------------------------------------------------------------------
<section class="ad-analytics">
<div class="container-fluid ad-analytics__contain">
<div class="row ad-analytics__row">
<div class="col-md-6" id="meetings-img-holder">
<!-- bg-img holder -->
</div>
<div class="col-md-6 ad-analytics__textbox">
<div class="col-sm-12 ad-analytics__info">
<h1 class="h2">Analytical Precision</h1>
<p>
Getting ahead of the curve is the best way to scale above the
compeititon. With our machine learning tools, you can leverage
your data and get real insight on what your customers want from
you.
</p>
<a
class="btn btn-outline-light btn-sm"
href="/machine-learning"
role="button"
>Get Started</a
>
</div>
</div>
</div>
</div>
</section>
<%- include('partials/footer.ejs') %>
<%- include('partials/scripts.ejs') %>
</body>
</html>
------------------------------------------------------------------------------------
(Inside partials/script.js)
<script
src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
crossorigin="anonymous"
></script>
<script type="javascript" src="/server.js"></script>
File Layout
You shouldn't use <script> tags to import server side files, like for an example server.js, this file is used to run the node server
let's say you make a script for home page, you need to save it inside /public and the send it to client to be interpreted by the browser by adding it to partials/scripts.ejs
example
<script type="javascript" src="/home_script.js"></script>
the path would be
public/home_script.js
Edit:
it feels like you're still a bit confused so i'll take a example
in server.js you have
const main = require("./routes/main");
app.use("/", main);
think about the file main.js like taking a function from server.js and moving it to a single file
now in main.js i'm guessing you have a function like this:
router.get('/', (req,res,next) => {
res.render('home.ejs')
})
the code above is part of server side code and shouldn't be sent to the user(the client)
now inside home.ejs
you have your partials and then a section for scripts
<script type="javascript" src="/bootstrap.bundle.min.js"></script>
<script type="javascript" src="/home_script.js"></script>
this file home_script should contains stuff that you want to do once the page arrives the user (we call this client side)
as an example:
if you have button and you want to do something when you click you write that part of javascript inside home_script.js
Related
This is my folder structure:
/+---home
+---public
My node.js entry point resides in the "public" folder (i.e. public/server.js).
My requirement is that all users must be login before they can access the "home" folder.
The login form is stored in public/index.html file.
For testing purpose, I put an index.html in "home" folder.
Unfortunately, I got nothing after I login.
Would you tell me what is the problem?
This is my login form(i.e. public/index.html).
<html>
<head>
<meta charset="UTF-8">
<title>Chat Room</title>
</head>
<body>
<form method="post" action="/login">
Nick name/Alias:<input type=text required name="alias"><br>
Email Address:<input type=email required name="email"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
Here is my server.js code:
var bodyParse = require('body-parser')
var cookieParser = require('cookie-parser');
var express = require('express');
var session = require('express-session');
var app = express();
var userList={};
var http = require('http');
var serverPort = 81;
server = http.createServer(app);
server.listen(serverPort, function() {
console.log('server up and running at %s port', serverPort);
});
var io = require('socket.io')(server);
app.use(bodyParse.urlencoded({extended:false}));
app.use(bodyParse.json());
app.use(cookieParser());
app.use(session({
secret: 'my secret',
resave: true,
saveUninitialized: true
}));
app.use(express.static('public'));
app.post('/login', function(request, response) {
var alias = request.body.alias;
var email = request.body.email;
if (userList[email]==null) {
request.session.loggedin = true;
request.session.alias=alias;
request.session.email=email;
response.redirect('/home');
} else {
response.send("<script>alert('Your email address has been used, please use anothe one.');location.href='/';</script>");
}
});
app.all('/home', function(request, response,next) {
if (request.session.loggedin) {
next();
} else {
response.send("<script>alert('Your have to login to view this page.');location.href='/';</script>");
}
response.end();
});
Sorry, I solve the problem by using the express render method.
I want to implement my outsourced .ejs files into the layouts/admin.ejs direction. But it throws this error. I want my outsourced header, footer and navbar to be shown. All these files are stored in /views/partials/admin/filename.ejs
My layout is in /views/layouts/admin.ejs
<%- head -%>
<body>
<!-- Navigation Top -->
<%- navigation -%>
<!-- Page Content -->
<div class="container-fluid main">
<%- footer -%>
</div>
<script src="/vendor/jquery/jquery.min.js"></script>
<script src="/vendor/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
so this is my app.js
const
express = require('express'),
path = require('path'),
crypto = require('crypto'),
mongoose = require('mongoose'),
multer = require('multer'),
GridFsStorage = require('multer-gridfs-storage'),
Grid = require('gridfs-stream'),
methodOverride = require('method-override'),
bodyParser = require('body-parser');
const app = express();
const port = 3003;
// Middleware
app.use(bodyParser.json());
app.use(methodOverride('_method')); // Use query string in form
// Set view engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// #route get /admin
// #desc route to admin panel
const partialRoute = '/views/partials/';
app.get('/', (req, res) => {
res.render('layouts/admin', {
head: res.sendFile(__dirname + partials + 'head.ejs');
footer: res.sendFile(__dirname + partials + 'footer.ejs');
navigation: res.sendFile(__dirname + partials + 'navigaiton.ejs');
});
app.listen(port, () => {
console.log(`Server running at port ${port}`);
})
I tried to change the foldernames and routes and also removed all <% ejs but nothing works
hmmm... im using pug and not ejs, but it seems, that the directoryname is wrong/undefined?
You initialize partialRoute, but not partials?
Maybe im blind
const partialRoute = '/views/partials/';
app.get('/', (req, res) => {
res.render('layouts/admin', {
head: res.sendFile(__dirname + partials + 'head.ejs');
footer: res.sendFile(__dirname + partials + 'footer.ejs');
navigation: res.sendFile(__dirname + partials + 'navigaiton.ejs');
});
i have simple blog express app which i set up of two different main routes, regular routes (login,post,signup etc...) and for admin (add post,edit post etc...) the issue is my assets, css or any other static files does not load in the admin routes only but fortunately works in regular routes. my express setup is as follow:
app.use('/admin/pages', adminPages);
app.use('/', pages);
so after investigating the chrome developer tools for both main routs this is the issue but have no idea how to solve it !
this is when the admin routs does not load bootstrap or css files:
notice all assets is prefixed with unwanted (admin/pages/...) after localhost:3005
but it works here (without the prefix) :
heres my file structure:
full App.js :
const express = require('express'),
app = express(),
path = require('path'),
mongoose = require('mongoose'),
bodyParser = require('body-parser'),
pages = require('./routes/pages.js'),
config = require('./config/database'),
expressSession = require('express-session'),
expressValidator = require('express-validator'),
adminPages = require('./routes/admin_pages.js');
mongoose.connect(config.database);
const database = mongoose.connection;
database.on('error', console.error.bind(console, '##error with database:'));
database.once('open', () => {
console.log('Connected To Database successfully');
});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
// app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.set('trust proxy', 1);
app.use(
expressSession({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
})
);
app.use(require('connect-flash')());
app.use(function(req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
app.use(
expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.'),
root = namespace.shift(),
formParam = root;
while (namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param: formParam,
msg: msg,
value: value
};
}
})
);
app.use('/admin/pages', adminPages);
app.use('/', pages);
const port = 3005;
app.listen(port, () => {
console.log(`App Listening # localhost:${port}`);
});
add_page.ejs :
<%- include('../_layouts/header') %>
<form>
<input type="text" />
<input type="text" />
<input type="text" />
<button> submit </button>
</form>
<%- include('../_layouts/footer') %>
heres my both main routes:
i've found the answer.
when using two main routes you need to specify each route to its static file so we have got this middleware for the regular route as follow :
app.use('/', express.static('public'));
since you have another route for admin/pages this was missing:
app.use('/admin/pages', express.static('public'));
this fixed the issue :D
In my case I'm using only one main route, so I changed the asset url adding a / at the beginning of the url and it work for me:
<link rel="stylesheet" href="assets/css/style.css">
to
<link rel="stylesheet" href="/assets/css/style.css">
Maybe it can be helpful for someone else, regards!
I'm hoping someone can help with showing flash messages in Express via a Handlebars view (which uses the bootstrap markup).
In app.js I have the below modules and middleware to try and get flashes working
//require modules
const express = require('express');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const expressValidator = require('express-validator');
const hbs = require('express-handlebars');
const session = require('express-session');
const flash = require('connect-flash');
const routes = require('./routes/index');
const app = express();
// view engine setup
app.engine('hbs', hbs({extname: 'hbs', defaultLayout: 'layout',layoutsDir: __dirname + '/views/layouts/'}));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(cookieParser());
app.use(session({
secret: process.env.SECRET,
key: process.env.KEY,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(flash());
app.use((req, res, next) => {
res.locals.h = helpers;
res.locals.flashes = req.flash();
res.locals.user = req.user || null;
res.locals.currentPath = req.path;
next();
});
app.use('/', routes);
module.exports = app;
and a route
router.post('/store/add', storeController.createStore);
which has the controller function
exports.createStore = async (req, res) => {
const store = new Store(req.body);
await store.save();
req.flash('error', 'leave a review');
console.log('my-messages',req.flash());
res.redirect('/');
};
when I create a new store and am redirected to homepage the console.log shows the correct value my-messages { error: [ 'leave a review' ] } but I cannot get it into the view
my homepage ('/') view is
<h1>{{title}}</h1>
<p>Hi! Welcome to {{title}} </p>
<p>This page was built by {{created}}</p>
{{#if message}}
<div class="alert alert-danger">{{message}}</div>
{{/if}}
{{#if errors}}
{{#each errors}}
<div class="error">
{{msg}}
</div>
{{/each}}
{{/if}}
but nothing shows up. I've read quite a few similar questions on SO, but can't seem to get this right.
Any help much appreciated.
OK, so this is how I've worked things based on https://gist.github.com/brianmacarthur/a4e3e0093d368aa8e423 from this https://stackoverflow.com/a/28221732/1699434 answer.
After app.use(flash()) in app.js I added:
app.use(function(req, res, next){
// if there's a flash message in the session request, make it available
in the response, then delete it
res.locals.sessionFlash = req.session.sessionFlash;
delete req.session.sessionFlash;
next();
});
In my routes file (index.js) I added the example in the gist:
router.all('/session-flash', function( req, res ) {
req.session.sessionFlash = {
type: 'info',
message: 'This is a flash message using custom middleware and express-session.'
}
res.redirect(301, '/');
});
Then I created a handlebars partial message.hbs (which makes use fo the contains helper from npmjs.com/package/handlebars-helpers:
{{#if sessionFlash.message}}
<div id="flash-messages" class="container">
{{#contains sessionFlash.type "info"}}
<div class="alert alert-info">
{{{sessionFlash.message}}}
</div>
{{/contains}}
{{#contains sessionFlash.type "success"}}
<div class="alert alert-success">
{{{sessionFlash.message}}}
</div>
{{/contains}}
{{#contains sessionFlash.type "warning"}}
<div class="alert alert-warning">
{{{sessionFlash.message}}}
</div>
{{/contains}}
{{#contains sessionFlash.type "error"}}
<div class="alert alert-danger">
{{{sessionFlash.message}}}
</div>
{{/contains}}
</div>
{{/if}}
I can then include this in my other handlebars templates {{> message}}. This gives me flash messages carrying bootstrap styling.
Unfortunately I'm not able to send multiple flashes at the same time (either of the same or different types) but I think this is discussed in https://gist.github.com/brianmacarthur/a4e3e0093d368aa8e423 anyway as a limitation of the middleware approach. As I learn more maybe I'll address this but I don't have a use case for multiple flash messages at the moment anyway :)
I am trying to replicate a tutorial on using passport to create user authentication.
whenever i try including the below snippet in signup.ejs:
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
it throws error and as soon as i remove this from signup.ejs, it renders.
below is my app.js(includes all the configurations), index.js(routing part), signup.ejs and passport.js(link to this file is mentioned)
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
var mongoose = require("mongoose");
var passport = require('passport');
var flash = require('connect-flash');
var session = require('express-session');
mongoose.connect("mongodb://jer:jer#ds061611.mongolab.com:61611/passport1");
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
require('./config/passport')(passport);
app.use(logger('dev'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// required for passport
app.use(session({ secret: 'zxcv' })); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.listen(8000);
module.exports = app;
index.js
var express = require('express');
var router = express.Router();
var passport = require('passport');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index.ejs', { title: 'Express' });
});
router.get('/signup', function(req, res) {
// render the page and pass in any flash data if it exists
res.render('signup.ejs');
});
// process the signup form
console.log("entering signup");
router.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/profile', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
router.get('/profile', isLoggedIn, function(req, res) {
console.log("going to profile page.................................................................");
res.render('profile.ejs', {
user : req.user // get the user out of session and pass to template
});
});
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
// if they aren't redirect them to the home page
res.redirect('/');
}
module.exports = router;
signup.ejs
<!doctype html>
<html>
<head>
<title>Node Authentication</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css"> <!-- load bootstrap css -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css"> <!-- load fontawesome -->
<style>
body { padding-top:80px; }
</style>
</head>
<body>
<div class="container">
<div class="col-sm-6 col-sm-offset-3">
<h1><span class="fa fa-sign-in"></span> Signup</h1>
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>
<!-- LOGIN FORM -->
<form action="/signup" method="post">
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" name="email">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-warning btn-lg">Signup</button>
</form>
<hr>
</div>
</div>
</body>
</html>
passport.js (at below link:)
https://scotch.io/tutorials/easy-node-authentication-setup-and-local
Any help would really help me in completing this tutorial.
Thanks in advance.
Finally, digged out the fault...... was a very simple and basic error.Happy i did not waste other's time...
error: i was not passing the variable into the template while rendering.
codeChange:
in index.js for the /signup path
res.render('signup.ejs'); changes to res.render('signup.ejs',{message:'errorMessage'});