Express failing to look up view - javascript

I am trying to create a SPA app, but when i start my application it does an infinte loop leading to a crash. I am using ExpressJS 4.3.0
App architecture:
public
--partials
----index.jade
server.js
My express code:
var app = express();
var port = process.env.PORT || 8080;
app.set('views', __dirname + '/public');
app.set('view engine', 'jade');
app.use(express.static(__dirname + '/public'));
app.get('*', function (req, res) {
res.render('partials/index');
});
app.get('/', function (req, res) {
res.render('partials/index');
});
app.get('/partials/:name', function (req, res) {
res.render('/partials/' + req.params.name);
});
app.listen(port);
console.log('Server is running on port: ' + port);
If i use
res.render('/partials/index');
i recieve a message:
Error: Failed to lookup view "/partials/index" in views directory

Its because of view lookup function in express view lookup
if (!utils.isAbsolute(path)) path = join(this.root, path);
which makes it assume '/partial/index' is already an absolute path and didnt prefix with root path.
Also move the
app.get('*', function (req, res) {
res.render('partials/index');
});
to end else it will always serve the index view.

It looks like you shouldn't have a preceding / in your view path in render(). Just use 'partials/' + req.params.name.
On a related note, are you sure you want your actual view files to be public? Usually they are stored outside of the public static directory (e.g. ./public contains static assets and ./partials contains views). Also that way you don't have to keep prefixing view paths with partials/.

Related

node js routing with ejs res.render does not work, but res.send does

I am setting up the environment for a node js app.
But the views/ejs files are not being rendered. If i do:
app.get("/", function(req, res){
res.send('Something');
});
This works. But, if I do(having an index,ejs file):
app.get("/", function(req, res){
res.render(index);
});
It does not work, I get "index is not defined" on the cleint side in the web, but no error in the command line.
Here is the app.js:
var express = require("express");
var path = require("path");
var app = express();
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.static(path.join(__dirname, 'public')));
app.get("/", function(req, res){
res.send('Something');
});
app.get("/", function(req, res){
res.render(index);
});
const port = process.env.PORT || 3000
app.listen(port, function () {
console.log(`Express is running on port ${port}`)
})
IS there something wrong with the app.set parameters, or has something changed? I am following a tutorial which might be out dated, but checking the docs, I do not see an issue.
So, what is wrong here, is there a new way to do the routing with ejs? I know partials are gone now. Does this mean no ejs files at all anymore, and if so, how is it supposed to be done now? By rendering an html file?
Thanks
Well, I'm not a pro of express but here index is not defined because you write it like a variable. Try using something like this
res.render(path.resolve(__dirname + "/views/index"));

Change .ejs to .html

How can I make the following server.js code work for .html files instead on .ejs in Node JS. Thanks!
var express = require('express');
var app = express();
// set the port of our application
// process.env.PORT lets the port be set by Heroku
var port = process.env.PORT || 8080;
// set the view engine to ejs
app.set('view engine', 'ejs');
// make express look in the public directory for assets (css/js/img)
app.use(express.static(__dirname + '/public'));
// set the home page route
app.get('/', function(req, res) {
// ejs render automatically looks in the views folder
res.render('index');
});
app.listen(port, function() {
console.log('Our app is running on http://localhost:' + port);
});
You should be able to just remove these lines:
// set the view engine to ejs
app.set('view engine', 'ejs');
// set the home page route
app.get('/', function(req, res) {
// ejs render automatically looks in the views folder
res.render('index');
});
and add your .html files to public/.
Testing this with this code
var express = require('express');
var app = express();
// set the port of our application
// process.env.PORT lets the port be set by Heroku
var port = process.env.PORT || 8080;
// make express look in the public directory for assets (css/js/img)
app.use(express.static(__dirname + '/public'));
app.listen(port, function() {
console.log('Our app is running on http://localhost:' + port);
});
and this directory structure
├── package.json
├── public
│   └── index.html
└── server.js
Works fine for me.

node server.js - Cannot GET /

I am currently working on a project which is a webpage using angular to dynamically change DOM elements. Within the project is a public folder which contains all HTML, CSS, JavaScript and JSON objects. The project must be distributed so I am using node to run from localhost. This is my server.js code:
var express = require('express');
var app = express();
var path = require('path');
app.get('/', function(req,res){
res.sendFile(path.join(__dirname + '/public'));
});
app.listen(8080, function(){
console.log((new Date()) + " Server is listening on port 8080");
});
When I head to localhost:8080 it just says Cannot GET /. Where am I going wrong?
The correct way to serve static files with express is as follows:
//Look for statics first
app.use(express.static(path.join(__dirname, 'public')));
//Return the index for any other GET request
app.get('/*', function (req, res) {
res.sendFile('index.html', {root: path.join(__dirname, 'public')});
});
Edit: on a side note this may be worthwhile to mention that app.get should be the last route declared in node so if you want API endpoints exposed declare them above (before) the final app.get.
You forgot to point to the actual html file you want to display. If you have a index.html in your public directory, just point tot '/public/index.html' . That works (tested it here).
Followed user Muli's answer and all files are now being served correctly. Code here:
var express = require('express');
var app = express();
var path = require('path');
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req,res){
res.sendFile('index.html', {root: path.join(__dirname, './public')})
});
app.listen(8080, function(){
console.log((new Date()) + " Server is listening on port 8080");
});

Route an entire folder and its content

I want to protect a folder and its content by redirecting the user back to index.
I've tried this, but it only works partially.
var express = require('express');
var path = require('path');
var http = require('http');
var app = express();
app.set('port', 8080);
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'views')));
app.get('/', function(req, res) {
res.render('index.ejs');
});
app.get('/protected/*', function(req, res, next) {
res.redirect('/');
next();
});
//activating server
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
This routes, for example, "localhost:8080/protected" and "localhost:8080/protected/asdf", but not "localhost:8080/protected/otherPage.html".
In this case asdf is not an actual file, but otherPage.html is. So if the file is there it doesn't redirect, but if it is not then it redirects. Why is this?
Your line dealing with static files app.use(express.static(path.join(__dirname, 'views'))); appears before app.get('/protected') so its being matched first.
If you moved the static handler to later in the code this would work as you require.
However, I would recommend splitting the static items into a separate folder to guard against accidentally revealing any server-side code you might be including in ejs files in the views folder.

Default route in Express.js

I'm writing an application with node.js and express.
I have setup a default route as this :
app.get('/', function(req, res){
res.sendfile('./views/index.html');
});
This works fine when I goto /localhost:port/
But in the URL when I type anything after that, /localhost:port/blah I get 404 ERROR which makes sense.
I want to setup a default route so that no matter what I type in the URL after localhost:port/ it should all get back the same html file.
I tried changing / to * :
app.get('*', function(req, res){
res.sendfile('./views/index.html');
});
but after I do this I start getting this error in the console and nothing shows up:
Uncaught SyntaxError: Unexpected token <
in all of my Javascript files: :3000/scripts/myscript.js:1
somehow my javascript file show the content of HTML
===EDIT====
I used this and it worked fine for first level urls: like loclhost:port/blah
app.use(function(req, res){
res.sendfile('./views/index.html');
});
but when the URLs are multilevel, I see the same problem as described earlier localhost:port/blah/foo
The problem here is that router is looking for public directory under /blah folder for all the javascript and CSS files in this case, which does not exist. And it's returning the default HTML file. How do I fix this?
==================EDIT POSTING THE WHOLE CODE =========================================
var http = require('http');
var express = require('express');
var api = require('./routes/api');
var mongoose = require('mongoose');
var app = express();
mongoose.connect('mongodb://localhost/mydb');
app.set('port', process.env.PORT || 3000);
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.get('/api/user/:userid', api.getUserInfo);
app.get('/', function(req, res){
res.sendfile('./views/index.html');
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
In addition to this, I have an HTML with a myscript linked in it,
<script type="text/javascript" src="./scripts/myscript.js" ></script>
Add this route at the after of all your previous routes
app.get('*',function (req, res) {
res.redirect('/');
});
This will redirect any route not handled to the index "/"
As stated here, you can add this middleware just after your routing logic:
app.use(function(req, res){
res.send(404);
});
You might find this answer also useful.
Of course, you need to adapt the res.send() part to meet your needs.
With the newer version of express I would suggest using res.sendStatus as res.send has been deprecated.
Express v3
app.use(function(req, res){
res.send(404);
});
Express v4
app.use(function(req, res){
res.sendStatus(404);
});

Categories