Comparar commits

..

76 Commits

Autor SHA1 Mensagem Data
visionmedia d893009a8d Release 0.7.3 2010-03-16 13:17:41 -07:00
visionmedia b62e1741be Fixed requiring of haml / sass 2010-03-16 13:16:55 -07:00
visionmedia 903c2aa642 Added package.json 2010-03-16 08:31:33 -07:00
visionmedia d0a8bb550e Release 0.7.2 2010-03-16 08:08:17 -07:00
visionmedia f96f1423e1 Fixed GIT submodules (HAH!) 2010-03-16 08:06:26 -07:00
visionmedia 7bf17f2f61 Removed old support dir 2010-03-16 08:03:57 -07:00
visionmedia 670b6cfc15 Merge branch 'remove-kiwi' 2010-03-16 08:03:33 -07:00
visionmedia b6d2c8479c Release 0.7.1 2010-03-16 08:03:06 -07:00
visionmedia 5aaa114271 Docs 2010-03-16 08:01:51 -07:00
visionmedia e99c2791bb Docs 2010-03-16 07:58:06 -07:00
visionmedia 656d7754cd Express now using submodules again until a PM is adopted 2010-03-16 07:54:20 -07:00
visionmedia 4aaf10fbfc Moved support 2010-03-16 07:39:56 -07:00
visionmedia 85e77b77aa Added submodules 2010-03-16 07:02:49 -07:00
visionmedia f23ef09247 Chat example using millisecond conversions from ext 2010-03-15 16:00:39 -07:00
visionmedia 440d956438 Refactored Session#startReaper() with ext millisecond conversions 2010-03-15 15:59:37 -07:00
visionmedia acd2852cf3 ext >= 0.2.4 2010-03-15 15:58:02 -07:00
visionmedia 4246f43bdf ext >= 0.2.3 2010-03-15 09:57:38 -07:00
visionmedia 7d33769cd2 Revert "Removed sass / haml "dependencies""
This reverts commit 31fdba80d4.
2010-03-15 09:43:29 -07:00
visionmedia 31fdba80d4 Removed sass / haml "dependencies" 2010-03-15 09:42:15 -07:00
visionmedia 77f8e460d0 Better example app 2010-03-15 09:31:11 -07:00
visionmedia 51e51db9f7 Docs 2010-03-15 09:16:13 -07:00
visionmedia 73c506f19c Release 0.7.0 2010-03-15 09:13:18 -07:00
visionmedia 79143f3334 Chat sample app using pass() 2010-03-15 09:10:50 -07:00
visionmedia 128ba9040e Refactored Router#matchingRoute() 2010-03-15 09:09:51 -07:00
visionmedia 300cfe74ad Request#pass() accepts a pathname string 2010-03-15 09:02:44 -07:00
visionmedia f008af05bd Merge branch 'pull' 2010-03-15 08:54:57 -07:00
Aaron Heckmann 3aa870d6bd return this in pass 2010-03-15 08:50:35 -07:00
Aaron Heckmann 25e1a8c001 add pass specs 2010-03-15 08:50:26 -07:00
Aaron Heckmann 0ba3b114b0 add pass support 2010-03-15 08:50:20 -07:00
visionmedia c429e88e8e Updated --version of node tested against in readme 2010-03-15 08:42:22 -07:00
Aaron Heckmann c7a2fe8440 remove profiler from plugins.js 2010-03-15 08:41:21 -07:00
Aaron Heckmann de237e760b remove Profiler 2010-03-15 08:41:03 -07:00
visionmedia 927f5c9883 Logger copyright 2010-03-12 07:36:50 -08:00
visionmedia 88f461baf2 Logger using Date#format() 2010-03-12 07:14:57 -08:00
visionmedia 3251ae26a0 Fixed plot format 2010-03-12 07:09:56 -08:00
visionmedia e84c81633e "combined" using printf() 2010-03-12 07:09:20 -08:00
visionmedia a2ec966ac7 "common" Logger format using printf() 2010-03-12 07:06:47 -08:00
visionmedia 69660fbfda Merge branch 'integration' 2010-03-12 06:58:34 -08:00
visionmedia dcedca1a80 Removed 'sinatra' logger, added duration to 'common' log format 2010-03-12 06:58:23 -08:00
visionmedia 6455e954fc Removed CommonLogger, use Logger 2010-03-12 06:53:17 -08:00
visionmedia 646904688f No need for utils.mixin() here 2010-03-11 11:16:48 -08:00
visionmedia 62779fc972 Doc typo 2010-03-11 11:14:33 -08:00
visionmedia fdee4cde26 Sample app in readme 2010-03-11 11:14:02 -08:00
visionmedia 0c18ac5adc Added kiwi installation docs 2010-03-11 11:05:41 -08:00
visionmedia 6da4a942ca Managing dependencies with the kiwi package manager. Closes #228
Merge branch 'kiwi'
2010-03-11 11:01:54 -08:00
visionmedia 565f68d2d7 Added kiwi.seed() calls to make them available via require()
This is needed since the view plugin uses
the regular require() and not kiwi.require()
2010-03-11 11:00:47 -08:00
visionmedia a7cee4c889 Removed references to submodules 2010-03-11 10:57:26 -08:00
visionmedia 4f315f9b11 Added haml / sass dependencies 2010-03-11 10:46:08 -08:00
visionmedia 51febfec2d Actually added seed.yml :) 2010-03-10 19:23:56 -08:00
visionmedia df8bd96b2e Added support for arbitrary view engines 2010-03-10 19:23:56 -08:00
visionmedia 9da9beb342 Added seed.yml for kiwi package management support 2010-03-10 19:23:56 -08:00
visionmedia f93af823df Fixed typo 2010-03-10 19:23:51 -08:00
Aaron Heckmann 5e74723a92 add logger 2010-03-10 22:09:07 -05:00
visionmedia ec77e1acea HTTP client appends query string when method is GET. Closes #205 2010-03-10 19:01:40 -08:00
visionmedia 1afad64972 Misc refactoring to http client 2010-03-10 18:53:12 -08:00
visionmedia a3365dda07 Removed usage of RESTful route funcs as http client 2010-03-10 18:49:04 -08:00
visionmedia 4c246a4cd1 Merge branch 'async-plugins' 2010-03-10 18:34:09 -08:00
visionmedia 934ffd0731 Fixed params in show-exception page 2010-03-10 18:32:25 -08:00
visionmedia 790e2c233d Inverted plugin async support. Return true WHEN async 2010-03-10 17:06:46 -08:00
visionmedia 9e9967381c Misc refactoring 2010-03-10 17:01:40 -08:00
visionmedia 891ed08827 Request#trigger() now supports callback as 2nd or 3rd arg 2010-03-10 17:01:08 -08:00
visionmedia 55d13a6f08 Doc typo 2010-03-10 16:58:53 -08:00
visionmedia 5569ea4397 Removed custom exceptions
because they are lame
2010-03-10 16:57:51 -08:00
visionmedia 693e37459a Removed InvalidResponseBody / InvalidStatusCode
stupid anyway, just dont fuck shit up :)
2010-03-10 16:46:47 -08:00
visionmedia 90de1fa55d Refactoring routing slightly 2010-03-10 16:34:21 -08:00
visionmedia 6d6e1557ce Refactored Request#trigger() 2010-03-10 16:26:20 -08:00
visionmedia 2d84f16dc0 Hooks do not support async at the moment anyway, return true 2010-03-10 16:14:54 -08:00
visionmedia 2f98ef9f6d Strict comparisons 2010-03-10 16:12:16 -08:00
visionmedia e0c07d2385 Fixed typo 2010-03-10 16:11:38 -08:00
ciaranj 0b2413d8c0 Missed a curly brace out 2010-03-10 23:52:31 +00:00
ciaranj e92b01f813 Change the approach to be truth based
Now just enforces that a plugin returns true, if it doesn't return true then
we assume the plugin is taking care of making sure that the plugin chain continues.

A sensible enhancement to this might be to improve the request.trigger function to timeout
after a fixed period, log a warning, then carry on as normal ??

I'm not too sure of what 'Hooks.js' does so I may haveconfigured that incorrectly, just FYI
2010-03-10 23:49:38 +00:00
ciaranj 27ff13459f Merge branch 'master' of git://github.com/visionmedia/express into async_plugins
Conflicts:
	lib/express/plugins/cookie.js
	lib/express/plugins/hooks.js
	lib/express/request.js
2010-03-10 23:36:18 +00:00
ciaranj 3e80915454 Oops, still had some proto code in there 2010-03-10 23:23:37 +00:00
ciaranj 4063d2e2c4 Initial stab at async plugin execution 2010-03-10 23:16:31 +00:00
visionmedia ce9416857b Renamed params -> keys now that ext.js is fixed 2010-03-10 13:39:49 -08:00
visionmedia 575d5e8e57 Updated ext.js. Closes #227 2010-03-10 13:38:07 -08:00
34 arquivos alterados com 341 adições e 396 exclusões
+2
Ver Arquivo
@@ -1 +1,3 @@
.DS_Store
*.seed
*.log
+8 -8
Ver Arquivo
@@ -1,12 +1,12 @@
[submodule "lib/support/haml"]
path = lib/support/haml
url = git://github.com/creationix/haml-js.git
[submodule "lib/support/js-oo"]
path = lib/support/js-oo
[submodule "lib/support/oo"]
path = lib/support/oo
url = git://github.com/visionmedia/js-oo.git
[submodule "lib/support/sass"]
path = lib/support/sass
url = git://github.com/visionmedia/sass.js.git
[submodule "lib/support/ext"]
path = lib/support/ext
url = git://github.com/visionmedia/ext.js.git
[submodule "lib/support/sass"]
path = lib/support/sass
url = git://github.com/visionmedia/sass.js.git
[submodule "lib/support/haml"]
path = lib/support/haml
url = git://github.com/creationix/haml-js.git
+42
Ver Arquivo
@@ -1,4 +1,46 @@
0.7.3 / 2010-03-16
==================
* Added package.json
* Fixed requiring of haml / sass due to kiwi removal
0.7.2 / 2010-03-16
==================
* Fixed GIT submodules (HAH!)
0.7.1 / 2010-03-16
==================
* Changed; Express now using submodules again until a PM is adopted
* Changed; chat example using millisecond conversions from ext
0.7.0 / 2010-03-15
==================
* Added Request#pass() support (finds the next matching route, or the given path)
* Added Logger plugin (default "common" format replaces CommonLogger)
* Removed Profiler plugin
* Removed CommonLogger plugin
0.6.0 / 2010-03-11
==================
* Added seed.yml for kiwi package management support
* Added HTTP client query string support when method is GET. Closes #205
* Added support for arbitrary view engines.
For example "foo.engine.html" will now require('engine'),
the exports from this module are cached after the first require().
* Added async plugin support
* Removed usage of RESTful route funcs as http client
get() etc, use http.get() and friends
* Removed custom exceptions
0.5.0 / 2010-03-10
==================
+1 -4
Ver Arquivo
@@ -3,9 +3,6 @@ NODE = node
all: test
init:
@git submodule init && git submodule update
test:
@$(NODE) spec/node.js all
@@ -17,4 +14,4 @@ app-chat:
app-upload:
@$(NODE) examples/upload/app.js
.PHONY: init test app
.PHONY: test app
+19 -28
Ver Arquivo
@@ -24,14 +24,16 @@
## Installation
Currently Express must be cloned (or downloaded), you can use the following command to
get rolling and initialize the submodule dependencies:
Install the [Kiwi package manager for nodejs](http://github.com/visionmedia/kiwi)
and run:
$ kiwi -v install express
or
$ git clone git://github.com/visionmedia/express.git && cd express && git submodule update --init && make app
Or with the [gh](http://github.com/visionmedia/gh) utility:
$ gh clone visionmedia express && cd express && git submodule update --init && make app
Install via git clone:
$ git://github.com/visionmedia/express.git && cd express && git submodule update --init
## Performance
@@ -42,41 +44,31 @@ Or with the [gh](http://github.com/visionmedia/gh) utility:
## Examples
Below is a minimal app example when express is already within your load path.
Below is a tiny Express application. View the [Wiki](http://wiki.github.com/visionmedia/express/) for detailed information.
require.paths.unshift('express/lib')
require('express')
require('express/plugins')
configure(function(){
use(MethodOverride)
use(ContentLength)
set('root', __dirname)
get('/user', function(){
this.redirect('/user/' + this.currentUser.id)
})
get('/hello', function(){
this.contentType('html')
return '<h1>World<h1>'
})
get('/user/:id?', function(id) {
get('/user/:id', function(id){
this.render('user.haml.html', {
locals: {
name: id ? 'User ' + id : 'You'
user: this.currentUser,
usersOnline: Session.store.length()
}
})
})
run()
## Running Tests
First we need to ensure all submodules are updated:
$ make init
Express uses the [JSpec](http://jspec.info) BDD JavaScript testing
framework to write and run elegant spec suites. JSpec is frozen
to spec/lib and does not require separate installation.
to spec/lib and **does not** require separate installation.
$ make test
@@ -88,13 +80,12 @@ Run individual suites:
...
Express is currently being developed with node --version:
v0.1.31
v0.1.32
## More Information
* [JavaScript Extensions &amp; Utilities](http://github.com/visionmedia/ext.js)
* [JavaScript Sass](http://github.com/visionmedia/sass.js)
* [Scons Build System](http://www.scons.org/) (some development dependencies rely on this, ex libxmljs)
* Featured in [Advanced JavaScript e-book](http://www.dev-mag.com/2010/02/18/advanced-javascript/) for only $4
## Contributors
+11 -13
Ver Arquivo
@@ -3,23 +3,21 @@ require.paths.unshift('lib')
require('express')
require('express/plugins')
configure(function(){
var fiveMinutes = 300000,
oneMinute = 60000
use(MethodOverride)
use(ContentLength)
use(CommonLogger)
use(Cookie)
use(Cache, { lifetime: fiveMinutes, reapInterval: oneMinute })
use(Session, { lifetime: fiveMinutes, reapInterval: oneMinute })
set('root', __dirname)
})
var messages = [],
utils = require('express/utils')
configure(function(){
use(MethodOverride)
use(ContentLength)
use(Cookie)
use(Cache, { lifetime: (5).minutes, reapInterval: (1).minute })
use(Session, { lifetime: (15).minutes, reapInterval: (1).minute })
use(Logger)
set('root', __dirname)
})
get('/', function(){
this.redirect('/chat')
this.pass('/chat')
})
get('/chat', function(){
+1 -1
Ver Arquivo
@@ -6,10 +6,10 @@ require('express/plugins')
configure(function(){
use(MethodOverride)
use(ContentLength)
use(CommonLogger)
use(Cookie)
use(Session)
use(Flash)
use(Logger)
set('root', __dirname)
})
+2 -4
Ver Arquivo
@@ -1,9 +1,7 @@
require.paths.unshift(__dirname + '/support/js-oo/lib')
require.paths.unshift(__dirname + '/support/ejs/lib')
require.paths.unshift(__dirname + '/support/ext/lib')
require.paths.unshift(__dirname + '/support/haml/lib')
require.paths.unshift(__dirname + '/support/sass/lib')
require.paths.unshift(__dirname + '/support/ext/lib')
require('oo')
require('ext')
require('support/oo/lib/oo')
require('express/core')
+37 -26
Ver Arquivo
@@ -11,7 +11,6 @@ var multipart = require('multipart'),
fs = require('fs')
global.merge(require('sys'))
global.merge(require('express/exceptions'))
global.merge(require('express/event'))
global.merge(require('express/request'))
global.merge(require('express/plugin'))
@@ -68,16 +67,16 @@ Route = Class({
normalize: function(path) {
var self = this
this.params = []
this.keys = []
if (path instanceof RegExp) return path
return new RegExp('^' + RegExp.escape(normalizePath(path), '.')
.replace(/\*/g, '(.+)')
.replace(/(\/|\\\.):(\w+)\?/g, function(_, c, key){
self.params.push(key)
self.keys.push(key)
return '(?:' + c + '([^\/]+))?'
})
.replace(/:(\w+)/g, function(_, key){
self.params.push(key)
self.keys.push(key)
return '([^\/]+)'
}) + '$', 'i')
}
@@ -105,10 +104,19 @@ Router = Class({
* @api private
*/
route: function(){
var route = this.matchingRoute()
if (route)
return route.fn.apply(this.request, this.request.captures.slice(1))
route: function() {
var body,
route = this.matchingRoute()
if (route) {
body = route.fn.apply(this.request, this.request.captures.slice(1));
if (this.request.passed) {
if (typeof this.request.passed === 'string')
this.request.url.pathname = this.request.passed
this.request.passed = false
return this.route()
}
return body
}
else if (this.request.accepts('html') && set('helpful 404'))
this.request.halt(404, require('express/pages/not-found').render(this.request))
else
@@ -122,10 +130,13 @@ Router = Class({
* @api private
*/
matchingRoute: function(){
return Express.routes.find(function(route){
return this.match(route)
}, this)
matchingRoute: function() {
this.lastMatchingRoute = this.lastMatchingRoute || 0
var routes = Express.routes, route
while (route = routes[this.lastMatchingRoute++])
if (this.match(route))
break
return route
},
/**
@@ -154,7 +165,7 @@ Router = Class({
*/
mapParams: function(route) {
route.params.each(function(key, i){
route.keys.each(function(key, i){
this.request.params.path[key] = this.request.captures[++i]
}, this)
}
@@ -264,16 +275,18 @@ Server = Class({
*/
route: function(request, response){
request = new Request(request, response)
request.trigger('request')
if (request.response.finished) return
try {
if (typeof (body = (new Router(request)).route()) == 'string')
request.halt(200, body)
}
catch (e) {
this.error(e, request)
}
var self = this,
request = new Request(request, response)
request.trigger('request', function(e) {
try {
if (e) throw e
if (request.response.finished) return
if (typeof (body = (new Router(request)).route()) === 'string')
request.halt(200, body)
} catch (e) {
self.error(e, request)
}
})
},
/**
@@ -286,8 +299,6 @@ Server = Class({
*/
error: function (e, request, response) {
if (e instanceof ExpressError)
throw e
if (!(request instanceof Request))
request = new Request(request, response),
request.trigger('request')
@@ -303,7 +314,7 @@ Server = Class({
// --- Express
Express = {
version: '0.5.0',
version: '0.7.3',
config: [],
routes: [],
plugins: [],
+1 -9
Ver Arquivo
@@ -1,12 +1,6 @@
// Express - DSL - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Module dependencies.
*/
var http = require('express/http')
/**
* Return a routing function for _method_.
*
@@ -19,9 +13,7 @@ function route(method) {
return function(path, options, fn){
if (options instanceof Function)
fn = options, options = {}
if (path.startsWith('http://'))
return http[method].apply(this, arguments)
else if (!Express.server.running)
if (!Express.server.running)
Express.routes.push(new Route(method, path, fn, options))
else
throw new Error('cannot create route ' + method.toUpperCase() + " `" + path + "' at runtime")
-14
Ver Arquivo
@@ -1,14 +0,0 @@
// Express - Exceptions - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
// --- ExpressError
ExpressError = Class({
name: 'ExpressError',
init: function(message) {
this.message = message
},
toString: function() {
return this.name + ': ' + this.message
}
})
+8 -4
Ver Arquivo
@@ -30,18 +30,22 @@ function request(method, url, data, headers, fn, redirects) {
search = url.search || '',
hash = url.hash || '',
port = url.port || 80,
headers = utils.mixin(headers, { host: url.hostname }),
headers = { host: url.hostname }.merge(headers || {}),
client = http.createClient(port, url.hostname)
if (headers.redirect)
redirects = headers.redirect,
delete headers.redirect
if (data) {
data = queryString.stringify(data)
headers['content-length'] = data.length
headers['content-type'] = 'application/x-www-form-urlencoded'
if (method === 'GET')
search += (search ? '&' : '?') + data
else
headers['content-length'] = data.length,
headers['content-type'] = 'application/x-www-form-urlencoded'
}
var req = client.request(method, path + search + hash, headers)
if (data) req.write(data)
if (data && method !== 'GET') req.write(data)
req.addListener('response', function(res){
if (req.statusCode < 200 || req.statusCode >= 400)
fn(new Error('request failed with status ' + res.statusCode + ' "' + http.STATUS_CODES[res.statusCode] + '"'))
+3 -3
Ver Arquivo
@@ -62,15 +62,15 @@ exports.render = function(request, e) {
</table> \n\
<h3>Params</h3> \n\
<table id="route-params"> \n\
' + hash(request.params) + ' \n\
' + hash(request.params.path) + ' \n\
</table> \n\
<h3>GET</h3> \n\
<table id="get-params"> \n\
' + hash(request.url.params) + ' \n\
' + hash(request.params.get) + ' \n\
</table> \n\
<h3>POST</h3> \n\
<table id="post-params"> \n\
' + hash(request.url.post) + ' \n\
' + hash(request.params.post) + ' \n\
</table> \n\
</div> \n\
</body> \n\
+2 -2
Ver Arquivo
@@ -53,9 +53,9 @@ exports.Plugin = Class({
* @api private
*/
trigger: function(event) {
trigger: function(event, callback) {
if ('on' in this)
if (event.name in this.on)
this.on[event.name].call(this, event)
return this.on[event.name].call(this, event, callback)
}
})
+8 -10
Ver Arquivo
@@ -1,13 +1,11 @@
// Express - Plugins - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
var utils = require('express/utils')
utils.mixin(require('express/plugins/hooks'))
utils.mixin(require('express/plugins/flash'))
utils.mixin(require('express/plugins/cache'))
utils.mixin(require('express/plugins/cookie'))
utils.mixin(require('express/plugins/session'))
utils.mixin(require('express/plugins/profiler'))
utils.mixin(require('express/plugins/common-logger'))
utils.mixin(require('express/plugins/content-length'))
utils.mixin(require('express/plugins/method-override'))
global.merge(require('express/plugins/hooks'))
global.merge(require('express/plugins/flash'))
global.merge(require('express/plugins/cache'))
global.merge(require('express/plugins/cookie'))
global.merge(require('express/plugins/session'))
global.merge(require('express/plugins/logger'))
global.merge(require('express/plugins/content-length'))
global.merge(require('express/plugins/method-override'))
-50
Ver Arquivo
@@ -1,50 +0,0 @@
// Express - CommonLogger - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Months.
*/
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
/**
* Format _date_.
*
* @param {Date} date
* @return {string}
* @api private
*/
function format(date) {
var d = date.getDate(),
m = months[date.getMonth()],
y = date.getFullYear(),
h = date.getHours(),
mi = date.getMinutes(),
s = date.getSeconds()
return (d < 10 ? '0' : '') + d + '/' + m + '/' + y + ' ' +
(h < 10 ? '0' : '') + h + ':' + (mi < 10 ? '0' : '') +
mi + ':' + (s < 10 ? '0' : '') + s
}
// --- CommonLogger
exports.CommonLogger = Plugin.extend({
on: {
/**
* Output log data.
*/
response: function(event) {
puts([event.request.connection.remoteAddress,
'-',
'-',
'[' + format(new Date) + ']',
'"' + event.request.method.toUpperCase() + ' ' + (event.request.url.pathname || '/') +
' HTTP/' + event.request.httpVersion + '"',
event.request.response.status,
event.request.response.headers['content-length'] || 0].join(' '))
}
}
})
+80
Ver Arquivo
@@ -0,0 +1,80 @@
// Express - Logger - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Module dependencies.
*/
var sys = require('sys')
/**
* Log formats
*/
var formats = {
common: function(event, start) {
printf('%s - - [%s] "%s %s HTTP/%d" %s %d %0.3f',
event.request.connection.remoteAddress,
(new Date).format('%d/%b/%Y %H:%M:%S'),
event.request.method.uppercase,
event.request.url.pathname || '/',
event.request.httpVersion,
event.request.response.status,
event.request.response.headers['content-length'] || 0,
(Number(new Date) - start) / 1000)
},
combined: function(event, start) {
formats.common(event, start)
printf('"%s" "%s"',
event.request.headers['referrer'] || event.request.headers['referer'] || '-',
event.request.headers['user-agent'])
},
plot: function(event, start) {
sys.print(Number(new Date) - start)
}
}
// --- Logger
exports.Logger = Plugin.extend({
extend: {
/**
* Initialize logger options.
*
* Options:
*
* - format
* 'common' outputs log in CommonLog format (DEFAULT)
* 'combined' outputs log in Apache Combined format
* 'plot' outputs request duration in milliseconds only
*
* @param {hash} options
* @api private
*/
init: function(options) {
this.merge(options || {})
}
},
on: {
/**
* Start timer.
*/
request: function(event) {
this.start = Number(new Date)
},
/**
* Output log data.
*/
response: function(event) {
formats[exports.Logger.format || 'common'](event, this.start)
sys.print('\n')
}
}
})
-51
Ver Arquivo
@@ -1,51 +0,0 @@
// Express - Profiler - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
var n = 0
exports.Profiler = Plugin.extend({
extend: {
/**
* Initialize profiler options.
*
* Options:
*
* - format 'plot' outputs request duration in milliseconds only
*
* @param {hash} options
* @api private
*/
init: function(options) {
this.merge(options || {})
}
},
// --- Events
on: {
/**
* Start timer.
*/
request: function(event) {
this.start = Number(new Date)
},
/**
* Output duration.
*/
response: function(event) {
if (exports.Profiler.format === 'plot')
puts(Number(new Date) - this.start)
else
puts(event.request.method + ' ' +
event.request.url.pathname + ': ' +
(Number(new Date) - this.start) + ' ms' +
' #' + ++n)
}
}
})
+2 -5
Ver Arquivo
@@ -168,12 +168,9 @@ exports.Session = Plugin.extend({
*/
startReaper: function() {
var self = this,
oneDay = 86400000,
oneHour = 3600000
setInterval(function(){
self.store.reap(self.lifetime || oneDay)
}, self.reapInterval || self.reapEvery || oneHour)
this.store.reap(this.lifetime || (1).day)
}, this.reapInterval || this.reapEvery || (1).hour, this)
}
},
+3 -7
Ver Arquivo
@@ -10,14 +10,10 @@ var utils = require('express/utils'),
fs = require('fs')
/**
* Supported template engines.
* Cache supported template engine exports.
*/
var engine = {
ejs: require('ejs'),
haml: require('haml'),
sass: require('sass')
}
var engines = {}
// --- View
@@ -73,7 +69,7 @@ exports.View = Plugin.extend({
options.context = options.context || this
self.contentType(ext)
function render(content) {
content = engine[type].render(content, options)
content = (engines[type] = engines[type] || require(type)).render(content, options)
if (layout)
self.render(layout + '.' + type + ext, utils.mixin(true, options, {
layout: false,
+54 -40
Ver Arquivo
@@ -12,24 +12,6 @@ var StaticFile = require('express/static').File,
utils = require('express/utils'),
url = require('url')
// --- InvalidStatusCode
InvalidStatusCode = ExpressError.extend({
name: 'InvalidStatusCode',
init: function(status) {
this.message = status + ' is an invalid HTTP response code'
}
})
// --- InvalidResponseBody
InvalidResponseBody = ExpressError.extend({
name: 'InvalidResponseBody',
init: function(request) {
this.message = request.method + ' ' + JSON.encode(request.url.pathname) + ' did not respond with a body string'
}
})
// --- Helpers
/**
@@ -89,9 +71,9 @@ exports.Request = Class({
*/
header: function(key, val) {
return val === undefined ?
this.headers[key.toLowerCase()] :
this.response.headers[key.toLowerCase()] = val
return val === undefined
? this.headers[key.toLowerCase()]
: this.response.headers[key.toLowerCase()] = val
},
/**
@@ -161,9 +143,6 @@ exports.Request = Class({
* default to the default body associated with the response
* _code_.
*
* When an invalid status _code_ is passed, InvalidStatusCode
* will be thrown.
*
* @param {int} code
* @param {string} body
* @param {string} encoding
@@ -171,11 +150,10 @@ exports.Request = Class({
* @api public
*/
halt: function(code, body, encoding) {
halt: function(code, body, encoding, callback) {
this.status(code = code || 404)
if (body = body || statusBodies[code])
return this.respond(body, encoding)
throw new InvalidStatusCode(code)
return this.respond(body, encoding, callback)
},
/**
@@ -187,14 +165,33 @@ exports.Request = Class({
* @api private
*/
respond: function(body, encoding) {
respond: function(body, encoding, callback) {
var self = this
this.response.body = body
this.trigger('response')
if (typeof this.response.body != 'string') throw new InvalidResponseBody(this)
if (typeof this.response.status != 'number') throw new InvalidStatusCode(this.response.status)
this.response.writeHeader(this.response.status, this.response.headers)
this.response.write(this.response.body, encoding)
this.response.close()
this.trigger('response', function(e) {
if (e)
if (callback !== undefined) callback(e)
else throw e
self.response.writeHeader(self.response.status, self.response.headers)
self.response.write(self.response.body, encoding)
self.response.close()
});
},
/**
* Pass control to the next matching route, or
* the given _path_.
*
* NOTE: _path_ may be the request pathname only,
* and may not contain a query string etc.
*
* @param {string} path
* @api public
*/
pass: function(path) {
this.passed = path || true
return this
},
/**
@@ -212,20 +209,37 @@ exports.Request = Class({
},
/**
* Trigger even _name_ with optional _data_.
* Trigger event _name_ with optional _data_ and _callback_ function.
* The _callback_ function may be the second or third argument.
*
* @param {string} name
* @param {hash} data
* @param {object} data
* @param {function} callback
* @return {Request}
* @api public
*/
trigger: function(name, data) {
trigger: function(name, data, callback) {
if (data instanceof Function)
callback = data,
data = null
data = data || {}
data.merge({ request: this, response: this.response })
this.plugins.each(function(plugin){
plugin.trigger(new Event(name, data))
})
var self = this,
complete = 0,
total = this.plugins.length
;(function next(e) {
if (e || complete === total)
callback(e)
else {
try {
if (self.plugins.at(complete++).trigger(new Event(name, data), next) !== true)
next()
} catch(e) {
next(e)
}
}
})()
return this
},
+6 -10
Ver Arquivo
@@ -1,18 +1,13 @@
// Express - Static - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
/**
* Module dependencies.
*/
var path = require('path'),
fs = require('fs')
// --- InvalidPathError
InvalidPathError = ExpressError.extend({
name: 'InvalidPathError',
init: function(path) {
this.message = "`" + path + "' is not a valid path"
}
})
// --- File
exports.File = Class({
@@ -26,7 +21,8 @@ exports.File = Class({
init: function(path) {
this.path = path
if (path.indexOf('..') != -1) throw new InvalidPathError(path)
if (path.indexOf('..') != -1)
Error.raise('InvalidPathError', "`" + path + "' is not a valid path")
},
/**
-53
Ver Arquivo
@@ -1,53 +0,0 @@
/* Ejs template parser for CommonJS
*
* Copyright (c) 2009, Howard Rauscher
* Licensed under the MIT License
*
* base on:
* Simple JavaScript Templating (http://ejohn.org/blog/javascript-micro-templating/)
* John Resig - http://ejohn.org/ - MIT Licensed
*/
(function(){
var cache = {};
var ejs = this.ejs = {};
ejs.parse = function tmpl(str, options) {
options = options || {};
options.context = options.context || {};
options.locals = options.locals || {};
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = cache[str] ||
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[];" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/\-%>(\n|\r)/g, "%>")
.replace(/[\t\b\f]/g, " ")
.replace(/[\n\r]/g, "\f")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'").replace(/\f+/g, '\\n') +
"');}return p.join('');");
cache[str] = fn;
// Provide some basic currying to the user
return fn.call(options.context, options.locals);
};
})();
exports.render = ejs.parse;
Ver Arquivo
+14
Ver Arquivo
@@ -0,0 +1,14 @@
{
"name": "Express",
"description": "Sinatra inspired web development framework",
"version": "0.7.3",
"keywords": ["framework", "sinatra", "web", "rest", "restful"],
"directories": {
"lib": "lib"
},
"scripts": {
"install": "git submodule update --init",
"test": "make test"
},
"engines": { "node": ">= 0.1.30" }
}
+4
Ver Arquivo
@@ -0,0 +1,4 @@
---
name: Express
description: Sinatra inspired web development framework
version: 0.7.3
-1
Ver Arquivo
@@ -25,7 +25,6 @@ specs = {
'plugins',
'plugins.cache',
'plugins.view',
'plugins.common-logger',
'plugins.content-length',
'plugins.method-override',
'plugins.body-decoder',
-23
Ver Arquivo
@@ -1,23 +0,0 @@
describe 'Express'
before_each
reset()
use(require('express/plugins/common-logger').CommonLogger)
end
describe 'CommonLogger'
describe 'on'
describe 'response'
it 'should output in common log format'
GLOBAL.stub('puts')
GLOBAL.should.receive('puts')
get('/style.css', function(){
this.contentType('css')
return 'body { background: #000; }'
})
get('/style.css')
end
end
end
end
end
+28 -13
Ver Arquivo
@@ -107,18 +107,6 @@ describe 'Express'
get('/user').body.should.include('Oh noes!')
end
end
describe 'when given an invalid status code'
it 'should throw an InvalidStatusCode exception'
// TODO: use throw_error when fixed...
get('/user', function(){ this.halt(123123) })
try { get('/user') }
catch (e) {
e.should.be_an_instance_of ExpressError
e.should.be_an_instance_of InvalidStatusCode
}
end
end
end
describe '#contentType()'
@@ -210,6 +198,33 @@ describe 'Express'
})
get('/public/app.js').body.should.eql 'public, app, js'
end
end
end
describe '#pass()'
it 'should pass control to the next matching route'
get('/user', function(){
this.pass()
})
get('/user', function(){
this.pass()
return 'nodejs'
})
get('/user', function(){ return 'success'})
get('/user').body.should.eql 'success'
end
describe 'given a string'
it 'should pass to the given route'
get('/user', function(){
this.pass('/user/1')
})
get('/user/:id', function(){
return 'Supa doopa usa'
})
get('/user').body.should.eql 'Supa doopa usa'
end
end
end
end
end
-13
Ver Arquivo
@@ -84,19 +84,6 @@ describe 'Express'
end
end
describe 'with no response body'
it 'should throw a InvalidResponseBody'
// TODO: use throw_error when fixed...
get('/user', function(){
this.respond()
})
try { get('/user') }
catch (e) {
e.should.be_an_instance_of InvalidResponseBody
}
end
end
describe 'with regular expression'
it 'should match'
get(/^\/user\/(\d+)\/(\w+)/, function(id, operation){
+2 -1
Ver Arquivo
@@ -14,7 +14,8 @@ describe 'Express'
// TODO: use throw_error when fixed...
try { new StaticFile('/../foobar') }
catch (e) {
e.should.be_an_instance_of InvalidPathError
e.name.should.eql 'InvalidPathError'
e.message.should.eql "`/../foobar' is not a valid path"
}
end
end