Tracking down a routing error with node / express - node.js

I've set up my express site with poet recently. I can use post.url and all the locals which are provided to all views, except the url routing - for example, in my blog.jade view:
ul.blog-preview$
each post in postList$
li$
a(href=#{post.url}) #{post.title}$
The view renders fine, but the route express tries when clicking on the post.url: "http://localhost:8080/undefined/post/poet-testundefined" where the post I was trying to reach is called 'poet-test'. So, I tried printing out post.url within the view
p #{post.url}
and to my surprise it printed out fine as post/poet-test. So, obviously I tried browsing to localhost:8080/post/poet-test, but that didn't work either because of a reference error on post.title, which I suspect is a problem because the post is getting lost in routing somehow.
This is my site.js (or app.js as most are called) and I've included what I think must be relevant to solving this.
var express = require('express')
, app = module.exports = express()
, http = require('http')
, poet = require('poet')(app)
poet
.createPostRoute()
.createPageRoute()
.createTagRoute()
.createCategoryRoute()
.init(function(locals) {
locals.postList.forEach(function ( post ) {
console.log('loading post: ' + post.url)
})
})
app.configure(function(){
//...etc
app.use(app.router);
//...etc
app.use(express.static(__dirname + '/public'));
});
//Dev settings
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions:true, showStack:true }));
app.set('port', process.env.PORT || 8080);
app.use(express.logger('dev'));
});
//Production settings
//....etc
// controllers - load them
controllers = ["pages", "blog"]
for (i in controllers) {
controller = require('./controllers/' + controllers[i]);
controller.setup(app)
}
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
As you can see, I check the post.url for each post it loads in poet.init(function(post) { ... }) and each of those check out with the correct /post/title url... so, I'm a little stuck here. Perhaps logging routes somehow with app.router() or a poet specific solution.

Check out the examples in the Poet repo -- You shouldn't have to escape your hrefs.. looks like the urls in Poet are fine, just some wrestling with Jade, try this:
a(href=post.url) post.title
https://github.com/jsantell/poet/blob/master/examples/views/includes/postSnippet.jade#L3

Related

Express req.query always empty

I was using express route like this and I want my urls to contain query strings initially.
app.get('/', function(req, res){
res.render('index', {});
});
app.get('/us01', function(req, res){
console.log('query: '+JSON.stringify(req.query));
res.render('templates/us01', {});
});
app.get('/benchmark', function(req, res){
res.render('templates/benchmark', {});
});
However, I never get my query strings printed no matter what query strings I append after /us01. For example, "localhost:9200/us01?a=1" req.query should get me {a:1}, correct? Is this a common thing? What am I missing here?
My app.js
"use strict";
var express = require('express');
var expApp = express();
var http = require('http').Server(expApp);
var path = require('path');
var bodyParser = require('body-parser');
// all environments
expApp.set('port', process.env.PORT || 5555);
expApp.set('views', __dirname + '/views');
expApp.set('view engine', 'ejs');
expApp.use(bodyParser.urlencoded({ extended: true }));
expApp.use(bodyParser.json());
expApp.use(express.static(path.join(__dirname, 'public')));
//----------------ROUTES--------------------------//
require("./routes/route.js")(expApp);
http.listen(expApp.get('port'), function(){
console.log('Node-Server listening on port ' + expApp.get('port'));
});
My indexController.js has :
$stateProvider
.state('us01', {
url: '/us01',
templateUrl: '/us01'
}).state('benchmark', {
url: '/benchmark',
templateUrl: '/benchmark'
})....
This simple code:
const express = require('express');
const app = express();
app.get('/us01', function(req, res) {
console.log(req.query);
res.send("ok");
});
app.listen(80);
Then, accessed by http://localhost/us01?a=1 produces this output in the console:
{ a: '1' }
Or, if I use:
console.log('query: ' + JSON.stringify(req.query));
Then, I see this in the console:
query: {"a":"1"}
So, clearly something else is wrong in your code.
"localhost:9200/us01?a=1" req.query should get me {a:1}, correct?
It should get you query: {"a":"1"} if the code you show is running on port 9200 on localhost.
Is this a common thing?
No. Something other than the code you show is busted because there's nothing wrong with just that bit of code.
What am I missing here?
Things to examine:
Are you getting any output in the console when you hit any of your expected routes?
Can you prove that your server is running and your browser is hitting your route handlers?
If you just do console.log(req.query), what output do you get?
Are you absolutely sure that you've killed any prior servers and started the server that corresponds to the code you show. People sometimes get fooled by a prior version of the server that is still running and doesn't actually contain the code they think they are running.
Are you 100% sure you are running your server on the desired port that matches the port in the URL you are using.
When all else fails, sometimes a computer reboot will make sure no prior versions of anything are still running.

Routing problems using NodeJS and AngularJS

I am building my first application using NodeJS & ExpressJS for the backend and AngularJS front end. I have all my front end routes working how I want, but I cannot figure out how to properly configure the Node backend so that when a specific URL is entered into the address bar, Node renders only the same Angular app every time.
For example, if I use About as a link to my about page in Angular, then the correct view will render and the address bar will show localhost:8080/about. However, if I just manually type in localhost:8080/about then Node responds with Cannot GET /about. Now I understand this is because my backend currently only handles the following:
var express = require('express');
var crypto = require('crypto');
var app = express();
app.set('views', __dirname + '/public');
app.engine('html', require('ejs').renderFile);
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
res.render('index.html');
});
// API
app.get('/api/sync', function(req, res){
// Here we generate a 32 byte string and make it the key
var num = Math.floor(Math.random()*100);
var key = crypto.createHash('md5').update(num.toString()).digest('hex');
key = key.slice(0, key.length/2);
console.log('Created key: ' + key);
res.send(key);
});
var server = app.listen(8080, function(){
console.log('Listening on port %d', server.address().port);
});
So what I want to do is make it so EVERY request to Node renders the same index.html page but then properly routes the view in Angular based on the URL. What is the best way to do this?
I just realized that using:
app.get('*', function(req, res){
res.render('index.html');
});
And placing this after all other routes I want to catch first will work.
Since I don't have enough reputation yet to just add a comment, it's worth noting that res.render() won't work if you're not using a server-side template rendering engine (as you are using EJS). You would instead want to use something like res.sendFile() if you were just serving a static HTML and Angular page with all the routing set up in Angular.
app.get( '*', function( req, res ) {
res.sendFile( __dirname + '/public/index.html' );
} );
The best way handle angular route in angular-app and backend route in backend.
Angular/Frontend:
sampleApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/home.html',
controller: 'MainController'
}).
when('/about', {
templateUrl: 'templates/about.html',
controller: 'AboutController'
}).
// >>> redirect other routes to
otherwise({
redirectTo: '/'
});
}]);
Backend:
For render static html you don't need app.get(...)
simple place index.html into:
public/index.html
and express serve it as html. Other not exists pages(routes) return 404 error and it is right.
In this case API fully separate and independent and angular fully single page app. Express serve static resources needed for angular.

Cannot find view in node/express

As my username implies, I'm new to node.js. I'm trying to learn it. As part of this process, I'm working to setup a basic web site. This web site will show a couple of basic web pages and expose a single REST endpoint. The structure of my project is:
config.js
home.html
start.js
routes.js
server.js
resources
css
style.css
images
up.png
down.png
javascript
home.html.js
start.js has my main server code. That file gets executed via command line using 'node start.js'. Once started, my server begins listening on port 3000. The code in start.js looks like this:
var express = require('express');
var app = express();
var UserProfileHandler = require('./app/handlers/UserProfileHandler');
app.configure(function () {
app.engine('html', require('ejs').renderFile);
app.set('views', __dirname + '/');
app.use(express.logger({ stream: expressLogFile }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
var routes = {
userProfiles: new UserProfileHandler()
};
function start() {
routeConfig.setup(app, routes);
var port = process.env.PORT || 3000;
app.listen(port);
console.log("SUCCESS: Server listening on port %d in %s mode", port, app.settings.env);
}
exports.start = start;
exports.app = app;
My routes.js file has the following:
function setup(app, routes) {
viewSetup(app);
apiSetup(app, routes);
}
function viewSetup(app) {
app.get('/', function (req, res) {
res.render("/home.html");
});
app.get('/home.html', function (req, res) {
res.render("/home.html");
});
}
function apiSetup(app, routes) {
app.get('/api/userProfiles/:username', routes.userProfiles.getUserProfiles);
}
I am trying to load home.html in a browser window. I attempt this by visiting http://localhost:3000 and http://localhost:3000/ and http://localhost:3000/home.html. Unfortunately, none of these work. In fact, I receive an error that says:
Express 500 Error: Failed to lookup view "/home.html"
I know that I'm close. If I visit http://localhost:3000/api/userProfiles/me I receive a JSON response back like I'm expecting. For some reason, i can't seem to return HTML though. My home.html file looks like the following.
<html>
<head>
<script type='text/javascript' src='/resources/javascript/home.html.js'></script>
</head>
<body>
We're up and running! <img src='/resources/images/up.png' />
</body>
</html>
Its a pretty basic HTML file. Even if the HTML comes back though, I'm concerned the JavaScript file and Image it references won't be accessible. I'm concerned of this because I'm not really sure how paths and such work in Node.
How do I get home.html to work in my Node setup?
Thank you!
as your view file is in same folder as your main file, below changes should make it work
1.change the view folder configuration line
from
app.set('views', __dirname + '/');//wont work
to
app.set('views', __dirname);//will work
2.change view render lines
from
res.render("/home.html");//wont work
to
res.render("home.html");//will work
with both the changes, the view should be working fine
update to below comments.
the issue you mentioned regarding the images,css and js is due to the static folder configuration which should be changed from
app.use(express.static(__dirname + '/public'));
to
app.use(express.static(__dirname + '/resources'));
as your static folder is named resources.
but make sure in your view you are refering the css/js/image files like
eg:
/css/style.css
/images/up.png
/images/down.png
/javascript/home.html.js
from your view file
Also if the above dint work, check if you have given the path correctly and also you can try by taking the
app.use(express.static(__dirname + '/resources'));
before the
app.use(express.methodOverride());
app.use(app.router);
lines like
app.configure(function () {
app.engine('html', require('ejs').renderFile);
app.set('views', __dirname + '/');
app.use(express.static(__dirname + '/public'));
//try changing the position of above line in app.configure and resatrt node app
app.use(express.logger({ stream: expressLogFile }));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
});
had similar problem in my case is
app.set('./views');
look for the dot, dont know why but the dot will mess it up.
I had it like this
app.set('/views') and no matter what i did couldt find the folder until added the dot.

Express and AngularJS - web page freezes when attempting to open home page

I will explain the issue in as much detail as possible.
I am attempting to use AngularJS with Express and am running into trouble. I wish to display HTML files (not using a templating engine). These HTML files will have AngularJS directives.
However, I am not able to display a simple HTML file itself!
The directory structure is as follows:
Root
---->public
-------->js
------------>app.js
------------>controllers.js
---->views
-------->index.html
-------->partials
------------>test.html
---->app.js
The contents of public/js/app.js is:
angular.module('myApp', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {templateUrl: 'partials/test.html', controller: IndexCtrl});
$routeProvider.otherwise({redirectTo: '/'});
}]);
The contents of public/js/controllers/js is:
function IndexCtrl() {
}
The contents of the body tag in views/index.html is:
<div ng-view></div>
That's it. The expectation is that AngularJS will substitute the above view with test.html - views/partials/test.html whose contents are:
This is the test page!
enclosed within the paragraph tags. That's it!
Finally, the contents of ROOT/app.js file is:
var express = require('express');
var app = module.exports = express();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.use(app.router);
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// routes
app.get('/', function(request, response) {
response.render('index.html');
});
// Start server
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});
Now, when I do $node app.js in the root folder, the server starts without any error. However if I go to localhost:3000 in the browser, the URL changes to localhost:3000/#/ and the page gets stuck / freezes. I can't even check the console log in Chrome!
This is the problem that I am facing. Any clue about what I am doing wrong?
Finally figured it out - after many intense moments of hair pulling!!
The reason why the page freezes is because (explained step by step):
User launches localhost:3000
This requests the express server for '/'
Express renders index.html
AngularJS will render the template 'partials/test.html'.
Here, I am taking a wild guess - AngularJS has made a HTTP request for the page 'partials/test.html'.
However, you can see that express or rather app.js does not have a handler for this GET request. That is, the following code is missing:
app.get('partials/:name', function(request, response) {
var name = request.params.name;
response.render('partials/' + name);
});
inside app.js of the ROOT directory. Once I add this code, the page renders as expected.
Try following the design pattern in this working fiddle. Code shown below. You can replace the template option with templateUrl and it should still work fine.
var app = angular.module('app', []);
app.config(['$routeProvider', function($routeProvider){
$routeProvider.when('/', {template: '<p>Index page</p>', controller: 'IndexCtrl'});
$routeProvider.otherwise({redirect:'/'});
}]);
app.controller('IndexCtrl', function(){
});

Jade URL Routing in Node Express

I am building a Node Express application using Jade, and I am confused about how to route my views to the specific requests the browser will make. I understand that in order to get URLs to work in the browser, we need to use Node's routes; however, from looking online, I have discovered that Express has its own router.
I used PHPStorm to start up my project, and the index.jade will load... but how do I load the others? Here is my existing code:
var express = require('express'), routes = require('./routes'), http = require('http'), path = require('path');
var app = express();
app.configure(function ()
{
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(require('less-middleware')({ src:__dirname + '/public' }));
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function ()
{
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function ()
{
console.log("Express server listening on port " + app.get('port'));
});
What is the most basic way to route my application, and where can I find more extensive documentation on this topic?
Thanks.
I understand that in order to get URLs to work in the browser,
we need to use Node's routes; however, from looking online,
I have discovered that Express has its own router.
Node.js per-se does not provide support for "routes", but Express does. You build your routes in Express using the following syntax:
app.[verb]('[url-path]', [handler]);
So your route app.get('/', routes.index) will process HTTP GET request to URL path / with the routes.index function. Express will automatically pass a request and response objects to your handler.
You can add more routes like this:
app.get('/users', routes.userList);
app.get('/user/:id', routes.userInfoView);
app.post('/user/:id', routes.userInfoSave);
You can find more information about this here http://expressjs.com/api.html#app.param
I am building a Node Express application using Jade, and I
am confused about how to route my views to the specific
requests the browser will make.
Once a route handler is invoked, say (routes.userList) you can call res.render() method inside userList to render the Jade file that you want. For example:
res.render('user_list',
{ users: [{name: "user1", age: 10}, {name: "user2", age: 20}] });
See here for more information: http://expressjs.com/api.html#res.render

Resources