Comparar commits

..

69 Commits

Autor SHA1 Mensagem Data
Tj Holowaychuk 380a6c5363 Release 2.5.2 2011-12-10 11:07:21 -08:00
Tj Holowaychuk c047b64ab5 removed less support since compiler() has gone away 2011-12-10 11:05:49 -08:00
Tj Holowaychuk ae2bcb2615 express(1) LF -> CRLF for windows 2011-12-10 11:05:20 -08:00
Tj Holowaychuk 02cdf0c72b fixed express(1) --version 2011-11-18 08:03:16 -08:00
Tj Holowaychuk a7520ad00c Release 2.5.1 2011-11-17 11:36:13 -08:00
Tj Holowaychuk bf7807619d updated connect to 1.8.x 2011-11-17 11:32:56 -08:00
Tj Holowaychuk b5346005af typo 2011-11-04 08:55:57 -07:00
Tj Holowaychuk 334a8d3fa2 Removed sass.js support from express(1)
sass.js is lame, use stylus
2011-11-04 08:35:10 -07:00
Tj Holowaychuk 7c6c07497a "node": ">= 0.4.1 < 0.7.0" 2011-10-24 16:01:46 -07:00
Tj Holowaychuk 95f6cda9c4 Release 2.5.0 2011-10-24 16:00:46 -07:00
Tj Holowaychuk e2de941d09 Release 0.5.0 2011-10-24 16:00:35 -07:00
Tj Holowaychuk f7d67ce766 Added ./routes dir for generated app by default 2011-10-24 15:58:22 -07:00
Tj Holowaychuk b63f2ca903 Added npm install reminder to express(1) app gen 2011-10-24 15:46:42 -07:00
Tj Holowaychuk 77c2d89be6 fixing tests 2011-10-24 14:59:21 -07:00
Tj Holowaychuk 458097fe7b fixing tests 2011-10-24 14:51:09 -07:00
Tj Holowaychuk 1b25240d36 update expresso/should 2011-10-24 14:47:06 -07:00
Tj Holowaychuk 1cce4d98ff Removed make test-cov since it wont work with node 0.5.x 2011-10-24 14:37:09 -07:00
Tj Holowaychuk 09b5c79073 OCD 2011-10-24 14:36:45 -07:00
Tj Holowaychuk 9348500366 readme 2011-10-24 14:36:30 -07:00
Tj Holowaychuk 0f6a044d98 Fixed express(1) public dir for windows. Closes #866 2011-10-14 08:38:21 -07:00
Tj Holowaychuk 049a557341 remove test stuff 2011-10-07 08:30:31 -07:00
Tj Holowaychuk 94a6f42efd clean up jade example 2011-10-07 08:28:57 -07:00
Tj Holowaychuk a4aed5f51a jade example using template inheritance 2011-10-07 08:25:43 -07:00
Tj Holowaychuk 3e6f45cb72 update jade dev dep 2011-10-07 08:19:11 -07:00
Tj Holowaychuk 3bd4de7f73 bump express(1) version 2011-10-06 12:05:44 -07:00
Tj Holowaychuk 5c04f85f93 Release 2.4.7 2011-10-05 15:41:50 -07:00
Tj Holowaychuk 77f885d4a0 connect 1.7.x to fix npm issue... 2011-10-05 15:34:22 -07:00
Tj Holowaychuk c2fc9a83e8 Added mkdirp to express(1). Closes #795 2011-09-21 08:24:37 -07:00
Tj Holowaychuk d8b20bd2d5 Added simple json-config example
for some who might prefer this. there are benefits to both
2011-09-13 09:00:09 -07:00
Tj Holowaychuk d3c4fd91c9 typo 2011-09-12 10:39:22 -07:00
Tj Holowaychuk 00e44f6fc9 Fixed res.redirect() HEAD support. [reported by xerox] 2011-09-07 10:01:28 -07:00
Tj Holowaychuk 6692f911ab Fixed req.flash(), only escape args 2011-09-06 15:14:09 -07:00
Tj Holowaychuk 4f0b3f4684 Added shorthand for the parsed request's pathname 2011-09-02 16:41:58 -07:00
Tj Holowaychuk cbf330c3db Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie] 2011-08-29 08:40:30 -07:00
Tj Holowaychuk 13010987b0 logger for jade example 2011-08-24 03:14:21 -07:00
Tj Holowaychuk b078481cdb Release 2.5.6 2011-08-22 10:20:04 -07:00
Tj Holowaychuk 3888468a96 Fixed multiple param callback regression. Closes #824 [reported by TroyGoode] 2011-08-22 10:04:46 -07:00
Tj Holowaychuk a6b70ceca4 fixed tests 2011-08-22 09:47:43 -07:00
Tj Holowaychuk 45757a0f1a bump express(1) version 2011-08-20 04:33:51 -07:00
Tj Holowaychuk 24a4a80ccd Release 2.4.5 2011-08-19 10:12:38 -07:00
Tj Holowaychuk 2fdd906a41 docs 2011-08-19 08:53:02 -07:00
Tj Holowaychuk 71cc6bac22 google analytics 2011-08-19 08:51:54 -07:00
Tj Holowaychuk 3a46660932 typo. Closes #815 2011-08-18 09:03:46 -07:00
Tj Holowaychuk adca07a858 Refactored Route to use a single array of callbacks 2011-08-17 15:48:27 -07:00
Tj Holowaychuk 6b924bf1df fixed route error handlers when errors are thrown 2011-08-17 14:39:27 -07:00
Tj Holowaychuk eb88f160b6 Added support for routes to handle errors. Closes #809
currently only the route end-point callbacks
support this, however this will change in the near future
to support route middleware etc
2011-08-17 14:33:11 -07:00
Tj Holowaychuk 01e6df759e Added "basepath" setting to work in conjunction with reverse proxies etc. Closes #805
this will allow you to essentially "trick" the express
app into thinking it is mounted when it is not.
2011-08-17 09:27:28 -07:00
Tj Holowaychuk 1dc4e6fcb4 qs >= 0.3.1 2011-08-17 07:53:16 -07:00
Tj Holowaychuk fff6951d94 use nextRoute() internally 2011-08-16 18:29:57 -07:00
Tj Holowaychuk 1ebd49af75 Changed: removed .call(self) for route callbacks
not sure why we had this, ive never even used it
and the tests dont cover it, and its slower
2011-08-16 18:28:41 -07:00
Tj Holowaychuk 8c2107e337 Added app.routes.all(). Closes #803
not a huge fan of this API-wise, but at least it is something for now
2011-08-16 17:51:20 -07:00
Tj Holowaychuk cddc5442f1 typo 2011-08-15 16:31:11 -07:00
Tj Holowaychuk ac8cb270fe Fixed res.redirect() on windows due to join() usage. Closes #808 2011-08-15 13:46:58 -07:00
Tj Holowaychuk d54ee58f93 Added support for multiple callbacks for app.param(). Closes #801
you can also make several calls to `app.param()` for the same
param name, which is equivalent to passing multiple in
a single call
2011-08-11 11:07:04 -07:00
Tj Holowaychuk ce0fa0a3b2 Added test for multiple app.param() calls for the same param 2011-08-11 10:17:23 -07:00
Tj Holowaychuk e2f41147ed added another test 2011-08-11 10:12:16 -07:00
Tj Holowaychuk af3f7f0a65 Added test for app.param(fn) 2011-08-11 10:11:00 -07:00
Tj Holowaychuk a37003945b docs 2011-08-05 19:35:11 -07:00
Tj Holowaychuk 75361fb177 Release 2.4.4 2011-08-05 04:29:52 -07:00
Tj Holowaychuk 21f9b386db empty string 2011-08-05 04:28:31 -07:00
Tj Holowaychuk 271cb16ecd Fixed res.send(204) (again?) 2011-08-05 04:28:08 -07:00
Tj Holowaychuk 803ec213d7 Fixed res.header() intention of a set, even when undefined 2011-08-03 19:59:40 -07:00
Tj Holowaychuk 9e9042f1eb added header.jade to jade example 2011-08-02 08:59:14 -07:00
Tj Holowaychuk ec4c86f46d fixed * consumption 2011-07-29 09:51:09 -07:00
Arpad Borsos 45f22ec602 specialcase .:format routing to not include a dot in the capture group 2011-07-29 09:43:34 -07:00
Tj Holowaychuk 0e1eb72058 fixed a jade test 2011-07-29 09:32:36 -07:00
Tj Holowaychuk 4690b6cdf2 tweak generated stylus 2011-07-25 11:15:10 -07:00
Tj Holowaychuk 22204a5ce1 Fixed res.send(204) support. Closes #771 2011-07-22 08:34:13 -07:00
Tj Holowaychuk 1ec16c0450 qs >= 0.3.0 2011-07-19 12:08:50 -07:00
246 arquivos alterados com 7137 adições e 7888 exclusões
+1 -5
Ver Arquivo
@@ -1,4 +1,3 @@
coverage.html
.DS_Store
lib-cov
*.seed
@@ -10,9 +9,6 @@ lib-cov
*.swp
*.swo
benchmarks/graphs
testing
testing.js
node_modules/
testing
.coverage_data
cover_html
test.js
-1
Ver Arquivo
@@ -5,4 +5,3 @@ support/
test/
testing.js
.DS_Store
coverage.html
-3
Ver Arquivo
@@ -1,3 +0,0 @@
language: node_js
node_js:
- 0.6
+38 -1
Ver Arquivo
@@ -1,10 +1,47 @@
2.5.2 / 2011-12-10
==================
* Fixed: express(1) LF -> CRLF for windows
2.5.1 / 2011-11-17
==================
* Changed: updated connect to 1.8.x
* Removed sass.js support from express(1)
2.5.0 / 2011-10-24
==================
* Added ./routes dir for generated app by default
* Added npm install reminder to express(1) app gen
* Added 0.5.x support
* Removed `make test-cov` since it wont work with node 0.5.x
* Fixed express(1) public dir for windows. Closes #866
2.4.7 / 2011-10-05
==================
* Added mkdirp to express(1). Closes #795
* Added simple _json-config_ example
* Added shorthand for the parsed request's pathname via `req.path`
* Changed connect dep to 1.7.x to fix npm issue...
* Fixed `res.redirect()` __HEAD__ support. [reported by xerox]
* Fixed `req.flash()`, only escape args
* Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]
2.4.6 / 2011-08-22
==================
* Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]
2.4.5 / 2011-08-19
==================
* Added support for routes to handle errors. Closes #809
* Added `app.routes.all()`. Closes #803
* Added "basepath" setting to work in conjunction with reverse proxies etc. * Refactored `Route` to use a single array of callbacks
* Added "basepath" setting to work in conjunction with reverse proxies etc.
* Refactored `Route` to use a single array of callbacks
* Added support for multiple callbacks for `app.param()`. Closes #801
Closes #805
* Changed: removed .call(self) for route callbacks
+22 -12
Ver Arquivo
@@ -1,19 +1,29 @@
REPORTER = dot
DOCS = $(shell find docs/*.md)
HTMLDOCS = $(DOCS:.md=.html)
TESTS = $(shell find test/*.test.js)
test:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter $(REPORTER)
@NODE_ENV=test ./node_modules/.bin/expresso $(TESTS)
test-acceptance:
@NODE_ENV=test ./node_modules/.bin/mocha \
--reporter spec \
test/acceptance/*.js
docs: $(HTMLDOCS)
@ echo "... generating TOC"
@./support/toc.js docs/guide.html
test-cov: lib-cov
@EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html
%.html: %.md
@echo "... $< -> $@"
@markdown $< \
| cat docs/layout/head.html - docs/layout/foot.html \
> $@
lib-cov:
@jscoverage lib lib-cov
site:
rm -fr /tmp/docs \
&& cp -fr docs /tmp/docs \
&& git checkout gh-pages \
&& cp -fr /tmp/docs/* . \
&& echo "done"
.PHONY: site test test-acceptance
docclean:
rm -f docs/*.{1,html}
.PHONY: site test docs docclean
+67 -100
Ver Arquivo
@@ -1,20 +1,23 @@
![express logo](http://f.cl.ly/items/0V2S1n0K1i3y1c122g04/Screen%20Shot%202012-04-11%20at%209.59.42%20AM.png)
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
```js
var app = express.createServer();
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
```
# Express
Insanely fast (and small) server-side JavaScript web development framework
built on [node](http://nodejs.org) and [Connect](http://github.com/senchalabs/connect).
var app = express.createServer();
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
## Installation
$ npm install express
or to access the `express(1)` executable install globally:
$ npm install -g express
## Quick Start
@@ -28,55 +31,83 @@ app.listen(3000);
Install dependencies:
$ npm install
$ npm install -d
Start the server:
$ node app
$ node app.js
## Features
* Built on [Connect](http://github.com/senchalabs/connect)
* Robust routing
* HTTP helpers (redirection, caching, etc)
* View system supporting 14+ template engines
* Redirection helpers
* Dynamic view helpers
* Content negotiation
* Focus on high performance
* View rendering and partials support
* Environment based configuration
* Executable for generating applications quickly
* Session based flash notifications
* Built on [Connect](http://github.com/senchalabs/connect)
* High test coverage
* Executable for generating applications quickly
* Application level view options
## Philosophy
Via Connect:
The Express philosophy is to provide small, robust tooling for HTTP servers. Making
it a great solution for single page applications, web sites, hybrids, or public
HTTP APIs.
Built on Connect you can use _only_ what you need, and nothing more, applications
can be as big or as small as you like, even a single file. Express does
not force you to use any specific ORM or template engine. With support for over
14 template engines via [Consolidate.js](github.com/visionmedia/consolidate.js) you
can quickly craft your perfect framework.
* Session support
* Cache API
* Mime helpers
* ETag support
* Persistent flash notifications
* Cookie support
* JSON-RPC
* Logging
* and _much_ more!
## Contributors
The following are the major contributors of Express (in no specific order).
* TJ Holowaychuk ([visionmedia](http://github.com/visionmedia))
* Ciaran Jessup ([ciaranj](http://github.com/ciaranj))
* Aaron Heckmann ([aheckmann](http://github.com/aheckmann))
* Guillermo Rauch ([guille](http://github.com/guille))
## More Information
* Join #express on freenode
* [Google Group](http://groups.google.com/group/express-js) for discussion
* #express on freenode
* [express-expose](http://github.com/visionmedia/express-expose) expose objects, functions, modules and more to client-side js with ease
* [express-configure](http://github.com/visionmedia/express-configuration) async configuration support
* [express-messages](http://github.com/visionmedia/express-messages) flash notification rendering helper
* [express-namespace](http://github.com/visionmedia/express-namespace) namespaced route support
* [express-params](https://github.com/visionmedia/express-params) param pre-condition functions
* [express-mongoose](https://github.com/LearnBoost/express-mongoose) plugin for easy rendering of Mongoose async Query results
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
* [Google Group](http://groups.google.com/group/express-js) for discussion
* Visit the [Wiki](http://github.com/visionmedia/express/wiki)
* [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito)
* [Русскоязычная документация](http://express-js.ru/)
* Screencast - [Introduction](http://bit.ly/eRYu0O)
* Screencast - [View Partials](http://bit.ly/dU13Fx)
* Screencast - [Route Specific Middleware](http://bit.ly/hX4IaH)
* Screencast - [Route Path Placeholder Preconditions](http://bit.ly/eNqmVs)
## Node Compatibility
Express 1.x is compatible with node 0.2.x and connect < 1.0.
Express 2.x is compatible with node 0.4.x or 0.6.x, and connect 1.x
Express 3.x (master) will be compatible with node 0.6.x and connect 2.x
## Viewing Examples
First install the dev dependencies to install all the example / test suite deps:
$ cd express
$ npm install -d
$ npm install
then run whichever tests you want:
$ node examples/content-negotiation
$ node examples/jade/app.js
## Running Tests
@@ -88,75 +119,11 @@ then run the tests:
$ make test
## Contributors
```
project: express
commits: 3559
active : 468 days
files : 237
authors:
1891 Tj Holowaychuk 53.1%
1285 visionmedia 36.1%
182 TJ Holowaychuk 5.1%
54 Aaron Heckmann 1.5%
34 csausdev 1.0%
26 ciaranj 0.7%
21 Robert Sköld 0.6%
6 Guillermo Rauch 0.2%
3 Dav Glass 0.1%
3 Nick Poulden 0.1%
2 Randy Merrill 0.1%
2 Benny Wong 0.1%
2 Hunter Loftis 0.1%
2 Jake Gordon 0.1%
2 Brian McKinney 0.1%
2 Roman Shtylman 0.1%
2 Ben Weaver 0.1%
2 Dave Hoover 0.1%
2 Eivind Fjeldstad 0.1%
2 Daniel Shaw 0.1%
1 Matt Colyer 0.0%
1 Pau Ramon 0.0%
1 Pero Pejovic 0.0%
1 Peter Rekdal Sunde 0.0%
1 Raynos 0.0%
1 Teng Siong Ong 0.0%
1 Viktor Kelemen 0.0%
1 ctide 0.0%
1 8bitDesigner 0.0%
1 isaacs 0.0%
1 mgutz 0.0%
1 pikeas 0.0%
1 shuwatto 0.0%
1 tstrimple 0.0%
1 ewoudj 0.0%
1 Adam Sanderson 0.0%
1 Andrii Kostenko 0.0%
1 Andy Hiew 0.0%
1 Arpad Borsos 0.0%
1 Ashwin Purohit 0.0%
1 Benjen 0.0%
1 Darren Torpey 0.0%
1 Greg Ritter 0.0%
1 Gregory Ritter 0.0%
1 James Herdman 0.0%
1 Jim Snodgrass 0.0%
1 Joe McCann 0.0%
1 Jonathan Dumaine 0.0%
1 Jonathan Palardy 0.0%
1 Jonathan Zacsh 0.0%
1 Justin Lilly 0.0%
1 Ken Sato 0.0%
1 Maciej Małecki 0.0%
1 Masahiro Hayashi 0.0%
```
## License
(The MIT License)
Copyright (c) 2009-2012 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Copyright (c) 2009-2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
+163 -135
Ver Arquivo
@@ -4,37 +4,49 @@
* Module dependencies.
*/
var express = require('../')
var fs = require('fs')
, exec = require('child_process').exec
, program = require('commander')
, mkdirp = require('mkdirp')
, os = require('os')
, fs = require('fs');
, mkdirp = require('mkdirp');
// CLI
/**
* Framework version.
*/
program
.version(express.version)
.option('-s, --sessions', 'add session support')
.option('-e, --ejs', 'add ejs engine support (defaults to jade)')
.option('-J, --jshtml', 'add jshtml engine support (defaults to jade)')
.option('-c, --css <engine>', 'add stylesheet <engine> support (less|stylus) (defaults to plain css)')
.option('-f, --force', 'force on non-empty directory')
.parse(process.argv);
var version = '2.5.2';
// Path
/**
* Add session support.
*/
var path = program.args.shift() || '.';
var sessions = false;
// end-of-line code
/**
* CSS engine to utilize.
*/
var eol = 'win32' == os.platform() ? '\r\n' : '\n'
var cssEngine;
// Template engine
/**
* Template engine to utilize.
*/
program.template = 'jade';
if (program.ejs) program.template = 'ejs';
if (program.jshtml) program.template = 'jshtml';
var templateEngine = 'jade';
/**
* Usage documentation.
*/
var usage = ''
+ '\n'
+ ' Usage: express [options] [path]\n'
+ '\n'
+ ' Options:\n'
+ ' -s, --sessions add session support\n'
+ ' -t, --template <engine> add template <engine> support (jade|ejs). default=jade\n'
+ ' -c, --css <engine> add stylesheet <engine> support (stylus). default=plain css\n'
+ ' -v, --version output framework version\n'
+ ' -h, --help output help information\n'
;
/**
* Routes index template.
@@ -47,9 +59,9 @@ var index = [
, ' */'
, ''
, 'exports.index = function(req, res){'
, ' res.render(\'index\', { title: \'Express\' });'
, ' res.render(\'index\', { title: \'Express\' })'
, '};'
].join(eol);
].join('\r\n');
/**
* Jade layout template.
@@ -61,27 +73,23 @@ var jadeLayout = [
, ' head'
, ' title= title'
, ' link(rel=\'stylesheet\', href=\'/stylesheets/style.css\')'
, ' body'
, ' block content'
].join(eol);
, ' body!= body'
].join('\r\n');
/**
* Jade index template.
*/
var jadeIndex = [
'extends layout'
, ''
, 'block content'
, ' h1= title'
, ' p Welcome to #{title}'
].join(eol);
'h1= title'
, 'p Welcome to #{title}'
].join('\r\n');
/**
* EJS index template.
* EJS layout template.
*/
var ejsIndex = [
var ejsLayout = [
'<!DOCTYPE html>'
, '<html>'
, ' <head>'
@@ -89,37 +97,19 @@ var ejsIndex = [
, ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
, ' </head>'
, ' <body>'
, ' <h1><%= title %></h1>'
, ' <p>Welcome to <%= title %></p>'
, ' <%- body %>'
, ' </body>'
, '</html>'
].join(eol);
].join('\r\n');
/**
* JSHTML layout template.
* EJS index template.
*/
var jshtmlLayout = [
'<!DOCTYPE html>'
, '<html>'
, ' <head>'
, ' <title> @write(title) </title>'
, ' <link rel=\'stylesheet\' href=\'/stylesheets/style.css\' />'
, ' </head>'
, ' <body>'
, ' @write(body)'
, ' </body>'
, '</html>'
].join(eol);
/**
* JSHTML index template.
*/
var jshtmlIndex = [
'<h1>@write(title)</h1>'
, '<p>Welcome to @write(title)</p>'
].join(eol);
var ejsIndex = [
'<h1><%= title %></h1>'
, '<p>Welcome to <%= title %></p>'
].join('\r\n');
/**
* Default css template.
@@ -134,22 +124,7 @@ var css = [
, 'a {'
, ' color: #00B7FF;'
, '}'
].join(eol);
/**
* Default less template.
*/
var less = [
'body {'
, ' padding: 50px;'
, ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;'
, '}'
, ''
, 'a {'
, ' color: #00B7FF;'
, '}'
].join(eol);
].join('\r\n');
/**
* Default stylus template.
@@ -161,7 +136,7 @@ var stylus = [
, ' font: 14px "Lucida Grande", Helvetica, Arial, sans-serif'
, 'a'
, ' color: #00B7FF'
].join(eol);
].join('\r\n');
/**
* App template.
@@ -175,41 +150,83 @@ var app = [
, ''
, 'var express = require(\'express\')'
, ' , routes = require(\'./routes\')'
, ' , http = require(\'http\');'
, ''
, 'var app = express();'
, 'var app = module.exports = express.createServer();'
, ''
, '// Configuration'
, ''
, 'app.configure(function(){'
, ' app.set(\'views\', __dirname + \'/views\');'
, ' app.set(\'view engine\', \':TEMPLATE\');'
, ' app.use(express.favicon());'
, ' app.use(express.logger(\'dev\'));{css}'
, ' app.use(express.static(__dirname + \'/public\'));'
, ' app.use(express.bodyParser());'
, ' app.use(express.methodOverride());{sess}'
, ' app.use(express.methodOverride());{sess}{css}'
, ' app.use(app.router);'
, ' app.use(express.static(__dirname + \'/public\'));'
, '});'
, ''
, 'app.configure(\'development\', function(){'
, ' app.use(express.errorHandler());'
, ' app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); '
, '});'
, ''
, 'app.configure(\'production\', function(){'
, ' app.use(express.errorHandler()); '
, '});'
, ''
, '// Routes'
, ''
, 'app.get(\'/\', routes.index);'
, ''
, 'http.createServer(app).listen(3000);'
, 'app.listen(3000);'
, 'console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);'
, ''
, 'console.log("Express server listening on port 3000");'
, ''
].join(eol);
].join('\r\n');
// Parse arguments
var args = process.argv.slice(2)
, path = '.';
while (args.length) {
var arg = args.shift();
switch (arg) {
case '-h':
case '--help':
abort(usage);
break;
case '-v':
case '--version':
abort(version);
break;
case '-s':
case '--session':
case '--sessions':
sessions = true;
break;
case '-c':
case '--css':
args.length
? (cssEngine = args.shift())
: abort('--css requires an argument');
break;
case '-t':
case '--template':
args.length
? (templateEngine = args.shift())
: abort('--template requires an argument');
break;
default:
path = arg;
}
}
// Generate application
(function createApplication(path) {
emptyDirectory(path, function(empty){
if (empty || program.force) {
if (empty) {
createApplicationAt(path);
} else {
program.confirm('destination is not empty, continue? ', function(ok){
confirm('destination is not empty, continue? ', function(ok){
if (ok) {
process.stdin.destroy();
createApplicationAt(path);
@@ -231,11 +248,8 @@ function createApplicationAt(path) {
console.log();
process.on('exit', function(){
console.log();
console.log(' install dependencies:');
console.log(' $ cd %s && npm install', path);
console.log();
console.log(' run the app:');
console.log(' $ node app');
console.log(' dont forget to install dependencies:');
console.log(' $ cd %s && npm install', path);
console.log();
});
@@ -244,10 +258,7 @@ function createApplicationAt(path) {
mkdir(path + '/public/javascripts');
mkdir(path + '/public/images');
mkdir(path + '/public/stylesheets', function(){
switch (program.css) {
case 'less':
write(path + '/public/stylesheets/style.less', less);
break;
switch (cssEngine) {
case 'stylus':
write(path + '/public/stylesheets/style.styl', stylus);
break;
@@ -261,67 +272,49 @@ function createApplicationAt(path) {
});
mkdir(path + '/views', function(){
switch (program.template) {
switch (templateEngine) {
case 'ejs':
write(path + '/views/layout.ejs', ejsLayout);
write(path + '/views/index.ejs', ejsIndex);
break;
case 'jade':
write(path + '/views/layout.jade', jadeLayout);
write(path + '/views/index.jade', jadeIndex);
break;
case 'jshtml':
write(path + '/views/layout.jshtml', jshtmlLayout);
write(path + '/views/index.jshtml', jshtmlIndex);
break;
}
});
// CSS Engine support
switch (program.css) {
case 'less':
app = app.replace('{css}', eol + ' app.use(require(\'less-middleware\')({ src: __dirname + \'/public\' }));');
break;
switch (cssEngine) {
case 'stylus':
app = app.replace('{css}', eol + ' app.use(require(\'stylus\').middleware({ src: __dirname + \'/public\' }));');
app = app.replace('{css}', '\r\n app.use(require(\'stylus\').middleware({ src: __dirname + \'/public\' }));');
break;
default:
app = app.replace('{css}', '');
}
// Session support
app = app.replace('{sess}', program.sessions
? eol + ' app.use(express.cookieParser(\'your secret here\'));' + eol + ' app.use(express.session());'
app = app.replace('{sess}', sessions
? '\r\n app.use(express.cookieParser());\r\n app.use(express.session({ secret: \'your secret here\' }));'
: '');
// Template support
app = app.replace(':TEMPLATE', program.template);
app = app.replace(':TEMPLATE', templateEngine);
// package.json
var pkg = {
name: 'application-name'
, version: '0.0.1'
, private: true
, scripts: { start: 'node app' }
, dependencies: {
express: express.version
}
}
var json = '{\r\n';
json += ' "name": "application-name"\r\n';
json += ' , "version": "0.0.1"\r\n';
json += ' , "private": true\r\n';
json += ' , "dependencies": {\r\n';
json += ' "express": "' + version + '"\r\n';
if (cssEngine) json += ' , "' + cssEngine + '": ">= 0.0.1"\r\n';
if (templateEngine) json += ' , "' + templateEngine + '": ">= 0.0.1"\r\n';
json += ' }\r\n';
json += '}';
if (program.template) pkg.dependencies[program.template] = '*';
// CSS Engine support
switch (program.css) {
case 'less':
pkg.dependencies['less-middleware'] = '*';
break;
default:
if (program.css) {
pkg.dependencies[program.css] = '*';
}
}
write(path + '/package.json', JSON.stringify(pkg, null, 2));
write(path + '/package.json', json);
write(path + '/app.js', app);
});
}
@@ -352,6 +345,41 @@ function write(path, str) {
console.log(' \x1b[36mcreate\x1b[0m : ' + path);
}
/**
* Prompt confirmation with the given `msg`.
*
* @param {String} msg
* @param {Function} fn
*/
function confirm(msg, fn) {
prompt(msg, function(val){
fn(/^ *y(es)?/i.test(val));
});
}
/**
* Prompt input with the given `msg` and callback `fn`.
*
* @param {String} msg
* @param {Function} fn
*/
function prompt(msg, fn) {
// prompt
if (' ' == msg[msg.length - 1]) {
process.stdout.write(msg);
} else {
console.log(msg);
}
// stdin
process.stdin.setEncoding('ascii');
process.stdin.once('data', function(data){
fn(data);
}).resume();
}
/**
* Mkdir -p.
*
-25
Ver Arquivo
@@ -1,25 +0,0 @@
var http = require('http');
var times = 50;
while (times--) {
var req = http.request({
port: 3000
, method: 'POST'
, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
req.on('response', function(res){
console.log(res.statusCode);
});
var n = 500000;
while (n--) {
req.write('foo=bar&bar=baz&');
}
req.write('foo=bar&bar=baz');
req.end();
}
+13
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
+13
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
+13
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
+56 -11
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
@@ -180,8 +193,6 @@
</a>
<div id="wrapper">
<div id="container"><ul id="toc">
</ul><ul id="toc">
<li><a href="#installation">Installation</a></li>
<li><a href="#creating-a server">Creating A Server</a></li>
<li><a href="#creating-an https server">Creating An HTTPS Server</a></li>
@@ -217,6 +228,7 @@
<li><a href="#res.sendfile()">sendfile()</a></li>
<li><a href="#res.download()">download()</a></li>
<li><a href="#res.send()">send()</a></li>
<li><a href="#res.json()">json()</a></li>
<li><a href="#res.redirect()">redirect()</a></li>
<li><a href="#res.cookie()">cookie()</a></li>
<li><a href="#res.clearcookie()">clearCookie()</a></li>
@@ -335,6 +347,13 @@ app.configure('production', function(){
});
</code></pre>
<p>For similar environments you may also pass several env strings:</p>
<pre><code>app.configure('stage', 'prod', function(){
// config
});
</code></pre>
<p>For internal and arbitrary settings Express provides the <em>set(key[, val])</em>, <em>enable(key)</em>, <em>disable(key)</em> methods:</p>
<pre><code> app.configure(function(){
@@ -365,12 +384,14 @@ app.configure('production', function(){
<p>Express supports the following settings out of the box:</p>
<ul>
<li><em>home</em> Application base path used for <em>res.redirect()</em> and transparently handling mounted apps.</li>
<li><em>basepath</em> Application base path used for <em>res.redirect()</em> and transparently handling mounted apps.</li>
<li><em>views</em> Root views directory defaulting to <strong>CWD/views</strong></li>
<li><em>view engine</em> Default view engine name for views rendered without extensions</li>
<li><em>view options</em> An object specifying global view options</li>
<li><em>view cache</em> Enable view caching (enabled in production)</li>
<li><em>case sensitive routes</em> Enable case-sensitive routing</li>
<li><em>strict routing</em> When enabled trailing slashes are no longer ignored</li>
<li><em>jsonp callback</em> Enable <em>res.send()</em> / <em>res.json()</em> transparent jsonp support</li>
</ul>
@@ -532,7 +553,7 @@ var app = express.createServer(
);
</code></pre>
<p>Alternatively we can <em>use()</em> them which is useful when adding middleware within <em>configure()</em> blocks, in a progressive manner.</p>
<p>Alternatively we can <em>use()</em> them which is useful when adding middleware within <em>configure()</em> blocks, in a progressive manor.</p>
<pre><code>app.use(express.logger({ format: ':method :url' }));
</code></pre>
@@ -658,7 +679,7 @@ app.get('/', all, function(){});
<h3 id="http-methods">HTTP Methods</h3>
<p>We have seen <em>app.get()</em> a few times, however Express also exposes other familiar HTTP verbs in the same manner, such as <em>app.post()</em>, <em>app.del()</em>, etc.</p>
<p>We have seen <em>app.get()</em> a few times, however Express also exposes other familiar HTTP verbs in the same manor, such as <em>app.post()</em>, <em>app.del()</em>, etc.</p>
<p> A common example for <em>POST</em> usage, is when &ldquo;submitting&rdquo; a form. Below we simply set our form method to &ldquo;post&rdquo; in our html, and control will be given to the route we have defined below it.</p>
@@ -1268,6 +1289,19 @@ it will not be set again.</p>
<p>Note that this method <em>end()</em>s the response, so you will want to use node&rsquo;s <em>res.write()</em> for multiple writes or streaming.</p>
<h3 id="res.json()">res.json(obj[, headers|status[, status]])</h3>
<p> Send a JSON response with optional <em>headers</em> and <em>status</em>. This method
is ideal for JSON-only APIs, however <em>res.send(obj)</em> will send JSON as
well, though not ideal for cases when you want to send for example a string
as JSON, since the default for <em>res.send(string)</em> is text/html.</p>
<pre><code>res.json(null);
res.json({ user: 'tj' });
res.json('oh noes!', 500);
res.json('I dont have that', 404);
</code></pre>
<h3 id="res.redirect()">res.redirect(url[, status])</h3>
<p>Redirect to the given <em>url</em> with a default response <em>status</em> of 302.</p>
@@ -1281,11 +1315,12 @@ res.redirect('back');
<p>Express supports &ldquo;redirect mapping&rdquo;, which by default provides <em>home</em>, and <em>back</em>.
The <em>back</em> map checks the <em>Referrer</em> and <em>Referer</em> headers, while <em>home</em> utilizes
the &ldquo;home&rdquo; setting and defaults to &ldquo;/&rdquo;.</p>
the &ldquo;basepath&rdquo; setting and defaults to &ldquo;/&rdquo;.</p>
<h3 id="res.cookie()">res.cookie(name, val[, options])</h3>
<p>Sets the given cookie <em>name</em> to <em>val</em>, with options <em>httpOnly</em>, <em>secure</em>, <em>expires</em> etc.</p>
<p>Sets the given cookie <em>name</em> to <em>val</em>, with options <em>httpOnly</em>, <em>secure</em>, <em>expires</em> etc. The <em>path</em> option defaults to the app&rsquo;s &ldquo;basepath&rdquo; setting, which
is typically &ldquo;/&rdquo;.</p>
<pre><code>// "Remember me" for 15 minutes
res.cookie('rememberme', 'yes', { expires: new Date(Date.now() + 900000), httpOnly: true });
@@ -1307,7 +1342,8 @@ app.get('/', function(req, res){
<h3 id="res.clearcookie()">res.clearCookie(name[, options])</h3>
<p>Clear cookie <em>name</em> by setting &ldquo;expires&rdquo; far in the past.</p>
<p>Clear cookie <em>name</em> by setting &ldquo;expires&rdquo; far in the past. Much like
<em>res.cookie()</em> the <em>path</em> option also defaults to the &ldquo;basepath&rdquo; setting.</p>
<pre><code>res.clearCookie('rememberme');
</code></pre>
@@ -1324,6 +1360,16 @@ automatically, however otherwise a response of <em>200</em> and <em>text/html</e
res.render('index', { layout: false, user: user });
</code></pre>
<p>This <em>options</em> object is also considered an &ldquo;options&rdquo; object. For example
when you pass the <em>status</em> local, it&rsquo;s not only available to the view, it
sets the response status to this number. This is also useful if a template
engine accepts specific options, such as <em>debug</em>, or <em>compress</em>. Below
is an example of how one might render an error page, passing the <em>status</em> for
display, as well as it setting <em>res.statusCode</em>.</p>
<pre><code> res.render('error', { status: 500, message: 'Internal Server Error' });
</code></pre>
<h3 id="res.partial()">res.partial(view[, options])</h3>
<p>Render <em>view</em> partial with the given <em>options</em>. This method is always available
@@ -1451,7 +1497,7 @@ partial('movie', movie)
<pre><code> res.local('foo', bar);
res.local('bar', baz);
res.locals({ foo: bar, bar: baz });
res.locals({ foo: bar, bar, baz });
</code></pre>
<h3 id="app.set()">app.set(name[, val])</h3>
@@ -1596,7 +1642,6 @@ as well as the <em>name()</em> function exposed.</p>
<p>Express also provides a few locals by default:</p>
<pre><code>- `settings` the app's settings object
- `filename` the view's filename
- `layout(path)` specify the layout from within a view
</code></pre>
@@ -1804,4 +1849,4 @@ Hello World
</div>
</div>
</body>
</html>
</html>
+122 -64
Ver Arquivo
@@ -104,11 +104,11 @@ This is _very_ important, as many caching mechanisms are _only enabled_ when in
Express supports the following settings out of the box:
* _home_ Application base path used for _res.redirect()_ and transparently handling mounted apps.
* _basepath_ Application base path used for _res.redirect()_ and transparently handling mounted apps.
* _views_ Root views directory defaulting to **CWD/views**
* _view engine_ Default view engine name for views rendered without extensions
* _view options_ An object specifying global view options
* _view cache_ Enable view caching (enabled in production)
* _charset_ Alter the default charset of "utf-8"
* _case sensitive routes_ Enable case-sensitive routing
* _strict routing_ When enabled trailing slashes are no longer ignored
* _jsonp callback_ Enable _res.send()_ / _res.json()_ transparent jsonp support
@@ -245,7 +245,7 @@ The _app.all()_ method is useful for applying the same logic for all HTTP verbs
});
app.get('*', function(req, res){
res.send(404, 'what???');
res.send('what???', 404);
});
app.listen(3000);
@@ -262,7 +262,7 @@ passed to _express.createServer()_ as you would with a regular Connect server. F
, express.bodyParser()
);
Alternatively we can _use()_ them which is useful when adding middleware within _configure()_ blocks, in a progressive manner.
Alternatively we can _use()_ them which is useful when adding middleware within _configure()_ blocks, in a progressive manor.
app.use(express.logger({ format: ':method :url' }));
@@ -379,7 +379,7 @@ There are times when we may want to "skip" passed remaining route middleware, bu
### HTTP Methods
We have seen _app.get()_ a few times, however Express also exposes other familiar HTTP verbs in the same manner, such as _app.post()_, _app.del()_, etc.
We have seen _app.get()_ a few times, however Express also exposes other familiar HTTP verbs in the same manor, such as _app.post()_, _app.del()_, etc.
A common example for _POST_ usage, is when "submitting" a form. Below we simply set our form method to "post" in our html, and control will be given to the route we have defined below it.
@@ -421,16 +421,65 @@ The reason that these are not always defaults, is simply because these are not r
### Error Handling
Error handling middleware are simply middleware with an arity of 4, aka
the signature _(err, req, res, next)_. When you _next(err)_ an error,
only these middleware are executed and have a chance to respond. For example:
app.use(app.bodyParser());
app.use(app.methodOverride());
app.use(app.router);
app.use(function(err, req, res, next){
res.send(500, 'Server error');
Express provides the _app.error()_ method which receives exceptions thrown within a route,
or passed to _next(err)_. Below is an example which serves different pages based on our
ad-hoc _NotFound_ exception:
function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}
NotFound.prototype.__proto__ = Error.prototype;
app.get('/404', function(req, res){
throw new NotFound;
});
app.get('/500', function(req, res){
throw new Error('keyboard cat!');
});
We can call _app.error()_ several times as shown below.
Here we check for an instanceof _NotFound_ and show the
404 page, or we pass on to the next error handler.
Note that these handlers can be defined anywhere, as they
will be placed below the route handlers on _listen()_. This
allows for definition within _configure()_ blocks so we can
handle exceptions in different ways based on the environment.
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
});
Here we assume all errors as 500 for the simplicity of
this demo, however you can choose whatever you like. For example when node performs filesystem syscalls, you may receive an error object with the _error.code_ of _ENOENT_, meaning "no such file or directory", we can utilize this in our error handling and display a page specific to this if desired.
app.error(function(err, req, res){
res.render('500.jade', {
error: err
});
});
Our apps could also utilize the Connect _errorHandler_ middleware
to report on exceptions. For example if we wish to output exceptions
in "development" mode to _stderr_ we can use:
app.use(express.errorHandler({ dumpExceptions: true }));
Also during development we may want fancy html pages to show exceptions
that are passed or thrown, so we can set _showStack_ to true:
app.use(express.errorHandler({ showStack: true, dumpExceptions: true }));
The _errorHandler_ middleware also responds with _json_ if _Accept: application/json_
is present, which is useful for developing apps that rely heavily on client-side JavaScript.
### Route Param Pre-conditions
@@ -493,11 +542,13 @@ mix and match template engines:
res.render('another-page.ejs');
To apply application-level locals, or view engine options may be set using _app.local()_ or _app.locals()_, for example if we don't want layouts for most of our templates we may do:
Express also provides the _view options_ setting, which is applied each time a view is rendered, so for example if you rarely use layouts you may set:
app.local('layout', false);
app.set('view options', {
layout: false
});
Which can then be overridden within the _res.render()_ call if desired, and is otherwise functionally equivalent to passing directly to `res.render()`:
Which can then be overridden within the _res.render()_ call if need be:
res.render('myview.ejs', { layout: true });
@@ -513,6 +564,13 @@ These paths may also be absolute:
res.render('page', { layout: __dirname + '/../../mylayout.jade' });
A good example of this is specifying custom _ejs_ opening and closing tags:
app.set('view options', {
open: '{{',
close: '}}'
});
### View Partials
The Express view system has built-in support for partials and collections, which are "mini" views representing a document fragment. For example rather than iterating
@@ -589,7 +647,7 @@ Now the _req.session_ and _req.sessionStore_ properties will be accessible to al
// we could check req.session.items && req.session.items.length
// to print out a message
if (req.session.items && req.session.items.length) {
req.notify('info', 'You have %s items in your cart', req.session.items.length);
req.flash('info', 'You have %s items in your cart', req.session.items.length);
}
res.render('shopping-cart');
});
@@ -714,29 +772,27 @@ the _express.bodyParser middleware.
req.get('Content-Type', 'boundary');
// => "--foo-bar-baz"
### req.notify(type[, msg])
### req.flash(type[, msg])
Queue flash _msg_ of the given _type_.
req.notify('info', 'email sent');
req.notify('error', 'email delivery failed');
req.notify('info', 'email re-sent');
req.flash('info', 'email sent');
req.flash('error', 'email delivery failed');
req.flash('info', 'email re-sent');
// => 2
req.notify('info');
req.flash('info');
// => ['email sent', 'email re-sent']
req.notify('info');
req.flash('info');
// => []
req.notify();
req.flash();
// => { error: ['email delivery failed'], info: [] }
Flash notification message may also utilize formatters, by default only the %s string and %d integer formatters is available:
Flash notification message may also utilize formatters, by default only the %s string formatter is available:
req.notify('info', 'email delivery to <em>%s</em> from <em>%s</em> failed.', toUser, fromUser);
Argument HTML is escaped, to prevent XSS, however HTML notification format is valid.
req.flash('info', 'email delivery to _%s_ from _%s_ failed.', toUser, fromUser);
### req.isXMLHttpRequest
@@ -799,21 +855,6 @@ Sets the _Content-Disposition_ response header to "attachment", with optional _f
res.attachment('path/to/my/image.png');
### res.status(code)
Sets the `res.statusCode` property to `code` and returns for chaining:
res.status(500).send('Something bad happened');
is equivalent to:
res.statusCode = 500;
res.send('Something bad happened');
and:
res.send(500, 'Something bad happened');
### res.sendfile(path[, options[, callback]])
Used by `res.download()` to transfer an arbitrary file.
@@ -863,31 +904,36 @@ An optional second callback, _callback2_ may be given to allow you to act on con
// connection related error
});
### res.send(body|status[, body])
### res.send(body|status[, headers|status[, status]])
The _res.send()_ method is a high level response utility allowing you to pass
objects to respond with json, strings for html, Buffer instances, or numbers representing the status code. The following are all valid uses:
res.send(); // 204
res.send(new Buffer('wahoo'));
res.send({ some: 'json' });
res.send(201, { message: 'User created' });
res.send('<p>some html</p>');
res.send(404, 'Sorry, cant find that');
res.send(404); // "Not Found"
res.send(500); // "Internal Server Error"
res.send('Sorry, cant find that', 404);
res.send('text', { 'Content-Type': 'text/plain' }, 201);
res.send(404);
The _Content-Type_ response header is defaulted appropriately unless previously defined via `res.header()` / `res.contentType()` etc.
By default the _Content-Type_ response header is set, however if explicitly
assigned through `res.send()` or previously with `res.header()` or `res.contentType()`
it will not be set again.
Note that this method _end()_s the response, so you will want to use node's _res.write()_ for multiple writes or streaming.
### res.json(obj|status[, obj])
### res.json(obj[, headers|status[, status]])
Send an explicit JSON response. This method is ideal for JSON-only APIs, while it is much like _res.send(obj)_, send is not ideal for cases when you want to send for example a single string as JSON, since the default for _res.send(string)_ is text/html.
Send a JSON response with optional _headers_ and _status_. This method
is ideal for JSON-only APIs, however _res.send(obj)_ will send JSON as
well, though not ideal for cases when you want to send for example a string
as JSON, since the default for _res.send(string)_ is text/html.
res.json(null);
res.json({ user: 'tj' });
res.json(500, 'oh noes!');
res.json(404, 'I dont have that');
res.json('oh noes!', 500);
res.json('I dont have that', 404);
### res.redirect(url[, status])
@@ -901,11 +947,11 @@ Redirect to the given _url_ with a default response _status_ of 302.
Express supports "redirect mapping", which by default provides _home_, and _back_.
The _back_ map checks the _Referrer_ and _Referer_ headers, while _home_ utilizes
the "home" setting and defaults to "/".
the "basepath" setting and defaults to "/".
### res.cookie(name, val[, options])
Sets the given cookie _name_ to _val_, with options _httpOnly_, _secure_, _expires_ etc. The _path_ option defaults to the app's "home" setting, which
Sets the given cookie _name_ to _val_, with options _httpOnly_, _secure_, _expires_ etc. The _path_ option defaults to the app's "basepath" setting, which
is typically "/".
// "Remember me" for 15 minutes
@@ -926,7 +972,7 @@ To parse incoming _Cookie_ headers, use the _cookieParser_ middleware, which pro
### res.clearCookie(name[, options])
Clear cookie _name_ by setting "expires" far in the past. Much like
_res.cookie()_ the _path_ option also defaults to the "home" setting.
_res.cookie()_ the _path_ option also defaults to the "basepath" setting.
res.clearCookie('rememberme');
@@ -1163,11 +1209,21 @@ When mounted, _res.redirect()_ will respect the mount-point. For example if a bl
res.redirect('/posts');
### app.locals(obj)
### app.error(function)
Registers static view locals.
Adds an error handler _function_ which will receive the exception as the first parameter as shown below.
Note that we may set several error handlers by making several calls to this method, however the handler
should call _next(err)_ if it does not wish to deal with the exception:
app.locals({
app.error(function(err, req, res, next){
res.send(err.message, 500);
});
### app.helpers(obj)
Registers static view helpers.
app.helpers({
name: function(first, last){ return first + ', ' + last }
, firstName: 'tj'
, lastName: 'holowaychuk'
@@ -1183,14 +1239,16 @@ Express also provides a few locals by default:
- `settings` the app's settings object
- `layout(path)` specify the layout from within a view
### app.dynamicLocals(obj)
This method is aliased as _app.locals()_.
Registers dynamic view locals. Dynamic locals
### app.dynamicHelpers(obj)
Registers dynamic view helpers. Dynamic view helpers
are simply functions which accept _req_, _res_, and are
evaluated against the _Server_ instance before a view is rendered, and are unique to that specific request. The _return value_ of this function
evaluated against the _Server_ instance before a view is rendered. The _return value_ of this function
becomes the local variable it is associated with.
app.dynamicLocals({
app.dynamicHelpers({
session: function(req, res){
return req.session;
}
+14 -5
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
@@ -233,7 +246,7 @@ app.listen(3000);
<h2>Third-Party Modules</h2>
<p>The following modules compliment or extend Express directly:</p>
<p>The following modules complement or extend Express directly:</p>
<ul>
<li><a href="http://github.com/visionmedia/express-resource">express-resource</a> provides resourceful routing</li>
@@ -254,10 +267,6 @@ app.listen(3000);
<li><a href="http://groups.google.com/group/express-js">Google Group</a> for discussion</li>
<li>Visit the <a href="http://github.com/visionmedia/express/wiki">Wiki</a></li>
<li><a href="http://hideyukisaito.com/doc/expressjs/">日本語ドキュメンテーション</a> by <a href="https://github.com/hideyukisaito">hideyukisaito</a></li>
<li>Screencast &ndash; <a href="http://bit.ly/eRYu0O">Introduction</a></li>
<li>Screencast &ndash; <a href="http://bit.ly/dU13Fx">View Partials</a></li>
<li>Screencast &ndash; <a href="http://bit.ly/hX4IaH">Route Specific Middleware</a></li>
<li>Screencast &ndash; <a href="http://bit.ly/eNqmVs">Route Path Placeholder Preconditions</a></li>
</ul>
</div>
+1 -2
Ver Arquivo
@@ -34,7 +34,7 @@ The following are the major contributors of Express (in no specific order).
## Third-Party Modules
The following modules compliment or extend Express directly:
The following modules complement or extend Express directly:
* [express-resource](http://github.com/visionmedia/express-resource) provides resourceful routing
* [express-messages](http://github.com/visionmedia/express-messages) flash message notification rendering
@@ -51,4 +51,3 @@ The following modules compliment or extend Express directly:
* [Google Group](http://groups.google.com/group/express-js) for discussion
* Visit the [Wiki](http://github.com/visionmedia/express/wiki)
* [日本語ドキュメンテーション](http://hideyukisaito.com/doc/expressjs/) by [hideyukisaito](https://github.com/hideyukisaito)
* [Русскоязычная документация](http://express-js.ru/)
+13
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
+13
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
+13
Ver Arquivo
@@ -3,6 +3,19 @@
<title>Express - node web framework</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<style>
#tagline {
margin-left: 75px;
+35 -34
Ver Arquivo
@@ -6,49 +6,47 @@
var express = require('../../lib/express')
, crypto = require('crypto');
var app = module.exports = express();
var app = express.createServer(
express.bodyParser()
, express.cookieParser()
, express.session({ secret: 'keyboard cat' })
);
app.use(express.bodyParser());
app.use(express.cookieParser('shhhh, very secret'));
app.use(express.session());
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
// Session-persisted message middleware
// Message helper, ideally we would use req.flash()
// however this is more light-weight for an example
app.locals.use(function(req,res){
var err = req.session.error
, msg = req.session.success;
delete req.session.error;
delete req.session.success;
res.locals.message = '';
if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
})
app.dynamicHelpers({
message: function(req){
var err = req.session.error
, msg = req.session.success;
delete req.session.error;
delete req.session.success;
if (err) return '<p class="msg error">' + err + '</p>';
if (msg) return '<p class="msg success">' + msg + '</p>';
}
});
// Generate a salt for the user to prevent rainbow table attacks
// for better security take a look at the bcrypt c++ addon:
// https://github.com/ncb000gt/node.bcrypt.js
var users = {
tj: {
name: 'tj'
name: 'tj'
, salt: 'randomly-generated-salt'
, pass: hash('foobar', 'randomly-generated-salt')
}
};
// Used to generate a hash of the plain-text password + salt
function hash(msg, key) {
return crypto
.createHmac('sha256', key)
.update(msg)
.digest('hex');
}
function hash(msg, key) {
return crypto.createHmac('sha256', key).update(msg).digest('hex');
}
// Authenticate using our plain-object database of doom!
function authenticate(name, pass, fn) {
console.log('authenticating %s:%s', name, pass);
var user = users[name];
// query the db for the given username
if (!user) return fn(new Error('cannot find user'));
@@ -69,11 +67,16 @@ function restrict(req, res, next) {
}
}
function accessLogger(req, res, next) {
console.log('/restricted accessed by %s', req.session.user.name);
next();
}
app.get('/', function(req, res){
res.redirect('login');
res.redirect('/login');
});
app.get('/restricted', restrict, function(req, res){
app.get('/restricted', restrict, accessLogger, function(req, res){
res.send('Wahoo! restricted area');
});
@@ -81,7 +84,7 @@ app.get('/logout', function(req, res){
// destroy the user's session to log them out
// will be re-created next request
req.session.destroy(function(){
res.redirect('/');
res.redirect('home');
});
});
@@ -110,12 +113,10 @@ app.post('/login', function(req, res){
req.session.error = 'Authentication failed, please check your '
+ ' username and password.'
+ ' (use "tj" and "foobar")';
res.redirect('login');
res.redirect('back');
}
});
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express started on port 3000');
+1 -1
Ver Arquivo
@@ -1,6 +1,6 @@
<h1>Login</h1>
<%- message %>
Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj" and "foobar".
Try accessing <a href="/restricted">/restricted</a>.
<form method="post" action="/login">
<p>
<label>Username:</label>
+58
Ver Arquivo
@@ -0,0 +1,58 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, messages = require('express-messages');
var app = module.exports = express.createServer();
// Config
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
// mount hook
app.mounted(function(other){
console.log('ive been mounted!');
});
// Flash message helper provided by express-messages
// $ npm install express-messages
app.dynamicHelpers({
messages: messages
, base: function(){
// return the app's mount-point
// so that urls can adjust. For example
// if you run this example /post/add works
// however if you run the mounting example
// it adjusts to /blog/post/add
return '/' == app.route ? '' : app.route;
}
});
// Middleware
app.configure(function(){
app.use(express.logger('\x1b[33m:method\x1b[0m \x1b[32m:url\x1b[0m :response-time'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ secret: 'keyboard cat' }));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
// Routes
require('./routes/site')(app);
require('./routes/post')(app);
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
-50
Ver Arquivo
@@ -1,50 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../')
, app = module.exports = express();
// config
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
// middleware
app.configure('development',function(){
app.use(express.logger('dev'));
})
app.configure(function(){
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('keyboard cat'));
app.use(express.session());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
// Locals
app.locals.use(function(req, res){
// expose "error" and "message" to all
// views that are rendered.
res.locals.error = req.session.error || '';
res.locals.message = req.session.message || '';
// remove them so they're not displayed on subsequent renders
delete req.session.error;
delete req.session.message;
});
// Routes
require('./routes/site')(app);
require('./routes/post')(app);
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
+3 -3
Ver Arquivo
@@ -17,11 +17,11 @@ Post.prototype.save = function(fn){
};
Post.prototype.validate = function(fn){
if (!this.title) return fn(new Error('title required'));
if (!this.body) return fn(new Error('body required'));
if (!this.title) return fn(new Error('_title_ required'));
if (!this.body) return fn(new Error('_body_ required'));
if (this.body.length < 10) {
return fn(new Error(
'body should be at least 10 characters long, was only ' + this.title.length));
'_body_ should be at least **10** characters long, was only _' + this.title.length + '_'));
}
fn();
};
+8 -6
Ver Arquivo
@@ -41,16 +41,18 @@ a.edit {
.date {
font-size: 11px;
}
p.error,
p.message {
#messages ul {
padding: 10px;
border: 1px solid;
}
p.error {
background: #FDEAE7;
color: #E4250C;
#messages ul li {
list-style: none;
}
p.message {
#messages ul.info {
color: #2EBBE6;
background: #F7FBFD;
}
#messages ul.error {
color: #E4250C;
background: #FDEAE7;
}
+6 -7
Ver Arquivo
@@ -42,17 +42,17 @@ module.exports = function(app){
*/
app.post('/post', function(req, res){
var data = req.body.post || {}
var data = req.body.post
, post = new Post(data.title, data.body);
post.validate(function(err){
if (err) {
req.session.error = err.message;
req.flash('error', err.message);
return res.redirect('back');
}
post.save(function(err){
req.session.message = 'Successfully created the post.';
req.flash('info', 'Successfully created post _%s_', post.title);
res.redirect('/post/' + post.id);
});
});
@@ -82,13 +82,12 @@ module.exports = function(app){
var post = req.post;
post.validate(function(err){
if (err) {
req.session.error = err.message;
req.flash('error', err.message);
return res.redirect('back');
}
post.update(req.body.post, function(err){
if (err) return next(err);
req.session.message = 'Successfully updated post';
req.flash('info', 'Successfully updated post');
res.redirect('back');
});
});
+17 -20
Ver Arquivo
@@ -1,22 +1,19 @@
extends layout
h1 Blog
block content
h1 Blog
!= messages()
if count
p Display all #{count} post(s)
#posts
each post in posts
include post/index
else
p
| It looks like you have no posts!
p
| Click
a(href='/post/add') here
| to create a post. Login
| as
em "admin"
| and
em "express"
| .
- if (count)
p Display all #{count} post(s)
#posts!= partial('post', posts)
- else
p
| It looks like you have no posts!
p
| Click
a(href=base + '/post/add') here
| to create a post. Login
| as
em "admin"
| and
em "express"
| .
+2 -3
Ver Arquivo
@@ -2,7 +2,6 @@
html
head
title Blog
link(rel='stylesheet', href='/style.css')
link(rel='stylesheet', href=base + '/style.css')
body
#container
block content
#container!= body
-6
Ver Arquivo
@@ -1,6 +0,0 @@
if error
p.error= error
if message
p.message= message
+17 -19
Ver Arquivo
@@ -1,22 +1,20 @@
extends ../layout
block content
if post.title
h1 Editing #{post.title}
else
h1 New Post
- if (post.title)
h1 Editing #{post.title}
- else
h1 New Post
include ../messages
!= messages()
form#post(action='/post' + (post.title ? '/' + post.id : ''), method='post')
if post.title
input(type='hidden', name='_method', value='put')
p
label(for='post[title]') Title:
input(type='text', name='post[title]', value=post.title)
p
label(for='post[body]') Body:
textarea(name='post[body]')= post.body || ''
p
input(type='submit', value=post.title ? 'Update' : 'Create')
form#post(action=base + '/post' + (post.title ? '/' + post.id : ''), method='post')
- if (post.title)
input(type='hidden', name='_method', value='put')
p
label(for='post[title]') Title:
input(type='text', name='post[title]', value=post.title)
p
label(for='post[body]') Body:
textarea(name='post[body]')= post.body || ''
p
input(type='submit', value=post.title ? 'Update' : 'Create')
+16 -18
Ver Arquivo
@@ -1,18 +1,16 @@
extends ../layout
block content
.post
// title
h2
= post.title
a.edit(href='/post/' + post.id + '/edit') Edit
include ../messages
// dates
p.date.created Created at #{post.createdAt}
if post.updatedAt
p.date.updated Updated at #{post.updatedAt}
// body
pre.body= post.body
.post
// title
h2
= post.title
a.edit(href=base + '/post/' + post.id + '/edit') Edit
// flash messages
!= messages()
// dates
p.date.created Created at #{post.createdAt}
- if (post.updatedAt)
p.date.updated Updated at #{post.updatedAt}
// body
pre.body= post.body
+47
Ver Arquivo
@@ -0,0 +1,47 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express');
var app = express.createServer();
var users = [
{ name: 'tobi' }
, { name: 'loki' }
, { name: 'jane' }
];
function provides(type) {
return function(req, res, next){
if (req.accepts(type)) return next();
next('route');
}
}
// curl http://localhost:3000/users -H "Accept: application/json"
app.get('/users', provides('json'), function(req, res){
res.send(users);
});
// curl http://localhost:3000/users -H "Accept: text/html"
app.get('/users', provides('html'), function(req, res){
res.send('<ul>' + users.map(function(user){
return '<li>' + user.name + '</li>';
}).join('\n') + '</ul>');
});
// curl http://localhost:3000/users -H "Accept: text/plain"
app.get('/users', function(req, res, next){
res.contentType('txt');
res.send(users.map(function(user){
return user.name;
}).join(', '));
});
app.listen(3000);
console.log('Express server listening on port 3000');
-34
Ver Arquivo
@@ -1,34 +0,0 @@
var express = require('../../')
, app = module.exports = express();
var users = [];
users.push({ name: 'Tobi' });
users.push({ name: 'Loki' });
users.push({ name: 'Jane' });
app.get('/', function(req, res){
res.format({
html: function(){
res.send('<ul>' + users.map(function(user){
return '<li>' + user.name + '</li>';
}).join('') + '</ul>');
},
text: function(){
res.send(users.map(function(user){
return ' - ' + user.name + '\n';
}).join(''));
},
json: function(){
res.json(users);
}
})
});
if (!module.parent) {
app.listen(3000);
console.log('listening on port 3000');
}
-29
Ver Arquivo
@@ -1,29 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../');
var app = module.exports = express();
// pass a secret to cookieParser() for signed cookies
app.use(express.cookieParser('manny is cool'));
// add req.session cookie support
app.use(express.cookieSessions());
// do something with the session
app.use(count);
// custom middleware
function count(req, res) {
req.session.count = req.session.count || 0;
var n = req.session.count++;
res.send('viewed ' + n + ' times\n');
}
if (!module.parent) {
app.listen(3000);
console.log('Express server listening on port 3000');
}
+14 -23
Ver Arquivo
@@ -3,29 +3,22 @@
* Module dependencies.
*/
var express = require('../../')
, app = module.exports = express();
var express = require('../../lib/express');
var app = express.createServer(
// Place default Connect favicon above logger so it is not in
// the logging output
express.favicon(),
// add favicon() before logger() so
// GET /favicon.ico requests are not
// logged, because this middleware
// reponds to /favicon.ico and does not
// call next()
app.use(express.favicon());
// Custom logger format
express.logger({ format: '\x1b[36m:method\x1b[0m \x1b[90m:url\x1b[0m :response-time' }),
// custom log format
if ('test' != process.env.NODE_ENV)
app.use(express.logger(':method :url'));
// Provides req.cookies
express.cookieParser(),
// parses request cookies, populating
// req.cookies and req.signedCookies
// when the secret is passed, used
// for signing the cookies.
app.use(express.cookieParser('my secret here'));
// parses json, x-www-form-urlencoded, and multipart/form-data
app.use(express.bodyParser());
// Parses x-www-form-urlencoded request bodies (and json)
express.bodyParser()
);
app.get('/', function(req, res){
if (req.cookies.remember) {
@@ -48,7 +41,5 @@ app.post('/', function(req, res){
res.redirect('back');
});
if (!module.parent){
app.listen(3000);
console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express started on port 3000');
+24 -17
Ver Arquivo
@@ -3,8 +3,9 @@
* Module dependencies.
*/
var express = require('../../')
, app = module.exports = express();
var express = require('../../lib/express');
var app = express.createServer();
app.get('/', function(req, res){
res.send('<ul>'
@@ -18,27 +19,33 @@ app.get('/', function(req, res){
app.get('/files/:file(*)', function(req, res, next){
var file = req.params.file
, path = __dirname + '/files/' + file;
// either res.download(path) and let
// express handle failures, or provide
// a callback as shown below
res.download(path, function(err){
// if an error occurs in this callback
// the file most likely does not exist,
// and it's safe to respond or next(err)
if (err) return next(err);
res.download(path);
// the file has been transferred, do not respond
// from here, though you may use this callback
// for stats etc.
console.log('transferred %s', path);
}, function(err){
// this second optional callback is used when
// an error occurs during transmission
});
});
// error handling middleware. Because it's
// below our routes, you will be able to
// "intercept" errors, otherwise Connect
// will respond with 500 "Internal Server Error".
app.use(function(err, req, res, next){
// special-case 404s,
// remember you could
// render a 404 template here
if (404 == err.status) {
res.statusCode = 404;
app.error(function(err, req, res, next){
if ('ENOENT' == err.code) {
res.send('Cant find that file, sorry!');
} else {
// Not a 404
next(err);
}
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express started on port 3000');
+31
Ver Arquivo
@@ -0,0 +1,31 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express');
var app = express.createServer();
// Register ejs as .html
app.register('.html', require('ejs'));
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
// Dummy users
var users = [
{ name: 'tj', email: 'tj@sencha.com' }
, { name: 'ciaran', email: 'ciaranj@gmail.com' }
, { name: 'aaron', email: 'aaron.heckmann+github@gmail.com' }
];
app.get('/', function(req, res){
res.render('users', { users: users });
});
app.listen(3000);
console.log('Express app started on port 3000');
-46
Ver Arquivo
@@ -1,46 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../');
var app = module.exports = express();
// Register ejs as .html. If we did
// not call this, we would need to
// name our views foo.ejs instead
// of foo.html. The __express method
// is simply a function that engines
// use to hook into the Express view
// system by default, so if we want
// to change "foo.ejs" to "foo.html"
// we simply pass _any_ function, in this
// case `ejs.__express`.
app.engine('.html', require('ejs').__express);
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
// Without this you would need to
// supply the extension to res.render()
// ex: res.render('users.html').
app.set('view engine', 'html');
// Dummy users
var users = [
{ name: 'tobi', email: 'tobi@learnboost.com' }
, { name: 'loki', email: 'loki@learnboost.com' }
, { name: 'jane', email: 'jane@learnboost.com' }
];
app.get('/', function(req, res){
res.render('users', { users: users });
});
if (!module.parent) {
app.listen(3000);
console.log('Express app started on port 3000');
}
+6
Ver Arquivo
@@ -0,0 +1,6 @@
<html>
<body>
<h1>Users</h1>
<%- body %>
</body>
</html>
-6
Ver Arquivo
@@ -1,6 +0,0 @@
<h1>Users</h1>
<ul id="users">
<% users.forEach(function(user){ %>
<li><%= user.name %> <%= user.email %></li>
<% }) %>
</ul>
+3
Ver Arquivo
@@ -0,0 +1,3 @@
<ul id="users">
<%- partial('user', users) %>
</ul>
+1
Ver Arquivo
@@ -0,0 +1 @@
<li><%= user.name %> &lt;<%= user.email %>&gt;</li>
+22 -34
Ver Arquivo
@@ -1,25 +1,27 @@
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');
/**
* Module dependencies.
*/
var express = require('../../')
, app = module.exports = express()
, silent = 'test' == process.env.NODE_ENV;
var express = require('../../lib/express');
var app = express.createServer();
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
// Serve default connect favicon
app.use(express.favicon());
silent || app.use(express.logger('dev'));
// Logger is placed below favicon, so favicon.ico
// requests will not be logged
app.use(express.logger('":method :url" :status'));
// "app.router" positions our routes
// above the middleware defined below,
// this means that Express will attempt
// to match & call routes _before_ continuing
// on, at which point we assume it's a 404 because
// no route has handled the request.
// specifically above the middleware
// assigned below
app.use(app.router);
@@ -27,26 +29,11 @@ app.use(app.router);
// middleware use()d, we assume 404, as nothing else
// responded.
// $ curl http://localhost:3000/notfound
// $ curl http://localhost:3000/notfound -H "Accept: application/json"
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"
app.use(function(req, res, next){
// respond with html page
if (req.accepts('html')) {
res.status(404);
res.render('404', { url: req.url });
return;
}
// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}
// default to plain-text. send()
res.type('txt').send('Not found');
// the status option, or res.statusCode = 404
// are equivalent, however with the option we
// get the "status" local available as well
res.render('404', { status: 404, url: req.url });
});
// error-handling middleware, take the same form
@@ -61,12 +48,15 @@ app.use(function(req, res, next){
// would remain being executed, however here
// we simply respond with an error page.
app.use(function(err, req, res, next){
// we may use properties of the error object
// here and next(err) appropriately, or if
// we possibly recovered from the error, simply next().
res.status(err.status || 500);
res.render('500', { error: err });
res.render('500', {
status: err.status || 500
, error: err
});
});
// Routes
@@ -89,7 +79,5 @@ app.get('/500', function(req, res, next){
next(new Error('keyboard cat!'));
});
if (!module.parent) {
app.listen(3000);
silent || console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express app started on port 3000');
+1 -5
Ver Arquivo
@@ -1,5 +1 @@
extends error
block content
h2 Cannot find #{url}
h2 Cannot find #{url}
+2 -10
Ver Arquivo
@@ -1,10 +1,2 @@
// note that we extend a different
// layout with jade for 4xx & 5xx
// responses
extends error
block content
h1 Error: #{error.message}
pre= error.stack
h1 Error: #{error.message}
pre= error.stack
-6
Ver Arquivo
@@ -1,6 +0,0 @@
html
head
title Error
body
h1 An error occurred!
block content
+11 -15
Ver Arquivo
@@ -1,15 +1,11 @@
extends layout
block content
h2 Pages Example
ul
li
| visit
a(href="/500") 500
li
| visit
a(href="/404") 404
li
| visit
a(href='/403') 403
h2 Pages Example
ul
li
| visit
a(href="/500") 500
li
| visit
a(href="/404") 404
li
| visit
a(href='/403') 403
+1 -1
Ver Arquivo
@@ -3,4 +3,4 @@ html
title Custom Pages Example
body
h1 My Site
block content
!= body
+10 -33
Ver Arquivo
@@ -3,33 +3,9 @@
* Module dependencies.
*/
var express = require('../../')
, app = module.exports = express();
var express = require('../../lib/express');
if ('test' != process.env.NODE_ENV)
app.use(express.logger('dev'));
app.use(app.router);
// the error handler is strategically
// placed *below* the app.router; if it
// were above it would not receive errors
// from app.get() etc
app.use(error);
// error handling middleware have an arity of 4
// instead of the typical (req, res, next),
// otherwise they behave exactly like regular
// middleware, you may have several of them,
// in different orders etc.
function error(err, req, res, next) {
// log it
if ('test' != process.env.NODE_ENV)
console.error(err.stack);
// respond with 500 "Internal Server Error".
res.send(500);
}
var app = express.createServer();
app.get('/', function(req, res){
// Caught and passed down to the errorHandler middleware
@@ -38,12 +14,13 @@ app.get('/', function(req, res){
app.get('/next', function(req, res, next){
// We can also pass exceptions to next()
process.nextTick(function(){
next(new Error('oh no!'));
});
next(new Error('oh no!'))
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
// The errorHandler middleware in this case will dump exceptions to stderr
// as well as show the stack trace in responses, currently handles text/plain,
// text/html, and application/json responses to aid in development
app.use('/', express.errorHandler({ dump: true, stack: true }));
app.listen(3000);
console.log('app listening on port 3000');
+66
Ver Arquivo
@@ -0,0 +1,66 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express');
var app = express.createServer();
// Register ejs as .html
app.register('.html', require('ejs'));
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
// Dummy users
var users = [
{ name: 'tj', email: 'tj@sencha.com' }
, { name: 'ciaran', email: 'ciaranj@gmail.com' }
, { name: 'aaron', email: 'aaron.heckmann+github@gmail.com' }
];
// dynamic helpers are simply functions that are invoked
// per request (once), passed both the request and response
// objects. These can be used for request-specific
// details within a view, such telling the layout which
// scripts to include.
app.dynamicHelpers({
// by simply returning an object here
// we can set it's properties such as "page.title"
// within a view, and it remains specific to that request,
// so it would be valid to do:
// page.title = user.name + "'s account"
page: function() {
return {};
},
// the scripts array here is assigned once,
// so by returning a closure, we can use script(path)
// in a template, instead of something like
// scripts.push(path).
script: function(req){
req._scripts = [];
return function(path){
req._scripts.push(path);
}
},
// to expose our scripts array for iteration within
// our views (typically the layout), we simply return it
// here, and since composite types are mutable, it will
// contain all of the paths pushed with the helper above.
scripts: function(req){
return req._scripts;
}
});
app.get('/', function(req, res){
res.render('users', { users: users });
});
app.listen(3000);
console.log('Express app started on port 3000');
@@ -0,0 +1,11 @@
<html>
<head>
<title><%- page.title %></title>
<% for (var i in scripts) { %>
<script src="<%= scripts[i] %>"></script>
<% } %>
</head>
<body>
<%- body %>
</body>
</html>
@@ -0,0 +1,8 @@
<% page.title = 'Users' %>
<% script('/javascripts/jquery.js') %>
<% script('/javascripts/users.js') %>
<h1>Users</h1>
<ul id="users">
<%- partial('user', users) %>
</ul>
@@ -0,0 +1 @@
<li><%= user.name %> &lt;<%= user.email %>&gt;</li>
+46
Ver Arquivo
@@ -0,0 +1,46 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express');
// App with session support
var app = express.createServer(
express.cookieParser()
, express.session({ secret: 'keyboard cat' })
);
// View settings
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.dynamicHelpers({
// express-messages is a dynamicHelper that
// renders the flash messages to HTML for you
// $ npm install express-messages
messages: require('express-messages')
});
app.dynamicHelpers({
// Another dynamic helper example. Since dynamic
// helpers resolve at view rendering time, we can
// "inject" the "page" local variable per request
// providing us with the request url.
page: function(req, res){
return req.url;
}
});
app.get('/', function(req, res){
// Not very realistic notifications but illustrates usage
req.flash('info', 'email queued');
req.flash('info', 'email sent');
req.flash('error', 'delivery failed');
res.render('index');
});
app.listen(3000);
console.log('Express app started on port 3000');
+3
Ver Arquivo
@@ -0,0 +1,3 @@
<h1>Flash Message Example</h1>
<p>on page <%- page %></p>
<%- messages() %>
+5
Ver Arquivo
@@ -0,0 +1,5 @@
<html>
<body>
<%- body %>
</body>
</html>
+8 -6
Ver Arquivo
@@ -1,10 +1,14 @@
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');
/**
* Module dependencies.
*/
var express = require('../../');
var express = require('../../lib/express');
var app = module.exports = express();
var app = express.createServer();
// Here we use the bodyDecoder middleware
// to parse urlencoded request bodies
@@ -73,7 +77,5 @@ app.put('/', function(req, res){
res.redirect('/?name=' + req.body.name);
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express app started on port 3000');
+7 -8
Ver Arquivo
@@ -3,9 +3,9 @@
* Module dependencies.
*/
var express = require('../../');
var express = require('../../lib/express');
var app = module.exports = express();
var app = express.createServer();
// Fake items
@@ -45,7 +45,8 @@ app.get('/item/:id.:format?', function(req, res, next){
+ '<items>'
+ '<item>' + item.name + '</item>'
+ '</items>';
res.type('xml').send(xml);
res.contentType('.xml');
res.send(xml);
break;
case 'html':
default:
@@ -61,9 +62,7 @@ app.get('/item/:id.:format?', function(req, res, next){
// Middleware
app.use(express.errorHandler());
app.use(express.errorHandler({ showStack: true }));
if (!module.parent) {
app.listen(3000);
silent || console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express app started on port 3000');
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@
var express = require('../../lib/express')
, http = require('http');
var app = express();
var app = express.createServer();
// Expose our views
+8 -14
Ver Arquivo
@@ -1,14 +1,8 @@
extends layout
block content
each user in users
.user
h2= user.name
p.summary
| <a href="http://github.com/#{user.name}">#{user.name}</a> has
| <strong>#{user.repos.length}</strong> repositories
| with a total of <strong>#{user.totalWatchers}</strong> watchers.
table#repos
for repo in user.repos
include repo
- each user in users
.user
h2= user.name
p.summary
| <a href="http://github.com/#{user.name}">#{user.name}</a> has
| <strong>#{user.repos.length}</strong> repositories
| with a total of <strong>#{user.totalWatchers}</strong> watchers.
table#repos!= partial('repo', user.repos)
+1 -2
Ver Arquivo
@@ -4,5 +4,4 @@ html
title Github Example
link(rel="stylesheet", href="/style.css")
body
#container
block content
#container!= body
+2 -3
Ver Arquivo
@@ -3,13 +3,12 @@
* Module dependencies.
*/
var express = require('../../');
var express = require('../../lib/express');
var app = express();
var app = express.createServer();
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
console.log('Express started on port 3000');
+8 -19
Ver Arquivo
@@ -13,13 +13,17 @@ var pub = __dirname + '/public';
// and then serve with connect's staticProvider
var app = express.createServer();
app.use(express.logger('dev'));
app.use(express.compiler({ src: pub, enable: ['sass'] }));
app.use(app.router);
app.use(express.static(pub));
app.use(express.errorHandler({ dump: true, stack: true }));
// Optional since express defaults to CWD/views
// we're using jade's template inheritance, so we dont need
// the express layout concept
app.set('view options', { layout: false });
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
// Set our default template engine to "jade"
@@ -34,30 +38,15 @@ function User(name, email) {
// Dummy users
var users = [
new User('tj', 'tj@vision-media.ca')
, new User('ciaran', 'ciaranj@gmail.com')
, new User('aaron', 'aaron.heckmann+github@gmail.com')
new User('Tobi', 'tobi@learnboost.com')
, new User('Loki', 'loki@learnboost.com')
, new User('Jane', 'jane@learnboost.com')
];
app.get('/', function(req, res){
res.render('users', { users: users });
});
app.get('/users/callback', function(req, res){
// a callback is also accepted
res.partial('users/user', users, function(err, html){
if (err) throw err;
res.send(html);
});
});
app.get('/users', function(req, res){
// we can use res.partial() as if
// we were in a view, utilizing the same api
// to render a fragment
res.partial('users/user', users);
});
app.get('/users/list', function(req, res){
// use "object" to utilize the name deduced from
// the view filename. The examples below are equivalent
-3
Ver Arquivo
@@ -1,3 +0,0 @@
head
title Jade Example
link(rel="stylesheet", href="/stylesheets/style.css")
+7 -3
Ver Arquivo
@@ -1,4 +1,8 @@
!!!
doctype 5
html
include header
body!= body
head
block title
title Jade Example
link(rel="stylesheet", href="/stylesheets/style.css")
body
block content
+12 -3
Ver Arquivo
@@ -1,3 +1,12 @@
- if (users.length)
h1 Users
#users!= partial('user', users)
extends ../layout
block title
title Users
block content
if users.length
h1 Users
#users
for user in users
include ./user
+3 -2
Ver Arquivo
@@ -1,3 +1,4 @@
ul#users
- each user in list
li!= partial('user', user)
for user in list
li
include ./user
+26
Ver Arquivo
@@ -0,0 +1,26 @@
/**
* Module dependencies.
*/
var express = require('../../');
app = express.createServer();
// load the config for this environment (NODE_ENV)
var config = require('./config')[app.settings.env];
// apply settings
for (var key in config) app.set(key, config[key]);
// apply middleware
config.middleware.forEach(app.use.bind(app));
app.get('/', function(req, res){
res.render('index', { layout: false });
});
app.listen(3000);
+19
Ver Arquivo
@@ -0,0 +1,19 @@
// ok so it's not JSON, but close enough :)
var express = require('../../');
exports.development = {
'view engine': 'jade'
, 'views': __dirname + '/views'
, 'title': 'My Site'
, 'middleware': [
express.logger('dev')
, app.router
, express.static(__dirname + '/public')
]
};
exports.production = {
};
+4
Ver Arquivo
@@ -0,0 +1,4 @@
html
body
h1 #{settings.title}
p Simple example
+8 -28
Ver Arquivo
@@ -3,49 +3,29 @@
* Module dependencies.
*/
var express = require('../../lib/express')
, url = require('url');
var express = require('../../lib/express');
var app = express.createServer();
app.set('views', __dirname + '/views');
// map .html to ejs module
app.register('html', require('ejs'));
app.set('view engine', 'html');
// set default layout, usually "layout"
app.locals.layout = 'layouts/default';
app.set('view options', { layout: 'layouts/default' });
app.use(function(req, res, next){
// expose the current path as a view local
res.locals.path = url.parse(req.url).pathname;
// assign content str for section
res.locals.contentFor = function(section, str){
res.locals[section] = str;
};
next();
});
// Set our default template engine to "ejs"
// which prevents the need for extensions
// (although you can still mix and match)
app.set('view engine', 'ejs');
app.get('/', function(req, res){
res.render('page');
res.render('pages/default');
});
app.get('/alternate', function(req, res){
res.render('page', { layout: 'layouts/alternate' });
});
app.get('/alternate2', function(req, res){
res.render('page2');
});
app.get('/defined-in-view', function(req, res){
// note that we do not explicitly
// state the layout here, the view does,
// although we could do it here as well.
res.render('pages');
res.render('pages/alternate');
});
app.listen(3000);
@@ -1 +0,0 @@
<p>Moar sidebar here</p>
@@ -0,0 +1,6 @@
<html>
<body>
<h1>Alternate Layout</h1>
<%- body %>
</body>
</html>
@@ -1,26 +0,0 @@
<html>
<title>Alternate</title>
<style>
body {
padding: 50px;
font: 14px "helvetica neue", helvetica, sans-serif;
color: #333;
}
#sidebar {
float: left;
width: 150px;
}
#content {
float: left;
}
</style>
<body>
<h1>Alternate Layout</h1>
<div id="sidebar">
<%- sidebar %>
</div>
<div id="content">
<%- body %>
</div>
</body>
</html>
@@ -0,0 +1,6 @@
<html>
<body>
<h1>Default Layout</h1>
<%- body %>
</body>
</html>
@@ -1,16 +0,0 @@
<html>
<head>
<title>Default</title>
<style>
body {
padding: 50px;
font: 14px "helvetica neue", helvetica, sans-serif;
color: #333;
}
</style>
</head>
<body>
<h1>Default Layout</h1>
<%- body %>
</body>
</html>
-8
Ver Arquivo
@@ -1,8 +0,0 @@
<h1>Page</h1>
<% if (path == '/alternate') { %>
<% contentFor('sidebar', partial('alternate-sidebar')) %>
<p>Click <a href="/">here</a> to view the default layout.</p>
<p>Click <a href="/alternate2">here</a> to view another alternate page.</p>
<% } else { %>
<p>Click <a href="/alternate">here</a> to view the alternate layout.</p>
<% } %>
-4
Ver Arquivo
@@ -1,4 +0,0 @@
<% layout('layouts/alternate') %>
<% contentFor('sidebar', '<p>Another sidebar here</p>') %>
<h1>Page</h1>
<p>Click <a href="/">here</a> to view the default layout.</p>
@@ -0,0 +1,2 @@
<% layout('layouts/alternate') %>
<h1>Page</h1>
@@ -0,0 +1 @@
<h1>Page</h1>
+36
Ver Arquivo
@@ -0,0 +1,36 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, md = require('node-markdown').Markdown;
var app = express.createServer();
// register .md so that markdown may comply
// with the express view system by implementing
// a .compile() method
app.register('.md', {
compile: function(str, options){
var html = md(str);
return function(locals){
return html.replace(/\{([^}]+)\}/g, function(_, name){
return locals[name];
});
};
}
});
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
app.set('view engine', 'md');
app.get('/', function(req, res){
res.render('index', { layout: false, title: 'Markdown Example' });
});
app.listen(3000);
console.log('Express app started on port 3000');
-45
Ver Arquivo
@@ -1,45 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../')
, fs = require('fs')
, md = require('github-flavored-markdown').parse;
var app = module.exports = express();
// register .md as an engine in express view system
app.engine('md', function(path, options, fn){
fs.readFile(path, 'utf8', function(err, str){
if (err) return fn(err);
try {
var html = md(str);
html = html.replace(/\{([^}]+)\}/g, function(_, name){
return options[name] || '';
})
fn(null, html);
} catch(err) {
fn(err);
}
});
})
app.set('views', __dirname + '/views');
// make it the default so we dont need .md
app.set('view engine', 'md');
app.get('/', function(req, res){
res.render('index', { title: 'Markdown Example' });
})
app.get('/fail', function(req, res){
res.render('missing', { title: 'Markdown Example' });
})
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
+24
Ver Arquivo
@@ -0,0 +1,24 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, blog = require('../blog/app');
var app = express.createServer();
app.use(express.cookieParser());
app.use(express.session({ secret: 'keyboard cat' }));
// mount the blog. the blog app is written using the "base"
// local variable, allowing it's urls to adjust to wherever
// we wish to mount it.
app.use('/blog', blog);
app.get('/', function(req, res){
res.send('Visit <a href="/blog">/blog</a>');
});
app.listen(3000);
console.log('Server listening on port 3000');
+31 -19
Ver Arquivo
@@ -3,34 +3,46 @@
* Module dependencies.
*/
var express = require('../../')
, format = require('util').format;
var express = require('../../lib/express')
, form = require('connect-form');
var app = module.exports = express()
// bodyParser in connect 2.x uses node-formidable to parse
// the multipart form data.
app.use(express.bodyParser())
var app = express.createServer(
// connect-form (http://github.com/visionmedia/connect-form)
// middleware uses the formidable middleware to parse urlencoded
// and multipart form data
form({ keepExtensions: true })
);
app.get('/', function(req, res){
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Title: <input type="text" name="title" /></p>'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', function(req, res, next){
// the uploaded file can be found as `req.files.image` and the
// title field as `req.body.title`
res.send(format('\nuploaded %s (%d Kb) to %s as %s'
, req.files.image.name
, req.files.image.size / 1024 | 0
, req.files.image.path
, req.body.title));
// connect-form adds the req.form object
// we can (optionally) define onComplete, passing
// the exception (if any) fields parsed, and files parsed
req.form.complete(function(err, fields, files){
if (err) {
next(err);
} else {
console.log('\nuploaded %s to %s'
, files.image.filename
, files.image.path);
res.redirect('back');
}
});
// We can add listeners for several form
// events such as "progress"
req.form.on('progress', function(bytesReceived, bytesExpected){
var percent = (bytesReceived / bytesExpected * 100) | 0;
process.stdout.write('Uploading: %' + percent + '\r');
});
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express app started on port 3000');
+2 -1
Ver Arquivo
@@ -23,7 +23,8 @@ function bootApplication(app) {
app.use(express.static(__dirname + '/public'));
// Example 500 page
app.use(function(err, req, res, next){
app.error(function(err, req, res){
console.dir(err)
res.render('500');
});
+5 -14
Ver Arquivo
@@ -3,8 +3,8 @@
* Module dependencies.
*/
var express = require('../../')
, app = module.exports = express();
var express = require('../../lib/express')
, app = express.createServer();
// Faux database
@@ -18,14 +18,7 @@ var users = [
// Convert :to and :from to integers
app.param(['to', 'from'], function(req, res, next, num, name){
req.params[name] = num = parseInt(num, 10);
if( isNaN(num) ){
next(new Error('failed to parseInt '+num));
} else {
next();
}
});
app.param(['to', 'from'], function(n){ return parseInt(n, 10); });
// Load user by id
@@ -64,7 +57,5 @@ app.get('/users/:from-:to', function(req, res, next){
res.send('users ' + names.slice(from, to).join(', '));
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express application listening on port 3000');
+4 -6
Ver Arquivo
@@ -3,9 +3,9 @@
* Module dependencies.
*/
var express = require('../../');
var express = require('../../lib/express');
var app = module.exports = express();
var app = express.createServer();
// Ad-hoc example resource method
@@ -85,7 +85,5 @@ app.get('/', function(req, res){
].join('\n'));
});
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
app.listen(3000);
console.log('Express app started on port 3000');
-21
Ver Arquivo
@@ -1,21 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, redis = require('redis')
, app = express.createServer()
, db = { users: [] };
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
// pretend db is a database, could be
// whatever you like
require('./boot')(app, db);
app.listen(3000);
console.log('Express app started on port 3000');
-26
Ver Arquivo
@@ -1,26 +0,0 @@
/**
* Module dependencies.
*/
var vm = require('vm')
, fs = require('fs');
module.exports = function(app, db){
var dir = __dirname + '/routes';
// grab a list of our route files
fs.readdirSync(dir).forEach(function(file){
var str = fs.readFileSync(dir + '/' + file, 'utf8');
// inject some pseudo globals by evaluating
// the file with vm.runInNewContext()
// instead of loading it with require(). require's
// internals use similar, so dont be afraid of "boot time".
var context = { app: app, db: db };
// we have to merge the globals for console, process etc
for (var key in global) context[key] = global[key];
// note that this is essentially no different than ... just using
// global variables, though it's only YOUR code that could influence
// them, which is a bonus.
vm.runInNewContext(str, context, file);
});
};
-4
Ver Arquivo
@@ -1,4 +0,0 @@
app.get('/', function(req, res){
res.render('index');
});
-20
Ver Arquivo
@@ -1,20 +0,0 @@
app.redirect('user list', '/users');
app.get('/users', function(req, res){
res.render('user/list', { users: db.users });
});
app.get('/user/add', function(req, res){
res.render('user/add');
});
app.post('/user', function(req, res){
var user = req.body.user;
db.users.push(user);
res.redirect('user list');
});
app.get('/user/:id', function(req, res){
res.render('user');
});
-4
Ver Arquivo
@@ -1,4 +0,0 @@
h2 Route sharing example
ul
li: a(href='/user/add') Add user
li: a(href='/users') User list
-11
Ver Arquivo
@@ -1,11 +0,0 @@
doctype html
html
head
title Route loading example
style
body {
padding: 50px;
font: 14px/1.5 solid helvetica, arial, sans-serif;
}
body
#content!= body
-5
Ver Arquivo
@@ -1,5 +0,0 @@
h2 Add a user
form(action='/user', method='post')
p: input(type='text', name='user[name]', placeholder='Username')
p: input(type='text', name='user[email]', placeholder='Email')
p: input(type='submit', value='Add')
@@ -1,6 +0,0 @@
h1= user.name
table
tbody
tr
td Email
td= user.email
@@ -1,5 +0,0 @@
h1 Users
- if (users.length)
!= partial('user', users)
- else
p No users, head over to <a href='/user/add'>/user/add</a> to create one.
+3 -2
Ver Arquivo
@@ -1,3 +1,4 @@
/**
* Module dependencies.
*/
@@ -39,7 +40,7 @@ function andRestrictToSelf(req, res, next) {
} else {
// You may want to implement specific exceptions
// such as UnauthorizedError or similar so that you
// can handle these can be special-cased in an error handler
// can handle these in app.error() specifically
// (view ./examples/pages for this)
next(new Error('Unauthorized'));
}
@@ -58,7 +59,7 @@ function andRestrictTo(role) {
// Middleware for faux authentication
// you would of course implement something real,
// but this illustrates how an authenticated user
// may interact with middleware
// may interacte with middleware
app.use(function(req, res, next){
req.authenticatedUser = users[0];
@@ -3,37 +3,29 @@
* Module dependencies.
*/
var express = require('../../');
var express = require('../../lib/express');
var app = module.exports = express();
var app = express.createServer();
// create an error with .status. we
// can then use the property in our
// custom error handler (Connect repects this prop as well)
function error(status, msg) {
var err = new Error(msg);
err.status = status;
return err;
}
// configuration
// if we wanted to supply more than JSON, we could
// use something similar to the content-negotiation
// example.
// here we validate the API key,
// by mounting this middleware to /api
// meaning only paths prefixed with "/api"
// by mounting this middleware to /api/v1
// meaning only paths prefixed with "/api/v1"
// will cause this middleware to be invoked
app.use('/api', function(req, res, next){
app.use('/api/v1', function(req, res, next){
var key = req.query['api-key'];
// key isnt present
if (!key) return next(error(400, 'api key required'));
if (!key) return next(new Error('api key required'));
// key is invalid
if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key'));
if (!~apiKeys.indexOf(key)) return next(new Error('invalid api key'));
// all good, store req.key for route access
req.key = key;
@@ -52,23 +44,39 @@ app.use(app.router);
// regular middleware.
app.use(function(err, req, res, next){
// whatever you want here, feel free to populate
// properties on `err` to treat it differently in here.
res.send(err.status || 500, { error: err.message });
// properties on `err` to treat it differently in here,
// or when you next(err) set res.statusCode= etc.
res.send({ error: err.message }, 500);
});
// our custom JSON 404 middleware. Since it's placed last
// it will be the last middleware called, if all others
// invoke next() and do not respond.
app.use(function(req, res){
res.send(404, { error: "Lame, can't find that" });
res.send({ error: "Lame, can't find that" }, 404);
});
/**
* Generate our unique identifier.
*/
function uid() {
return [
Math.random() * 0xffff | 0
, Math.random() * 0xffff | 0
, Math.random() * 0xffff | 0
, Date.now()
].join('-');
}
// map of valid api keys, typically mapped to
// account info with some sort of database like redis.
// api keys do _not_ serve as authentication, merely to
// track API usage or help prevent malicious behavior etc.
var apiKeys = ['foo', 'bar', 'baz'];
var apiKeys = [uid(), uid(), uid()];
console.log('valid keys:\n ', apiKeys.join('\n '));
// these two objects will serve as our faux database
@@ -93,15 +101,15 @@ var userRepos = {
// we now can assume the api key is valid,
// and simply expose the data
app.get('/api/users', function(req, res, next){
app.get('/api/v1/users', function(req, res, next){
res.send(users);
});
app.get('/api/repos', function(req, res, next){
app.get('/api/v1/repos', function(req, res, next){
res.send(repos);
});
app.get('/api/user/:name/repos', function(req, res, next){
app.get('/api/v1/user/:name/repos', function(req, res, next){
var name = req.params.name
, user = userRepos[name];
@@ -109,7 +117,5 @@ app.get('/api/user/:name/repos', function(req, res, next){
else next();
});
if (!module.parent) {
app.listen(3000);
console.log('Express server listening on port 3000');
}
app.listen(3000);
console.log('Express server listening on port 3000');
+1 -3
Ver Arquivo
@@ -1,4 +1,2 @@
module.exports = process.env.EXPRESS_COV
? require('./lib-cov/express')
: require('./lib/express');
module.exports = require('./lib/express');
+37 -43
Ver Arquivo
@@ -9,75 +9,69 @@
* Module dependencies.
*/
var http = require('http')
, connect = require('connect')
, proto = require('./application')
var connect = require('connect')
, HTTPSServer = require('./https')
, HTTPServer = require('./http')
, Route = require('./router/route')
, Router = require('./router')
, req = require('./request')
, res = require('./response')
, utils = connect.utils;
/**
* Expose `createApplication()`.
* Re-export connect auto-loaders.
*
* This prevents the need to `require('connect')` in order
* to access core middleware, so for example `express.logger()` instead
* of `require('connect').logger()`.
*/
exports = module.exports = createApplication;
var exports = module.exports = connect.middleware;
/**
* Framework version.
*/
exports.version = '3.0.0alpha1';
exports.version = '2.5.2';
/**
* Create an express application.
* Shortcut for `new Server(...)`.
*
* @return {Function}
* @param {Function} ...
* @return {Server}
* @api public
*/
function createApplication() {
var app = connect();
utils.merge(app, proto);
app.request = { __proto__: req };
app.response = { __proto__: res };
app.init();
return app;
}
/**
* Expose connect.middleware as express.*
* for example `express.logger` etc.
*/
for (var key in connect.middleware) {
Object.defineProperty(
exports
, key
, Object.getOwnPropertyDescriptor(connect.middleware, key));
}
/**
* Expose the prototypes.
*/
exports.application = proto;
exports.request = req;
exports.response = res;
exports.createServer = function(options){
if ('object' == typeof options) {
return new HTTPSServer(options, Array.prototype.slice.call(arguments, 1));
} else {
return new HTTPServer(Array.prototype.slice.call(arguments));
}
};
/**
* Expose constructors.
*/
exports.HTTPServer = HTTPServer;
exports.HTTPSServer = HTTPSServer;
exports.Route = Route;
exports.Router = Router;
/**
* Expose HTTP methods.
* View extensions.
*/
exports.methods = require('./router/methods');
exports.View =
exports.view = require('./view');
/**
* Response extensions.
*/
require('./response');
/**
* Request extensions.
*/
require('./request');
// Error handler title
+269 -221
Ver Arquivo
@@ -1,6 +1,6 @@
/*!
* Express - proto
* Express - HTTPServer
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
@@ -9,120 +9,132 @@
* Module dependencies.
*/
var connect = require('connect')
var qs = require('qs')
, connect = require('connect')
, router = require('./router')
, Router = require('./router')
, methods = Router.methods.concat('del', 'all')
, middleware = require('./middleware')
, debug = require('debug')('express:application')
, View = require('./view')
, view = require('./view')
, toArray = require('./utils').toArray
, methods = router.methods.concat('del', 'all')
, url = require('url')
, utils = connect.utils
, path = require('path')
, http = require('http')
, join = path.join
, fs = require('fs');
, utils = connect.utils;
/**
* Application prototype.
* Expose `HTTPServer`.
*/
var app = exports = module.exports = {};
exports = module.exports = HTTPServer;
/**
* Server proto.
*/
var app = HTTPServer.prototype;
/**
* Initialize a new `HTTPServer` with optional `middleware`.
*
* @param {Array} middleware
* @api public
*/
function HTTPServer(middleware){
connect.HTTPServer.call(this, []);
this.init(middleware);
};
/**
* Inherit from `connect.HTTPServer`.
*/
app.__proto__ = connect.HTTPServer.prototype;
/**
* Initialize the server.
*
* - setup default configuration
* - setup default middleware
* - setup route reflection methods
*
* @param {Array} middleware
* @api private
*/
app.init = function(){
app.init = function(middleware){
var self = this;
this.cache = {};
this.settings = {};
this.engines = {};
this.viewCallbacks = [];
this.defaultConfiguration();
this.redirects = {};
this.isCallbacks = {};
this._locals = {};
this.dynamicViewHelpers = {};
this.errorHandlers = [];
// route reflection methods
this.set('env', process.env.NODE_ENV || 'development');
// expose objects to each other
this.use(function(req, res, next){
req.query = req.query || {};
res.setHeader('X-Powered-By', 'Express');
req.app = res.app = self;
req.res = res;
res.req = req;
req.next = next;
// assign req.query
if (req.url.indexOf('?') > 0) {
var query = url.parse(req.url).query;
req.query = qs.parse(query);
}
next();
});
// apply middleware
if (middleware) middleware.forEach(self.use.bind(self));
// router
this.routes = new Router(this);
this.__defineGetter__('router', function(){
this.__usedRouter = true;
return self.routes.middleware;
});
// default locals
this.locals({
settings: this.settings
, app: this
});
// default development configuration
this.configure('development', function(){
this.enable('hints');
});
// default production configuration
this.configure('production', function(){
this.enable('view cache');
});
// register error handlers on "listening"
// so that they disregard definition position.
this.on('listening', this.registerErrorHandlers.bind(this));
// route manipulation methods
methods.forEach(function(method){
self.lookup[method] = function(path){
return self._router.lookup(method, path);
return self.routes.lookup(method, path);
};
self.match[method] = function(path){
return self.routes.match(method, path);
};
self.remove[method] = function(path){
return self._router.lookup(method, path).remove();
return self.routes.lookup(method, path).remove();
};
});
// del -> delete
self.lookup.del = self.lookup.delete;
self.match.del = self.match.delete;
self.remove.del = self.remove.delete;
};
/**
* Initialize application configuration.
*
* @api private
*/
app.defaultConfiguration = function(){
var self = this;
// default settings
this.set('env', process.env.NODE_ENV || 'development');
debug('booting in %s mode', this.get('env'));
// implicit middleware
this.use(connect.query());
this.use(middleware.init(this));
// app locals
this.locals = function(obj){
for (var key in obj) self.locals[key] = obj[key];
return self;
};
// response locals
this.locals.use = function(fn){
if (3 == fn.length) {
self.viewCallbacks.push(fn);
} else {
self.viewCallbacks.push(function(req, res, done){
fn(req, res);
done();
});
}
return this;
};
// router
this._router = new Router(this);
this.routes = this._router.routes;
this.__defineGetter__('router', function(){
this._usedRouter = true;
this._router.caseSensitive = this.enabled('case sensitive routing');
this._router.strict = this.enabled('strict routing');
return this._router.middleware;
});
// default locals
this.locals.settings = this.settings;
// default configuration
this.enable('jsonp callback');
this.configure('development', function(){
this.set('json spaces', 2);
});
this.configure('production', function(){
this.enable('view cache');
});
};
/**
* Remove routes matching the given `path`.
*
@@ -132,45 +144,82 @@ app.defaultConfiguration = function(){
*/
app.remove = function(path){
return this._router.lookup('all', path).remove();
return this.routes.lookup('all', path).remove();
};
/**
* Lookup routes defined with a path
* equivalent to `path`.
*
* @param {String} path
* @param {Stirng} path
* @return {Array}
* @api public
*/
app.lookup = function(path){
return this._router.lookup('all', path);
return this.routes.lookup('all', path);
};
/**
* Proxy `connect#use()` to apply settings to
* mounted applications.
* Lookup routes matching the given `url`.
*
* @param {String|Function|Server} route
* @param {Function|Server} fn
* @return {app} for chaining
* @param {Stirng} url
* @return {Array}
* @api public
*/
app.use = function(route, fn){
var app, home, handle;
app.match = function(url){
return this.routes.match('all', url);
};
// default route to '/'
if ('string' != typeof route) fn = route, route = '/';
/**
* When using the vhost() middleware register error handlers.
*/
app.onvhost = function(){
this.registerErrorHandlers();
};
/**
* Register error handlers.
*
* @return {Server} for chaining
* @api public
*/
app.registerErrorHandlers = function(){
this.errorHandlers.forEach(function(fn){
this.use(function(err, req, res, next){
fn.apply(this, arguments);
});
}, this);
return this;
};
/**
* Proxy `connect.HTTPServer#use()` to apply settings to
* mounted applications.
*
* @param {String|Function|Server} route
* @param {Function|Server} middleware
* @return {Server} for chaining
* @api public
*/
app.use = function(route, middleware){
var app, base, handle;
if ('string' != typeof route) {
middleware = route, route = '/';
}
// express app
if (fn.handle && fn.set) app = fn;
if (middleware.handle && middleware.set) app = middleware;
// restore .app property on req and res
if (app) {
app.route = route;
fn = function(req, res, next) {
middleware = function(req, res, next) {
var orig = req.app;
app.handle(req, res, function(err){
req.app = res.app = orig;
@@ -179,38 +228,86 @@ app.use = function(route, fn){
};
}
connect.proto.use.call(this, route, fn);
connect.HTTPServer.prototype.use.call(this, route, middleware);
// mounted an app
// mounted an app, invoke the hook
// and adjust some settings
if (app) {
base = this.set('basepath') || this.route;
if ('/' == base) base = '';
base = base + (app.set('basepath') || app.route);
app.set('basepath', base);
app.parent = this;
app.emit('mount', this);
if (app.__mounted) app.__mounted.call(app, this);
}
return this;
};
/**
* Register the given template engine callback `fn`
* as `ext`. For example we may wish to map ".html"
* files to ejs rather than using the ".ejs" extension.
* Assign a callback `fn` which is called
* when this `Server` is passed to `Server#use()`.
*
* app.engine('.html', require('ejs').render);
* Examples:
*
* or
* var app = express.createServer()
* , blog = express.createServer();
*
* app.engine('html', require('ejs').render);
* blog.mounted(function(parent){
* // parent is app
* // "this" is blog
* });
*
* app.use(blog);
*
* @param {String} ext
* @param {Function} fn
* @return {app} for chaining
* @return {Server} for chaining
* @api public
*/
app.engine = function(ext, fn){
if ('function' != typeof fn) throw new Error('callback function required');
if ('.' != ext[0]) ext = '.' + ext;
this.engines[ext] = fn;
app.mounted = function(fn){
this.__mounted = fn;
return this;
};
/**
* See: view.register.
*
* @return {Server} for chaining
* @api public
*/
app.register = function(){
view.register.apply(this, arguments);
return this;
};
/**
* Register the given view helpers `obj`. This method
* can be called several times to apply additional helpers.
*
* @param {Object} obj
* @return {Server} for chaining
* @api public
*/
app.helpers =
app.locals = function(obj){
utils.merge(this._locals, obj);
return this;
};
/**
* Register the given dynamic view helpers `obj`. This method
* can be called several times to apply additional helpers.
*
* @param {Object} obj
* @return {Server} for chaining
* @api public
*/
app.dynamicHelpers = function(obj){
utils.merge(this.dynamicViewHelpers, obj);
return this;
};
@@ -269,7 +366,7 @@ app.engine = function(ext, fn){
*
* @param {String|Array|Function} name
* @param {Function} fn
* @return {app} for chaining
* @return {Server} for chaining
* @api public
*/
@@ -286,18 +383,47 @@ app.param = function(name, fn){
});
// param logic
} else if ('function' == typeof name) {
this._router.param(name);
this.routes.param(name);
// single
} else {
if (':' == name[0]) name = name.substr(1);
fns.forEach(function(fn){
self._router.param(name, fn);
self.routes.param(name, fn);
});
}
return this;
};
/**
* Assign a custom exception handler callback `fn`.
* These handlers are always _last_ in the middleware stack.
*
* @param {Function} fn
* @return {Server} for chaining
* @api public
*/
app.error = function(fn){
this.errorHandlers.push(fn);
return this;
};
/**
* Register the given callback `fn` for the given `type`.
*
* @param {String} type
* @param {Function} fn
* @return {Server} for chaining
* @api public
*/
app.is = function(type, fn){
if (!fn) return this.isCallbacks[type];
this.isCallbacks[type] = fn;
return this;
};
/**
* Assign `setting` to `val`, or return `setting`'s value.
* Mounted servers inherit their parent server's settings.
@@ -309,7 +435,7 @@ app.param = function(name, fn){
*/
app.set = function(setting, val){
if (1 == arguments.length) {
if (val === undefined) {
if (this.settings.hasOwnProperty(setting)) {
return this.settings[setting];
} else if (this.parent) {
@@ -321,21 +447,6 @@ app.set = function(setting, val){
}
};
/**
* Return the app's absolute pathname
* based on the parent(s) that have
* mounted it.
*
* @return {String}
* @api private
*/
app.path = function(){
return this.parent
? this.parent.path() + this.route
: '';
};
/**
* Check if `setting` is enabled.
*
@@ -364,7 +475,7 @@ app.disabled = function(setting){
* Enable `setting`.
*
* @param {String} setting
* @return {app} for chaining
* @return {Server} for chaining
* @api public
*/
@@ -376,7 +487,7 @@ app.enable = function(setting){
* Disable `setting`.
*
* @param {String} setting
* @return {app} for chaining
* @return {Server} for chaining
* @api public
*/
@@ -384,6 +495,20 @@ app.disable = function(setting){
return this.set(setting, false);
};
/**
* Redirect `key` to `url`.
*
* @param {String} key
* @param {String} url
* @return {Server} for chaining
* @api public
*/
app.redirect = function(key, url){
this.redirects[key] = url;
return this;
};
/**
* Configure callback for zero or more envs,
* when no env is specified that callback will
@@ -406,44 +531,29 @@ app.disable = function(setting){
*
* @param {String} env...
* @param {Function} fn
* @return {app} for chaining
* @return {Server} for chaining
* @api public
*/
app.configure = function(env, fn){
var envs = 'all'
, args = [].slice.call(arguments);
, args = toArray(arguments);
fn = args.pop();
if (args.length) envs = args;
if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this);
return this;
};
/**
* Listen for connections.
*
* This method takes the same arguments
* as node's `http.Server#listen()`.
*
* @return {http.Server}
* @api public
*/
app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
/**
* Delegate `.VERB(...)` calls to `.route(VERB, ...)`.
*/
methods.forEach(function(method){
app[method] = function(path){
if ('get' == method && 1 == arguments.length) return this.set(path);
var args = [method].concat([].slice.call(arguments));
if (!this._usedRouter) this.use(this.router);
return this._router.route.apply(this._router, args);
if (1 == arguments.length) return this.routes.lookup(method, path);
var args = [method].concat(toArray(arguments));
if (!this.__usedRouter) this.use(this.router);
return this.routes._route.apply(this.routes, args);
}
});
@@ -453,14 +563,15 @@ methods.forEach(function(method){
*
* @param {String} path
* @param {Function} ...
* @return {app} for chaining
* @return {Server} for chaining
* @api public
*/
app.all = function(path){
var args = arguments;
if (1 == args.length) return this.routes.lookup('all', path);
methods.forEach(function(method){
if ('all' == method || 'del' == method) return;
if ('all' == method) return;
app[method].apply(this, args);
}, this);
return this;
@@ -470,66 +581,3 @@ app.all = function(path){
app.del = app.delete;
/**
* Render the given view `name` name with `options`
* and a callback accepting an error and the
* rendered template string.
*
* @param {String} name
* @param {String|Function} options or fn
* @param {Function} fn
* @api public
*/
app.render = function(name, options, fn){
var self = this
, opts = {}
, cache = this.cache
, engines = this.engines
, view;
// support callback function as second arg
if ('function' == typeof options) {
fn = options, options = {};
}
// merge app.locals
utils.merge(opts, this.locals);
// merge options.locals
if (options.locals) utils.merge(opts, options.locals);
// merge options
utils.merge(opts, options);
// set .cache unless explicitly provided
opts.cache = null == opts.cache
? this.enabled('view cache')
: opts.cache;
// primed cache
if (opts.cache) view = cache[name];
// view
if (!view) {
view = new View(name, {
defaultEngine: this.get('view engine')
, root: this.get('views') || process.cwd() + '/views'
, engines: engines
});
if (!view.path) {
return fn(new Error('Failed to lookup view "' + name + '"'));
}
// prime the cache
if (opts.cache) cache[name] = view;
}
// render
try {
view.render(opts, fn);
} catch (err) {
fn(err);
}
};

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais