I want to use express.js with Flatiron's director (router) and Resourceful (ODM) because I need like the benefits of routing tables and clean multi-db schemas with validation.
The reason why I now completly switch to Flatiron is, is because I think it needs some more time and there is not much doc material.
However, that is the current way I use director in express:
var express = require('express')
, director = require('director');
function hello(){
console.log('Success');
}
var router = new director.http.Router({
'/': {
get: hello
}
});
Unfortunatly this doesn't work and gives me just a "Cannot GET /"
So what's to do?
var express = require('express')
, director = require('director')
, http = require('http');
var app = express();
var hello = function () {
this.res.send(200, 'Hello World!');
};
var router = new director.http.Router({
'/': {
get: hello
}
});
var middleware = function (req, res, next) {
router.dispatch(req, res, function (err) {
if (err == undefined || err) next();
});
};
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.bodyParser());
app.use(middleware);
app.use(express.static(__dirname + '/public'));
});
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
There is a sample app using express, resourceful and director here.
If you have more doubts, you can ask them in our IRC room #nodejitsu on freenode.
First, in order to use director you need to wrap it up as a middleware and pass it to express, like so:
app.use(function (req, res, next) {
router.dispatch(req, res, function (err) {
if (err) {
// handle errors however you like. This one is probably not important.
}
next();
});
};
Aside from that: You don't need director to use resourceful, and express has its own router (so you may not even need/want director).
Related
I'm having a problem routing in express 4. I was following the example, but it isn't loading. I'm just getting a spinning wheel.
How do you do routing in express version 4?
app.js:
var express = require('express');
var http = require('http');
var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
var port = (process.env.PORT || process.env.VCAP_APP_PORT || 5000);
app.use('/birds', require('./controller/bird'));
http.createServer(function (req, res) {
//res.writeHead(200, {'Content-Type': 'text/plain'});
//res.end('Hello World!\n');
}).listen(port);
console.log('Server running at http://127.0.0.1:'+port);
bird.js:
var express = require('express');
var router = express.Router();
// middleware specific to this router
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});
// define the home page route
router.get('/', function(req, res) {
res.send('Birds home page');
});
// define the about route
router.get('/about', function(req, res) {
res.send('About birds');
});
module.exports = router;
You're not calling the app.listen() function. Instead of the http.createServer one, you should invoke the Express function.
Please, take a look at a basic example.
Relevant code:
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Edit: as slebetman wrote in the comment, the more general way for it is:
http.createServer(app).listen(port, function(){
console.log('now listening on port ' + port);
});
I get an error trying to render a simple html page using NodeJS and Express 4.10.4, with the following code:
var path = require('path');
var express = require('express');
var logger = require('morgan');
var app = express();
app.set('port', process.env.PORT || 8080);
app.use(express.static(path.join(__dirname, '/client')));
app.set('view engine', 'html');
app.use(logger('dev'));
app.get('*', function (req, res) {
res.sendFile('/index.html');
});
app.use(function (err, req, res, next) {
console.log(err.stack);
res.status(500).send({message: err.message});
});
console.log('Server has started on port: '+ app.get('port'));
My index.html page is within the client folder, it is rendered in my browser but I get the following error:
Error: ENOENT, stat 'c:\index.html'
Has anyone an idea what's the issue?
The error code 'ENOENT' is a unix error code indicating absence of file.
Check here: http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html
I'll advise you use sendFile method of express response with the options and callback stated in the API here: http://expressjs.com/api.html#res.sendFile. Use the options object literal to indicate the location of the html file. See sample below. At first request there is no error. At subsequent requests, the callback will receive an error with response status code 304 - read about what this means.
See below for an amendment to your code and see if it helps you.
var path = require('path');
var express = require('express');
var logger = require('morgan');
var app = express();
app.set('port', process.env.PORT || 9090);
app.use(express.static(path.join(__dirname, '/client')));
app.set('view engine', 'html');
app.use(logger('dev'));
app.get('*', function (req, res) {
var options = {
root: __dirname + '/client/'
};
res.sendFile('/index.html', options, function (err) {
if (err) {
console.log('Error in res : %s, status code: %s', err, res.statusCode);
res.status(err.status).end();
}
else {
console.log('Sent: ', 'index.html');
}
});
});
app.use(function (err, req, res, next) {
console.log('error stack is here : ' + err.stack);
res.status(500).send({message: err.message});
});
app.listen(app.get('port'), function() {
console.log('Server has started on port: '+ app.get('port'));
});
I'm new to Node.js and Express.
How can I access the variable created in "app.js" called "pg" in "routes/index.js"?
app.js
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var pg = require('pg');
var conString = "postgres://someuser:somepass#localhost/postgres"
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
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(app.router);
app.use(express.static(path.join(__dirname, 'public')));
routes/index.js
/*
* GET home page.
*/
exports.index = function(req, res){
var client = new pg.Client(conString);
client.connect(function(err) {
if(err) {
return console.error('could not connect to postgres', err);
}
client.query('SELECT NOW() AS "theTime"', function(err, result) {
if(err) {
return console.error('error running query', err);
}
console.log(result.rows[0].theTime);
//output: Tue Jan 15 2013 19:12:47 GMT-600 (CST)
client.end();
});
});
I got the error in the browser:
Express 500 ReferenceError: pg is not defined
Can you guys give me a clue?
Best Regards
A simple way of passing anything to route handlers (whether they are declared in different files or not) in Express is to use app.locals:
// app.js
...
var app = express();
...
app.locals.someVar = someValue;
...
// somewhere else
module.exports.myhandler = function(req, res) {
var someVar = req.app.locals.someVar;
...
};
// app.js
var routes = require('./routes/index')({ varname: thevar });
...
...
And
// /routes/index.js
module.exports = function(options) {
var moduleVar = options.varname;
return {
someMethod: function (req, res) { var i = moduleVar + 2; // etc},
anotherMethod: function (req, res) {}
};
};
I do this when I create a connection (or connection pool) and simply want my modules to have access to the db without having to create another connection. All depends on your project of course, one of my hit tracking modules uses it's own connection, so I pass it the db info and from there it does it's own thing. This allows me to have multiple apps using this tracker module while each connecting to their own db.
You could define the variable without the var keyword to make the variable global.
what I'm trying to achieve is to accept requests for a value, add that value to an array, run a function on it that'll query it and then remove it from the array with the shift function. What I have so far is a simplified framework of that, but it's now giving me this error.
RangeError: Maximum call stack size exceeded
if there's anything I can do to improve my code as well please let me know.
app.js
var express = require('express')
, http = require('http')
, path = require('path')
, fs = require('fs')
, eventEmitter = require('events').EventEmitter;
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(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
var ee = new eventEmitter;
var queries = new Array();
ee.on('next', next_search);
function next_search() {
console.log(queries);
search();
}
function search() {
// do something
queries.shift();
console.log(queries);
ee.emit('next')
}
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.post('/search', function(req, res) {
letter = req.param('letter');
console.log(letter);
queries.push(letter);
next_search();
});
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
jQuery code
$(document).ready(function() {
$('#letter').on("keyup", function() {
letter = $('#letter').val();
$.post("/search", { letter: letter}, function(data) {
$('#status').html(data);
});
});
});
This is an infinite function call, when you post. next_search -> search ->ee next event-> next_search -> ...
ee.on('next', next_search);
function next_search() {
console.log(queries);
search();
}
function search() {
// do something
queries.shift();
console.log(queries);
ee.emit('next') // execute first line
// only do this when queries is non-empty
}
You should check if queries is not empty, only then do next_search.
Hello I am trying to retrieve something from the post, and need the rawBody property from the incoming request. How can I retrieve it??
I tried using express.bodyParser() and in my post handler, I was looking for req.rawBody, and it was undefined.
I even tried it with connect.bodyParser(), but I still have no luck with it. I am getting undefined for rawBody.
I was reading on the stackoverflow site saying that they had removed the rawBody functionality, but mentioned that it is a quick fix to add it to our own middleware file. I am a newbie, so I do not have a clue as to how to achieve this. Below is my code snippet.
/**
* Module dependencies.
*/
var express = require('express')
, connect = require('connect')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path');
var app = express();
// all environments
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(connect.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
/**custom stuff**/
app.post('/upload',function(req, res){
console.log(req.header('Content-Type'));
console.log(req.header('Host'));
console.log(req.header('User-Agent'));
console.log(req.rawBody);
console.log(req.body);
res.send("<h1> Hello the response is "+req.body.username);
});
/** end**/
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Any help with this is much appreciated.
Thank you.
You can use your own middle ware to do this:
app.use(function(req, res, next){
var data = "";
req.on('data', function(chunk){ data += chunk})
req.on('end', function(){
req.rawBody = data;
next();
})
})
// Your route registration:
app.get('/', function(){// whatever...})
app.post('/test', function(req, res){
console.log(req.rawBody);
res.send("your request raw body is:"+req.rawBody);
})
I'm back again :D. After read the connect.bodyParser I've found something: The bodyParser only parse the data which mime type is one of: application/json, application/x-www-form-urlencoded and multipart/form-data. So I think this is another approach, it's not generally elegant but acceptable: When you try to send raw data to server, change the mime type to something different. As your question it's a string, so I choose text/plain as example:
// if the request's mime type is text/plain, read it as raw data
var myRawParser = function(req, res, next){
req.rawData = '';
if(req.header('content-type') == 'text/plain'){
req.on('data', function(chunk){
req.rawData += chunk;
})
req.on('end', function(){
next();
})
} else {
next();
}
}
// ...
app.use(myRawParser);
app.use(express.bodyParser());
// ...
// Here is my test route:
app.post('/test', function(req, res){
console.log('Mime type is:'+req.header('content-type'));
console.log('Raw data is:'+req.rawData);
console.log('Body via bodyParser is:');
console.dir(req.body);
res.send('Hello!');
})
I've tested it via curl:
$ curl -d 'test=hello' 127.0.0.1:3000/test
// console result:
Mime type is:application/x-www-form-urlencoded
Raw data is:
Body via bodyParser is:
{ test: 'hello' }
and:
$ curl -d 'test=hello' -H 'Content-Type:text/plain' 127.0.0.1:3000/test
// console result:
Mime type is:text/plain
Raw data is:test=hello
Body via bodyParser is:
{}
It's not actually integrate your middle ware to bodyParser, just make them work together.
Building on #Rikky's solution, the way to avoid a race condition in the data event handlers is to continue calling the middleware chain immediately after setting the handlers. Don't wait for req.on('end') to call next(), because that next() call is what allows the json body parser to register its own data and end handlers; if you wait until end is triggered on the request, they'll miss all the relevant events. Instead, use promises:
const process = require('process');
const bodyParser = require('body-parser');
const express = require('express');
function main() {
const app = express();
app.use((req, res, next) => {
req.rawBody = new Promise(resolve => {
buf = '';
req.on('data', x => buf += x);
req.on('end', () => {
resolve(buf);
});
});
next();
});
app.use(bodyParser.json());
app.use('/', async (req, res) => {
console.log('raw body:', await req.rawBody);
console.log('json parsed:', req.body);
res.send('bye\n');
});
app.listen('3000', 'localhost', (e) => {
if (e) {
console.error(e);
process.exit(1);
}
console.log('Listening on localhost:3000');
});
}
main();
The best solution I found is here: https://stackoverflow.com/a/9931478/1768033
Because using
req.on('data', function(chunk){ data += chunk})
somehow shifted the bits of the files I send in multiform-data requests, so they were not valid anymore.