Handlebars.js on Amazon Linux cannot locate a view template - express

I have an Express application that uses Handlebars.js as a templating engine. I'm trying to get it running on an EC2 Amazon Linux instance; the server is running and it can connect to the database, but when I try to open the website in my browser, I get the following error: Failed to lookup view "homepage" in views directory "/views".
The application works perfectly fine when I run it locally and on Heroku (I'm trying to move it off Heroku), so I have no idea what the issue here is. I deleted the /var/log/messages file, having not realized it wouldn't be regenerated (this is my first time using EC2), so I unfortunately can't look there for hints, but I do know that if I run <environment variables> node server.js in the Amazon Linux terminal, no errors occur.
The application has a .service file in /etc/systemd/system so I can keep it live with systemctl. I assume the error is to do with the configuration of that file. It's also being reverse-proxied with nginx, but this issue was present before I set that up.
Relevant code snippets:
/etc/systemd/system/lightbox.service:
[Unit]
Description=Lightbox
After=multi-user.target
[Service]
ExecStart=/usr/bin/node /home/ec2-user/lightbox/server.js
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=Lightbox
User=ec2-user
EnvironmentFile=/home/ec2-user/lightbox/lightbox.env
[Install]
WantedBy=multi-user.target
server.js:
const express = require('express');
const session = require('express-session');
const routes = require('./controllers');
const path = require('path');
const sequelize = require('./config/connection');
const app = express();
const PORT = process.env.PORT || 3005;
// handlebars init
const exphbs = require('express-handlebars');
const helpers = require('./utils/helpers');
const hbs = exphbs.create({helpers});
// handlebars init
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');
// session init
const SequelizeStore = require('connect-session-sequelize')(session.Store);
// session init
const sess = {
secret: process.env.SECRET,
cookie: {},
resave: false,
saveUninitialized: true,
store: new SequelizeStore({
db: sequelize
})
};
// general express init
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session(sess));
app.use(routes);
// startup
sequelize.sync({ force: false }).then(() => {
app.listen(PORT, () => {
console.log('http://localhost:' + PORT);
});
});
(Not including the .env file, but it's there, the secret is present and definitely being read by the server.)
Route that renders the homepage:
router.get('/', (req, res) => {
Post.findAll({
attributes: ['id', 'title', 'text', 'created_at'],
include: [
{
model: User,
attributes: ['username', 'id']
},
{
model: Comment,
attributes: ['id']
}
]
})
.then(dbPostData => {
const posts = dbPostData.map(post => post.get({plain: true}));
res.render('homepage', { posts, loggedIn: req.session.loggedIn });
})
.catch(err => {
console.log(err);
res.status(500).json(err);
});
});

I never resolved this error, but I did get the app functioning by reworking it to use PM2 rather than systemd.

Related

req.isAuthenticated() is false after i implemented mySqlSessionStore ,hence user always fails to login even if authentication is succes

I am implementing simple login application using express,passport,express-mysql-session .
When i debugged i found that user is set to req object(req.isAuthenticated() is true) ,so i could login successfully!
Then i implemeted mysqlSessionStore to store session details in db.
i cleared the sessions table and logged in .records after login failed:
data:
{"cookie":{"originalMaxAge":31536000000,"expires":"2023-11-05T05:25:53.426Z","httpOnly":true,"path":"/"},"flash":{}}
2){"cookie":{"originalMaxAge":31536000000,"expires":"2023-11-05T05:26:00.122Z","httpOnly":true,"path":"/"},"flash":{},"passport":{"user":2}}
3){"cookie":{"originalMaxAge":31536000000,"expires":"2023-11-05T05:26:00.138Z","httpOnly":true,"path":"/"},"flash":{"message":["Please log in to view that resource"]}}
session ids are same but data is mentioned above.
When i debugged i found that user object is missing in the req object hence req.isAuthenticated() is false.
passport.authenticate() method:
serializeUser and deserializeUser methods:
index.js(took care of order app.use(session()),passport.initialize() and passport.session()
[![index.js(took care of order app.use(session()),passport.initialize() and passport.session()
at last when i redirect to secure page i check for req.isAuthenticated() which is false only after implementing mySqlSessionStore***
]
tried to print session when i check req.isAuthenticated() (screenshot above) .below are the logs:
without session store implementation
[![screenshot1][2]][2]
after implementing sessionStore using express-mysql-session:
[![screenshot2][3]][3]
I have tried to set the secret in app.use(cookierParser("secret"); and the order of app.use methods in my index.js seems to be fine.
So i am confused how the MySqlSessionStore is impacting the the regular flow of passport.serializeUser() and passport.deserializeUser().
I i tried to understand the serializeUser and deserializeUser method working but not sure whats going wrong. I am new to node js .
In separate file passport-config.js i call passport.use(new LocalStrategy)
[![passport-config][4]][4]
importing above file in index.js
[![index.js][5]][5]
const express = require("express");
const cookieParser=require('cookie-parser')
const session = require("express-session");
const path = require("path");
const app = express();
const MySQLStore=require('express-mysql-session')(session)
const flash = require("connect-flash");
const passport = require("passport");
app.set("views", path.join(__dirname, "views"));
app.set("view-engine", "ejs");
app.use('/static', express.static(path.join(__dirname, 'public')))
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const env = process.env.NODE_ENV || 'development';
const config = require('./config/config.json')[env];
const { loginCheck } = require("./config/passport-config");
loginCheck(passport);
var options ={
host:'localhost',
port:3306,
user:'root',
password:'root',
database:'logindb'
}
const oneYear=1000*60*60*24*365
const sessionStore=new MySQLStore(options)
app.use(
session({
key:'session_cookie_name',
store:sessionStore,
secret: "LoginAppSecret",
saveUninitialized: false,
resave: false,
cookie: {maxAge:oneYear,httpOnly:true}
})
);
app.use(cookieParser("LoginAppSecret"))
app.use(flash());
app.use(function (request, response, next) {
response.locals.message = request.flash("message");
response.locals.errors = request.flash("error");
next();
});
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
const port = 3000;
const swaggerUi = require("swagger-ui-express"),
swaggerDocument = require("./swagger/swagger");
//Routes
app.use("/", require("./router/login"));
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));
app.listen(port,"localhost", () => {
console.log(" Server running!!");
});
[1]: https://i.stack.imgur.com/lX0Wa.png
[2]: https://i.stack.imgur.com/DFHQd.png
[3]: https://i.stack.imgur.com/Ct32Z.png
[4]: https://i.stack.imgur.com/BOUnE.png
[5]: https://i.stack.imgur.com/6h9O9.png
I can see your problem. Your program is adds new rows even though it has "session_id" and i cant see createDatabaseTable:true on your store config, and auto generated session table doesnt have created_at and updated_at colums. So you created this table manually.
Stop Project
Delete session table
Change MysqlStore options with this configs
const options = {
host: 'localhost',
...
database: 'logindb',
createDatabaseTable: true
}
Start Project
After that your project will work fine

unable to serve static vuejs files on express

Here is my express code:
const express = require('express');
const serveStatic = require('serve-static');
const path = require('path');
// create the express app
const app = express();
var cors = require('cors');
app.use(cors());
app.use("/",serveStatic ( path.join (__dirname, '/dist') ) );
app.use('/static', express.static(path.join(__dirname, '/dist23')));
app.listen(port, () => {
console.log("listening on "+port)
});
The above code only works for the folder /dist. But when I go to /static, it shows a blank page and this error in the console:
If I put the js files from /dist23 into /dist, then /static works and shows me the application. Its almost like it is looking for files inside /dist and not /dist23. How do I fix it?
Both apps were built using vue-2.6.11. Both directories have files built/bundled for production.
You need to set the content type while serving your static files.
app.get('/index.html', (req, res) => {
res.set('content-type', 'text/plain').sendFile('index.html', { root: path.join(__dirname, 'public/dist/') })
});
app.get('/', (req, res) => {
res.set('content-type', 'text/plain').sendFile('index.html', { root: path.join(__dirname, 'public/dist/') })
});

Rendertron setup -- How to run it's middleware through Vue 2 Cli express server (for production)

I'm working on a headless solution to give bots SSR, save the renderings on a firebase bucket. I've deployed a working Rendertron heroku app at https://xymba-renderbot.herokuapp.com/render/ .
This app works well enough with direct tests and on Google's mobile-friendly test. Serving local works, too from vue.config.js devServer proxy.
However, when I deploy the app to Vercel including the specified middleware in index.js, doesn't seem like I know how to test or the BOTS aren't config'd right (Heroku has the renderbot separately from the main app at Vercel)
To recap, I'm running Rendertron, need to learn how to send bots to the /render endpoint, and how to pipe the renderings as static files to be saved. Am I missing something or is this not possible from vue-cli?
index.js
const express = require('express');
const serveStatic = require('serve-static')
const path = require('path');
app = express();
const rendertron = require('rendertron-middleware');
const BOTS = rendertron.botUserAgents.concat('googlebot');
const BOT_UA_PATTERN = new RegExp(BOTS.join('|'), 'i');
app.use(serveStatic(path.join(__dirname, 'dist')));
app.use(rendertron.makeMiddleware({
proxyUrl: 'https://xymba-renderbot.herokuapp.com/render',
userAgentPattern: BOT_UA_PATTERN
}));
app.get('/service-worker.js', (req, res) => {
res.sendFile(path.resolve(__dirname, 'dist', 'service-worker.js'));
});
app.get('*', function (req, res) {
const index = path.join(__dirname, 'dist', 'index.html')
res.sendFile(index, path.join(__dirname, 'dist/'))
})
const port = process.env.PORT || 80;
app.listen(port);
vue.config.js
const path = require("path");
module.exports = {
devServer: {
open: process.platform === 'darwin',
host: '0.0.0.0',
port: 8085, // CHANGE YOUR PORT HERE!
https: true,
hotOnly: false,
proxy: {
"^/render/": {
target: "https://xymba-renderbot.herokuapp.com/",
pathRewrite: { "^/render/": "/render/" },
changeOrigin: true,
logLevel: "debug"
}
}
}
}

keep getting a 404 on routing with params

Im doing a mern tutorial on freecodecamp and I have run into an issue that is driving me nuts.
I have a route which is localhost:5000/exercises/1234
however I keep getting a 404 on that route.
If someone could point out the error if would be appreciated.
I have a server file:
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const exerciseRouter = require("./routes/exercises");
const usersRouter = require("./routes/users");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("Mongo DB database connection established successfully πŸ‘ΎπŸ‘ΎπŸ‘Ύ");
});
app.use(cors());
app.use(express.json());
app.use("/exercises", exerciseRouter);
app.use("/users", usersRouter);
app.listen(port, () => {
console.log(`server is running on port ${port} 😻`);
});
and the route is defined here in an exercise.js file:
const router = require("express").Router();
const Exercise = require("../models/exercise.model");
router.route("/:id").get((req, res) => {
console.log(req.params);
Exercise.findById(req.params.id)
.then((exercise) => res.json(exercise))
.catch((err) => res.status(400).json(`Error ${req.params}`));
});
When i run this in the browser I get a 404 and not even the console log is run. Im really not sure why it isnt working.
Ah disregard this issue, i did an idiotic mistake. I had the method get inside another method (which isnt apparent in the above question).
Note to myself and others make sure your route aren't nested by accident in another route! lol

How to add Cache-control and ETag header in Angular 4 Universal?

After running Google page speed test I got suggestion:
Setting an expiry date or a maximum age in the HTTP headers for static
resources instructs the browser to load previously downloaded
resources from local disk rather than over the network.
server.ts
//import statements
enableProdMode();
const app = express();
const port = Number(process.env.PORT || 8080);
app.engine('html', ngExpressEngine({
bootstrap: ServerAppModule
}));
app.set('view engine', 'html');
app.set('views', 'src');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
import {
getHomeApi, sendMailApi
} from './backend/api';
app.get('/api/homeData', getHomeApi);
app.post("/api/send", sendMailApi);
app.use(compression());
app.use('',express.static('dist'));
app.use('/assets',express.static('dist/assets'));
app.use('/static',express.static('dist/static', {
index: false
}));
ROUTES.forEach(route => {
app.get(route, (req, res) => {
console.time(`GET: ${req.originalUrl}`);
res.render('../dist/index', {
req: req,
res: res
});
console.timeEnd(`GET: ${req.originalUrl}`);
});
});
app.listen(port,() => {
console.log(`Listening at ${port}`);
});
It suggested me to leverage caching for following static resources.
http://00.000.00.00:8080/api/homeData (expiration not specified)
http://dsms0mj1bbhn4.cloudfront.net/assets/pub/shareaholic.js
(10minutes)
https://www.google-analytics.com/analytics.js (2 hours)
So how can I do this?
Thank You.