Express 0.9.0 released
A few minutes ago Express was released, packed with tons of bug fixes and features.
Installation
As always Express can be installed via the Kiwi package manager for NodeJS using one simple command:
$ kiwi install express
Alternatively you can Download a tarball, or install via Git:
$ git clone git://github.com/visionmedia/express.git
$ cd express && git submodule update --init
New Haml Support
I wrote another JavaScript implementation of Haml simply because haml-js was a little clunky and did not comply with the original Haml implementation. My implementation is about 4 times faster (not that it really matters once caching is involved), and more compliant.
“max upload size” setting
We added a simple “max upload size” setting which checks multipart post body Content-Length and raises an error when the specified size is exceeded.
set('max upload size', (5).megabytes)
Request#render() callbacks
The Request#render() method now accepts a trailing callback function, which passes an exception (if a problem occurs), and the final view rendered.
self.render('user.html.haml', function(err, contents){
// perform caching etc
})
Map Route Parameters With param()
The param() DSL-level function allows mapping of parameter names to preprocessor functions. In the example shown below we want to prevent users from typing an invalid path such as /user/rawr, as we need a user id. Our function passed to param() accepts the path segment, which when returning false will be disregarded as a valid route, and the router will continue searching for a matching route. Otherwise if parseInt() succeeds the id variable passed to our route is now a Number and not a String.
param('id', function(val){
val = parseInt(val)
return isNaN(val) ? false : val
})
get('/user/:id', function(id){
return 'User ' + id
})
In the near future I plan on having parameter preprocessing async-friendly, so that for example :user_id could be used to load an User record from the database.
Unified Exception Handling With error()
The error() DSL-level function is passed the exception thrown. Keep in mind
that with async environments like node we loose context if an exception bubbles,
so we pass them to Request#error() to allow for the unified error handler shown below.
error(function(err){
this.contentType('html')
this.halt(200, '<p><strong>Error:</strong> ' + err.message + '</p>')
})
Handling Missing Pages With notFound()
The request level method Request#notFound() is now used in place where you
would normally call halt(404), and supports deferring to the DSL-level function notFound() as shown below:
notFound(function(){
this.halt(404, 'your lame')
})
Changelog
- Added DSL level error() route support
- Added DSL level notFound() route support
- Added Request#error()
- Added Request#notFound()
- Added Request#render() callback function. Closes #258
- Added “max upload size” setting
- Added “magic” variables to collection partials (__index__, __length__, __isFirst__, __isLast__). Closes #254
- Added haml.js submodule; removed haml-js
- Added callback function support to Request#halt() as 3rd/4th arg
- Added preprocessing of route param wildcards using param(). Closes #251
- Added view partial support (with collections etc)
- Fixed bug preventing falsey params (such as ?page=0). Closes #286
- Fixed setting of multiple cookies. Closes #199
- Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
- Changed; session cookie is now httpOnly
- Changed; Request is no longer global
- Changed; Event is no longer global
- Changed; “sys” module is no longer global
- Changed; moved Request#download to Static plugin where it belongs
- Changed; Request instance created before body parsing. Closes #262
- Changed; Pre-caching views in memory when “cache view contents” is enabled. Closes #253
- Changed; Pre-caching view partials in memory when “cache view partials” is enabled
- Updated support to node —version 0.1.90
- Updated dependencies
- Removed set(“session cookie”) in favour of use(Session, { cookie: { … }})
- Removed utils.mixin(); use Object#mergeDeep()