Comparar commits

...

117 Commits

Autor SHA1 Mensagem Data
TJ Holowaychuk 33eaa8329c Release 3.0.5 2012-12-19 13:46:16 -08:00
TJ Holowaychuk 3c4fd57e51 Merge pull request #1451 from aweeks/fix-304-must-not-contain-body
Explicitly remove Transfer-Encoding header from 204 and 304 responses
2012-12-19 13:34:16 -08:00
Alex Weeks a1e42ac33f Explicitly remove Transfer-Encoding header from 204 and 304 responses
Per RFC 2616 §10.3.6 & §10.2.5 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) "The [204/304] response MUST NOT contain a message-body, and thus is always terminated by the first empty line after the header fields."
2012-12-19 10:53:17 -08:00
Thorsten Lorenz ce7d7bfd8d add throwing when a non-function is passed to a route 2012-12-14 15:06:17 -08:00
TJ Holowaychuk 9bd86cdddc Revert "add 'etag' option"
This reverts commit 6f6eec7d8d.
2012-12-06 15:15:49 -08:00
TJ Holowaychuk 0117464ac2 Release 3.0.4 2012-12-05 17:10:59 -08:00
Max Riveiro 6f6eec7d8d add 'etag' option 2012-12-05 16:49:09 -08:00
TJ Holowaychuk a4e93c0fb8 update connect 2012-12-05 16:35:44 -08:00
TJ Holowaychuk e2ad0d3d6e merge 2012-11-21 08:46:36 -08:00
TJ Holowaychuk 763be5e631 Merge pull request #1426 from piscis/master
change crc generator because of license issue
2012-11-21 08:45:42 -08:00
TJ Holowaychuk c8526932f3 Merge branch 'master' of github.com:visionmedia/express 2012-11-21 08:43:13 -08:00
TJ Holowaychuk 5cf29a3d29 Merge pull request #1425 from gmethvin/encode_text_redirect
Escape URLs in text/plain res.redirect response
2012-11-21 08:42:33 -08:00
Alexander Pirsig 18a3cc03ee use buffer-crc32 module for ETag CRC generator 2012-11-21 12:44:07 +01:00
Greg Methvin ea5e254c7d Escape URLs in text/plain res.redirect response
Escape the URL printed by res.redirect using URL encoding. This
prevents some browsers (primarily old versions of IE) from attempting
to sniff the Content-Type and evaluate it as HTML, which causes a
cross-site scripting vulnerability.
2012-11-21 02:22:37 -05:00
TJ Holowaychuk 060653bd4c Merge branch 'master' of github.com:visionmedia/express 2012-11-20 14:25:30 -08:00
TJ Holowaychuk b709009bc9 Release 3.0.3 2012-11-13 09:14:13 -08:00
TJ Holowaychuk b80d7ec257 update connect 2012-11-13 09:12:47 -08:00
TJ Holowaychuk ff0384e610 update cookie module 2012-11-13 09:12:32 -08:00
TJ Holowaychuk ab9c275bde fix cookie max-age
the cookie module we depend on never used to
set this value, however now it does :)
2012-11-13 09:08:37 -08:00
TJ Holowaychuk c70db96b06 Update examples/cors/index.js 2012-11-08 13:52:20 -08:00
TJ Holowaychuk 1c616e29e2 Merge branch 'master' of github.com:visionmedia/express 2012-11-08 09:20:29 -08:00
TJ Holowaychuk cb7518435f Merge pull request #1406 from DmitryBochkarev/patch-1
remove connect.static.send import from response.js
2012-11-08 09:20:20 -08:00
TJ Holowaychuk 79f81c0a25 Merge pull request #1408 from Laboratory/master
delete unused variables
2012-11-08 09:20:08 -08:00
TJ Holowaychuk 72b9e48331 Release 3.0.2 2012-11-08 09:15:59 -08:00
TJ Holowaychuk eba6aa1767 fix .version 2012-11-08 09:15:24 -08:00
Vitaly 534fbdb307 delete unused variables 2012-11-08 17:07:08 +04:00
Dmitry Bochkarev 6b309a4457 remove connect.static.send import from response.js 2012-11-08 12:43:38 +05:00
TJ Holowaychuk af5e38c31a Update Readme.md 2012-11-05 09:10:34 -08:00
TJ Holowaychuk 4283f38698 add OPTIONS to cors example. Closes #1398 2012-11-04 13:21:55 -08:00
TJ Holowaychuk 2d49c0d1f3 Merge branch 'master' of github.com:visionmedia/express 2012-11-04 12:28:53 -08:00
TJ Holowaychuk a7ca3817db fix route chaining regression. Closes #1397 2012-11-04 12:28:35 -08:00
TJ Holowaychuk 1f044547ee Release 3.0.1 2012-11-01 17:27:53 -07:00
TJ Holowaychuk 612fc47044 update connect 2012-11-01 17:27:33 -07:00
TJ Holowaychuk 8959ff155b Merge pull request #1388 from shtylman/unused-variables
remove unused variables
2012-10-27 13:10:14 -07:00
Roman Shtylman dadf57cc8b remove unused variables
Tests and examples with unused variables are unchanged.
2012-10-27 16:04:00 -04:00
TJ Holowaychuk 764b6c61d9 Merge pull request #1387 from valllabh/patch-1
Update Readme.md
2012-10-26 06:44:53 -07:00
vallabh 582dadf787 Update Readme.md
Text alignment in Contributors list
2012-10-26 12:24:01 +05:30
TJ Holowaychuk 12d97169d7 Release 3.0.0 2012-10-23 15:29:20 -07:00
TJ Holowaychuk c29cfa823d change res.redirect() to utilize a pathname-relative Location again. Closes #1382
nginx does not seem to set Host correctly,
though Location should be relative as per RFC
myself nor anyone else can report a client
that does not handle relative correctly so
this will be fine until then
2012-10-23 14:08:18 -07:00
TJ Holowaychuk e183a9694e add make clean 2012-10-19 11:47:36 -07:00
TJ Holowaychuk d6cb449011 add "Basic" check to req.auth 2012-10-19 11:46:46 -07:00
TJ Holowaychuk 7bf4ad30fc add req.auth test coverage 2012-10-19 11:44:44 -07:00
TJ Holowaychuk b3936b96e5 add cb && cb(payload) to res.jsonp(). Closes #1374 2012-10-16 11:57:37 -07:00
TJ Holowaychuk 44d0625e91 fix view-locals example. Closes #1370
this was from 2x, doesnt need to be there at all
2012-10-15 16:07:56 -07:00
TJ Holowaychuk c492cde048 Merge branch 'examples' 2012-10-09 19:31:56 -07:00
TJ Holowaychuk c2fa6cc94d fix route-separation example 2012-10-09 19:31:52 -07:00
TJ Holowaychuk 464608025b refactor ejs example some more 2012-10-09 19:26:55 -07:00
TJ Holowaychuk d653d2308b refactor ejs example 2012-10-09 19:26:17 -07:00
TJ Holowaychuk a52b1f121c add EJS title example to auth 2012-10-09 19:21:50 -07:00
TJ Holowaychuk 9edd8be520 remove user footer info from auth example
looks a little weird
2012-10-09 19:20:30 -07:00
TJ Holowaychuk aa1d47600a fix auth example acceptance tests 2012-10-09 19:19:54 -07:00
sakateka be7ec8b40e improved ejs Example 2012-10-09 19:16:54 -07:00
sakateka 8e12dd9c17 Checked all the examples 2012-10-09 19:16:54 -07:00
TJ Holowaychuk fee0f0dce0 Merge branch 'error-handling-routes' 2012-10-09 19:09:21 -07:00
TJ Holowaychuk 0dd80e7b50 refactor routes.error tests 2012-10-09 19:09:12 -07:00
TJ Holowaychuk 78d5b72081 rename a test file 2012-10-09 19:06:23 -07:00
Sean Soong e0df865401 make application routing callback behave the same as middleware, fix logic and add test code 2012-10-09 19:05:30 -07:00
Sean Soong 2abcbed67a make application routing callback behave the same as middleware 2012-10-09 19:05:30 -07:00
TJ Holowaychuk 02b9d0b2e6 fix express.mime reference, should be connect.mime 2012-10-09 18:59:44 -07:00
TJ Holowaychuk 927e181db7 update connect 2012-10-09 18:56:47 -07:00
TJ Holowaychuk dc411b3175 Merge pull request #1364 from isaacs/patch-1
package.json: Remove publishConfig field
2012-10-09 08:43:37 -07:00
Isaac Z. Schlueter 1e870f0f0d package.json: Remove publishConfig field
Fixes #1359
2012-10-09 08:14:36 -07:00
TJ Holowaychuk 3cd01598a5 Merge pull request #1355 from lihanli/view-cache-test
set the NODE_ENV to development for the development view cache test
2012-10-06 15:25:07 -07:00
lihan 3b6d683b7f set the NODE_ENV to development for the development view cache test 2012-10-06 17:58:17 -04:00
TJ Holowaychuk eeef763f6d Merge branch 'master' of github.com:visionmedia/express 2012-10-06 09:58:27 -07:00
TJ Holowaychuk 76d3ec583d move default of "views" out so multiple cwd() calls are not made 2012-10-06 09:58:17 -07:00
TJ Holowaychuk 077d8b9247 Merge pull request #1354 from sakateka/master
examples/auth/app.js
2012-10-05 09:17:18 -07:00
sakateka 92840b9f68 Fixed: notify of a successful auth. 2012-10-05 12:23:11 +04:00
TJ Holowaychuk bf60d5a041 update connect 2012-09-27 12:39:26 -07:00
TJ Holowaychuk 56ffab045e add backwards compat for res.redirect() status. Closes #1336 2012-09-26 09:07:22 -07:00
TJ Holowaychuk 496ee401d7 Merge branch 'master' of github.com:visionmedia/express 2012-09-26 09:04:35 -07:00
TJ Holowaychuk f0d5b3b368 remove non-primitive string support for res.send()
kinda silly.. valueOf() before if you happen to use
boxed strings, otherwise it is unfair that dont support
other boxed primitives all over, and quite frankly no one does
2012-09-26 09:04:26 -07:00
TJ Holowaychuk 88072a56ea refactor 2012-09-26 09:01:55 -07:00
TJ Holowaychuk 0d3a637389 add support for res.json() to retain previously defined Content-Types. Closes #1349 2012-09-26 09:00:52 -07:00
TJ Holowaychuk dc44f3c226 Update Readme.md 2012-09-25 13:55:57 -07:00
TJ Holowaychuk 1029b0b97f adjust locals tests 2012-09-25 08:45:09 -07:00
TJ Holowaychuk 84f8228b8c update send 2012-09-19 11:37:46 -07:00
TJ Holowaychuk 968e8f0121 Release 3.0.0rc5 2012-09-18 11:48:20 -07:00
TJ Holowaychuk 9eb1da4568 update connect 2012-09-18 11:44:50 -07:00
TJ Holowaychuk 315e79e9f0 add redis search example 2012-09-18 09:31:12 -07:00
TJ Holowaychuk 363d0d4f41 Merge branch 'master' of github.com:visionmedia/express 2012-09-13 09:52:46 -07:00
TJ Holowaychuk 5ac631a270 add "x-powered-by" setting 2012-09-13 09:52:35 -07:00
TJ Holowaychuk 75fc882001 Merge pull request #1319 from pyrotechnick/patch-1
typo
2012-09-04 12:50:46 -07:00
Nicholas Kinsey d7cb213eeb Update lib/application.js
typo: http -> https
2012-09-05 05:20:37 +10:00
TJ Holowaychuk 568e0d297a add "application/octet-stream" redirect Accept test case. Closes #1317 2012-09-03 16:17:49 -07:00
TJ Holowaychuk 8edf358739 refactor res.format(), dont pass "default" to req.accepts() 2012-09-03 16:16:46 -07:00
TJ Holowaychuk 40be3ed05d update connect dep 2012-09-03 14:49:46 -07:00
TJ Holowaychuk 2c174d6b3b add app.router to static-files example 2012-09-03 08:54:39 -07:00
TJ Holowaychuk 60ee465bf7 add static-files example
point people here if they have
problems with serving static files
2012-09-03 08:52:53 -07:00
TJ Holowaychuk 51210d6b95 Release 3.0.0rc4 2012-08-30 22:13:38 -07:00
TJ Holowaychuk a6caa267bd add res.jsonp(). Closes #1307
this also removes the jsonp
2012-08-30 09:29:43 -07:00
TJ Holowaychuk cdb3e9dc0d fix etag quoting. Closes #1310 2012-08-30 08:49:48 -07:00
TJ Holowaychuk f2f09767fb add etag util 2012-08-30 08:27:57 -07:00
TJ Holowaychuk eec31d7126 fix acceptance tests 2012-08-29 10:47:29 -07:00
TJ Holowaychuk 3c5ad753b6 add "verbose errors" option to error-pages example 2012-08-29 10:46:52 -07:00
TJ Holowaychuk dd338b5567 Merge pull request #1309 from nickjj/patch-1
fix error-pages 404 status
2012-08-29 10:42:42 -07:00
nickjj 1b15af713c fix error-pages 404 status 2012-08-29 14:31:13 -03:00
TJ Holowaychuk 89c5affc3b fix jsonp callback char restrictions 2012-08-28 18:11:49 -07:00
TJ Holowaychuk 2bba69f633 remove old OPTIONS default response
relatively useless since its so non-informative,
let me know if anyone has an objection to this,
i think its best to define these for your API
2012-08-28 17:24:52 -07:00
TJ Holowaychuk 4403f136b7 add another route example to express(1) so people are not so confused 2012-08-28 16:18:00 -07:00
TJ Holowaychuk f7c1c638bb add some comments to error-pages example 2012-08-28 10:28:58 -07:00
TJ Holowaychuk f2d7bbe0e9 change jsonp callback default to false. Closes #1304 2012-08-28 09:08:41 -07:00
TJ Holowaychuk 87468cffce update connect dep 2012-08-21 19:09:18 -07:00
TJ Holowaychuk 3f7e3a714e drop to assert() for less crazy error message 2012-08-16 10:14:05 -07:00
TJ Holowaychuk 38a9caf159 update send 2012-08-16 10:08:55 -07:00
TJ Holowaychuk 500c8ab4b3 docs 2012-08-14 04:14:37 -07:00
TJ Holowaychuk c4ad97d555 add redis online user activity tracking example 2012-08-14 04:13:55 -07:00
TJ Holowaychuk b96401ac83 Release 3.0.0rc3 2012-08-13 20:23:59 -07:00
TJ Holowaychuk 32a5c9cba5 Merge pull request #1286 from tnydwrds/fix-signed-cookie-prefix
Fix signed cookie prefix
2012-08-13 20:21:36 -07:00
Tony Edwards 0217e6ce96 Fix signed cookie prefix
Update res.cookie to prefix signed cookies with 's:'
2012-08-13 20:01:17 -07:00
TJ Holowaychuk 6bebe0837f refactor res.render() to prevent clobbering "locals" 2012-08-11 15:04:54 -07:00
TJ Holowaychuk ff1c6f0cfa rename multipart app.js to index.js 2012-08-09 20:08:03 -07:00
TJ Holowaychuk 8ac3e80bf0 Merge branch 'master' of github.com:visionmedia/express 2012-08-09 10:15:27 -07:00
TJ Holowaychuk 3923ec89f7 remove route-loading example
using vm for this is lame
2012-08-09 10:15:12 -07:00
TJ Holowaychuk fd8ca32ab2 Merge pull request #1273 from ritch/patch-1
Removed extraneous require('http')
2012-08-09 08:46:23 -07:00
Ritchie Martori ba2f66d765 Removed extraneous require('http') 2012-08-08 17:51:04 -07:00
TJ Holowaychuk 056c840a06 update connect dep 2012-08-07 09:10:40 -07:00
80 arquivos alterados com 1125 adições e 481 exclusões
+1
Ver Arquivo
@@ -16,3 +16,4 @@ testing
.coverage_data
cover_html
test.js
.idea
+78
Ver Arquivo
@@ -1,4 +1,82 @@
3.0.5 / 2012-12-19
==================
* add throwing when a non-function is passed to a route
* fix: explicitly remove Transfer-Encoding header from 204 and 304 responses
* revert "add 'etag' option"
3.0.4 / 2012-12-05
==================
* add 'etag' option to disable `res.send()` Etags
* add escaping of urls in text/plain in `res.redirect()`
for old browsers interpreting as html
* change crc32 module for a more liberal license
* update connect
3.0.3 / 2012-11-13
==================
* update connect
* update cookie module
* fix cookie max-age
3.0.2 / 2012-11-08
==================
* add OPTIONS to cors example. Closes #1398
* fix route chaining regression. Closes #1397
3.0.1 / 2012-11-01
==================
* update connect
3.0.0 / 2012-10-23
==================
* add `make clean`
* add "Basic" check to req.auth
* add `req.auth` test coverage
* add cb && cb(payload) to `res.jsonp()`. Closes #1374
* add backwards compat for `res.redirect()` status. Closes #1336
* add support for `res.json()` to retain previously defined Content-Types. Closes #1349
* update connect
* change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382
* remove non-primitive string support for `res.send()`
* fix view-locals example. Closes #1370
* fix route-separation example
3.0.0rc5 / 2012-09-18
==================
* update connect
* add redis search example
* add static-files example
* add "x-powered-by" setting (`app.disable('x-powered-by')`)
* add "application/octet-stream" redirect Accept test case. Closes #1317
3.0.0rc4 / 2012-08-30
==================
* add `res.jsonp()`. Closes #1307
* add "verbose errors" option to error-pages example
* add another route example to express(1) so people are not so confused
* add redis online user activity tracking example
* update connect dep
* fix etag quoting. Closes #1310
* fix error-pages 404 status
* fix jsonp callback char restrictions
* remove old OPTIONS default response
3.0.0rc3 / 2012-08-13
==================
* update connect dep
* fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds]
* fix `res.render()` clobbering of "locals"
3.0.0rc2 / 2012-08-03
==================
+5 -1
Ver Arquivo
@@ -26,4 +26,8 @@ lib-cov:
benchmark:
@./support/bench
.PHONY: test test-unit test-acceptance benchmark
clean:
rm -f coverage.html
rm -fr lib-cov
.PHONY: test test-unit test-acceptance benchmark clean
+4 -8
Ver Arquivo
@@ -1,4 +1,3 @@
![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). [![Build Status](https://secure.travis-ci.org/visionmedia/express.png)](http://travis-ci.org/visionmedia/express)
@@ -18,10 +17,6 @@ app.listen(3000);
$ npm install -g express
To install the 3.0 alpha:
$ npm install -g express@3.0
## Quick Start
The quickest way to get started with express is to utilize the executable `express(1)` to generate an application as shown below:
@@ -74,8 +69,9 @@ app.listen(3000);
## Viewing Examples
First install the dev dependencies to install all the example / test suite deps:
Clone the Express repo, then install the dev dependencies to install all the example / test suite deps:
$ git clone git://github.com/visionmedia/express.git --depth 1
$ cd express
$ npm install
@@ -107,7 +103,7 @@ authors:
54 Aaron Heckmann 1.5%
34 csausdev 1.0%
26 ciaranj 0.7%
21 Robert Sköld 0.6%
21 Robert Sköld 0.6%
6 Guillermo Rauch 0.2%
3 Dav Glass 0.1%
3 Nick Poulden 0.1%
@@ -153,7 +149,7 @@ authors:
1 Jonathan Zacsh 0.0%
1 Justin Lilly 0.0%
1 Ken Sato 0.0%
1 Maciej Małecki 0.0%
1 Maciej Małecki 0.0%
1 Masahiro Hayashi 0.0%
```
+18
Ver Arquivo
@@ -54,6 +54,21 @@ var index = [
, '};'
].join(eol);
/**
* Routes users template.
*/
var users = [
''
, '/*'
, ' * GET users listing.'
, ' */'
, ''
, 'exports.list = function(req, res){'
, ' res.send("respond with a resource");'
, '};'
].join(eol);
/**
* Jade layout template.
*/
@@ -195,6 +210,7 @@ var app = [
, ''
, 'var express = require(\'express\')'
, ' , routes = require(\'./routes\')'
, ' , user = require(\'./routes/user\')'
, ' , http = require(\'http\')'
, ' , path = require(\'path\');'
, ''
@@ -217,6 +233,7 @@ var app = [
, '});'
, ''
, 'app.get(\'/\', routes.index);'
, 'app.get(\'/users\', user.list);'
, ''
, 'http.createServer(app).listen(app.get(\'port\'), function(){'
, ' console.log("Express server listening on port " + app.get(\'port\'));'
@@ -280,6 +297,7 @@ function createApplicationAt(path) {
mkdir(path + '/routes', function(){
write(path + '/routes/index.js', index);
write(path + '/routes/user.js', users);
});
mkdir(path + '/views', function(){
+7 -9
Ver Arquivo
@@ -1,9 +1,8 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
var express = require('../..')
, hash = require('./pass').hash;
var app = module.exports = express();
@@ -50,6 +49,7 @@ hash('foobar', function(err, salt, hash){
// Authenticate using our plain-object database of doom!
function authenticate(name, pass, fn) {
if (!module.parent) console.log('authenticating %s:%s', name, pass);
var user = users[name];
@@ -79,7 +79,7 @@ app.get('/', function(req, res){
});
app.get('/restricted', restrict, function(req, res){
res.send('Wahoo! restricted area');
res.send('Wahoo! restricted area, click to <a href="/logout">logout</a>');
});
app.get('/logout', function(req, res){
@@ -91,11 +91,6 @@ app.get('/logout', function(req, res){
});
app.get('/login', function(req, res){
if (req.session.user) {
req.session.success = 'Authenticated as ' + req.session.user.name
+ ' click to <a href="/logout">logout</a>. '
+ ' You may now access <a href="/restricted">/restricted</a>.';
}
res.render('login');
});
@@ -109,6 +104,9 @@ app.post('/login', function(req, res){
// in the session store to be retrieved,
// or in this case the entire user object
req.session.user = user;
req.session.success = 'Authenticated as ' + user.name
+ ' click to <a href="/logout">logout</a>. '
+ ' You may now access <a href="/restricted">/restricted</a>.';
res.redirect('back');
});
} else {
@@ -123,4 +121,4 @@ app.post('/login', function(req, res){
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
}
+2
Ver Arquivo
@@ -0,0 +1,2 @@
</body>
</html>
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Authentication Example</title>
<title><%= title %></title>
<style>
body {
padding: 50px;
@@ -16,6 +16,3 @@
</style>
</head>
<body>
<%- body %>
</body>
</html>
+7 -1
Ver Arquivo
@@ -1,3 +1,7 @@
<% var title = 'Authentication Example' %>
<% include head %>
<h1>Login</h1>
<%- message %>
Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj" and "foobar".
@@ -13,4 +17,6 @@ Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj"
<p>
<input type="submit" value="Login">
</p>
</form>
</form>
<% include foot %>
+2 -1
Ver Arquivo
@@ -1,4 +1,3 @@
/**
* Module dependencies.
*/
@@ -21,11 +20,13 @@ api.use(express.bodyParser());
*/
api.all('*', function(req, res, next){
if (!req.get('Origin')) return next();
// use "*" here to accept any origin
res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
res.set('Access-Control-Allow-Methods', 'GET, POST');
res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
// res.set('Access-Control-Allow-Max-Age', 3600);
if ('OPTIONS' == req.method) return res.send(200);
next();
});
+9 -5
Ver Arquivo
@@ -31,16 +31,20 @@ 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' }
{ 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 });
res.render('users', {
users: users,
title: "EJS example",
header: "Some users"
});
});
if (!module.parent) {
app.listen(3000);
console.log('Express app started on port 3000');
}
}
+2
Ver Arquivo
@@ -0,0 +1,2 @@
</body>
</html>
+13
Ver Arquivo
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> <%= title %> </title>
<style type="text/css">
body {
padding: 50px;
font: 13px Helvetica, Arial, sans-serif;
}
</style>
</head>
<body>
+6 -2
Ver Arquivo
@@ -1,6 +1,10 @@
<% include header.html %>
<h1>Users</h1>
<ul id="users">
<% users.forEach(function(user){ %>
<li><%= user.name %> <%= user.email %></li>
<li><%= user.name %> &lt;<%= user.email %>&gt;</li>
<% }) %>
</ul>
</ul>
<% include footer.html %>
+19 -2
Ver Arquivo
@@ -1,4 +1,3 @@
/**
* Module dependencies.
*/
@@ -7,9 +6,21 @@ var express = require('../../')
, app = module.exports = express()
, silent = 'test' == process.env.NODE_ENV;
// general config
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
// our custom "verbose errors" setting
// which we can use in the templates
// via settings['verbose errors']
app.enable('verbose errors');
// disable them in production
// use $ NODE_ENV=production node examples/error-pages
if ('production' == app.settings.env) {
app.disable('verbose errors');
}
app.use(express.favicon());
silent || app.use(express.logger('dev'));
@@ -32,9 +43,10 @@ app.use(app.router);
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"
app.use(function(req, res, next){
res.status(404);
// respond with html page
if (req.accepts('html')) {
res.status(404);
res.render('404', { url: req.url });
return;
}
@@ -76,16 +88,21 @@ app.get('/', function(req, res){
});
app.get('/404', function(req, res, next){
// trigger a 404 since no other middleware
// will match /404 after this one, and we're not
// responding here
next();
});
app.get('/403', function(req, res, next){
// trigger a 403 error
var err = new Error('not allowed!');
err.status = 403;
next(err);
});
app.get('/500', function(req, res, next){
// trigger a generic (500) error
next(new Error('keyboard cat!'));
});
+4 -1
Ver Arquivo
@@ -7,4 +7,7 @@ extends error
block content
h1 Error: #{error.message}
pre= error.stack
if settings['verbose errors']
pre= error.stack
else
p An error ocurred!
+2 -2
Ver Arquivo
@@ -8,8 +8,8 @@ block content
| visit
a(href="/500") 500
li
| visit
| visit
a(href="/404") 404
li
| visit
| visit
a(href='/403') 403
+2 -1
Ver Arquivo
@@ -1,3 +1,4 @@
body {
padding: 50px 80px;
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;}
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;
}
@@ -3,7 +3,7 @@
* Module dependencies.
*/
var express = require('../../')
var express = require('../..')
, format = require('util').format;
var app = module.exports = express()
+54
Ver Arquivo
@@ -0,0 +1,54 @@
// first:
// $ npm install redis online
// $ redis-server
/**
* Module dependencies.
*/
var express = require('../..')
, online = require('online')
, redis = require('redis')
, db = redis.createClient();
// online
online = online(db);
// app
var app = express();
// activity tracking, in this case using
// the UA string, you would use req.user.id etc
app.use(function(req, res, next){
// fire-and-forget
online.add(req.headers['user-agent']);
next();
});
/**
* List helper.
*/
function list(ids) {
return '<ul>' + ids.map(function(id){
return '<li>' + id + '</li>';
}).join('') + '</ul>';
}
/**
* GET users online.
*/
app.get('/', function(req, res, next){
online.last(5, function(err, ids){
if (err) return next(err);
res.send('<p>Users online: ' + ids.length + '</p>' + list(ids));
});
});
app.listen(3000);
console.log('listening 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);
});
};
-20
Ver Arquivo
@@ -1,20 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express')
, app = express()
, 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');
-4
Ver Arquivo
@@ -1,4 +0,0 @@
app.get('/', function(req, res){
res.render('index');
});
-18
Ver Arquivo
@@ -1,18 +0,0 @@
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('/users');
});
app.get('/user/:id', function(req, res){
res.render('user');
});
-8
Ver Arquivo
@@ -1,8 +0,0 @@
extends layout
block content
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
block content
-9
Ver Arquivo
@@ -1,9 +0,0 @@
extends ../layout
block content
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')
-10
Ver Arquivo
@@ -1,10 +0,0 @@
extends ../layout
block content
h1= user.name
table
tbody
tr
td Email
td= user.email
-10
Ver Arquivo
@@ -1,10 +0,0 @@
extends ../layout
block content
h1 Users
if users.length
for user in users
include index
else
p No users, head over to <a href='/user/add'>/user/add</a> to create one.
+4 -2
Ver Arquivo
@@ -11,9 +11,11 @@ var express = require('../..')
// Config
app.set('view engine', 'ejs');
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
@@ -35,4 +37,4 @@ app.put('/user/:id/edit', user.update);
app.get('/posts', post.list);
app.listen(3000);
console.log('Express app started on port 3000');
console.log('Express app started on port 3000');
+3 -3
Ver Arquivo
@@ -2,9 +2,9 @@
// Fake posts database
var posts = [
{ title: 'Foo', body: 'some foo bar' }
, { title: 'Foo bar', body: 'more foo bar' }
, { title: 'Foo bar baz', body: 'more foo bar baz' }
{ title: 'Foo', body: 'some foo bar' },
{ title: 'Foo bar', body: 'more foo bar' },
{ title: 'Foo bar baz', body: 'more foo bar baz' }
];
exports.list = function(req, res){
+2 -2
Ver Arquivo
@@ -11,10 +11,10 @@ a.edit {
opacity: .3;
}
a.edit::before {
content: '[ ';
content: ' [';
}
a.edit::after {
content: ' ]';
content: ']';
}
dt {
font-weight: bold;
+6 -6
Ver Arquivo
@@ -2,8 +2,8 @@
// Fake user database
var users = [
{ name: 'TJ', email: 'tj@vision-media.ca' }
, { name: 'Tobi', email: 'tobi@vision-media.ca' }
{ name: 'TJ', email: 'tj@vision-media.ca' },
{ name: 'Tobi', email: 'tobi@vision-media.ca' }
];
exports.list = function(req, res){
@@ -22,15 +22,15 @@ exports.load = function(req, res, next){
exports.view = function(req, res){
res.render('users/view', {
title: 'Viewing user ' + req.user.name
, user: req.user
title: 'Viewing user ' + req.user.name,
user: req.user
});
};
exports.edit = function(req, res){
res.render('users/edit', {
title: 'Editing user ' + req.user.name
, user: req.user
title: 'Editing user ' + req.user.name,
user: req.user
});
};
-4
Ver Arquivo
@@ -1,4 +0,0 @@
<ul>
<li>Visit the <a href="/users">users</a> page</li>
<li>Visit the <a href="/posts">posts</a> page</li>
</ul>
+6
Ver Arquivo
@@ -0,0 +1,6 @@
extends layout
block content
ul
li Visit the <a href="/users">users</a> page
li Visit the <a href="/posts">posts</a> page
-9
Ver Arquivo
@@ -1,9 +0,0 @@
<html>
<head>
<title><%= title %></title>
<link href="/style.css" rel="stylesheet" />
</head>
<body>
<%- body %>
</body>
</html>
@@ -0,0 +1,6 @@
html
head
title= title
link(href="/style.css", rel="stylesheet")
body
block content
@@ -1,7 +0,0 @@
<h1>Posts</h1>
<dl id="posts">
<% posts.forEach(function(post){ %>
<dt><%= post.title %></dt>
<dd><%= post.body %></dd>
<% }) %>
</dl>
@@ -0,0 +1,8 @@
extends ../layout
block content
h1 Posts
dl#posts
for post in posts
dt= post.title
dd= post.body
@@ -1,9 +0,0 @@
<h1>Editing <%= user.name %></h1>
<div id="user">
<form method="post">
<input type="hidden" value="put" name="_method" />
<p>Name: <input type="text" value="<%= user.name %>" name="user[name]"/></p>
<p>Email: <input type="text" value="<%= user.email %>" name="user[email]"/></p>
<p><input type="submit" value="Save" /></p>
</form>
</div>
@@ -0,0 +1,13 @@
extends ../layout
block content
h1 Editing #{user.name}
#user
form(method="post")
input(type="hidden", value="put", name="_method")
p Name:
input(type="text", value= user.name, name="user[name]")
p Email:
input(type="text", value= user.email, name="user[email]")
p
input(type="submit", value="Save")
@@ -1,9 +0,0 @@
<h1>Users</h1>
<ul id="users">
<% users.forEach(function(user, id){ %>
<li>
<a href="/user/<%= id %>"><%= user.name %></a>
<a class="edit" href="/user/<%= id %>/edit">edit</a>
</li>
<% }) %>
</ul>
@@ -0,0 +1,9 @@
extends ../layout
block content
h1 Users
#users
for user, i in users
li
a(href="/user/#{i}")= user.name
a.edit(href="/user/#{i}/edit") edit
@@ -1,4 +0,0 @@
<h1><%= user.name %></h1>
<div id="user">
<p>Email: <%= user.email %></p>
</div>
@@ -0,0 +1,6 @@
extends ../layout
block content
h1= user.name
#user
p Email: #{user.email}
+14
Ver Arquivo
@@ -0,0 +1,14 @@
var search = document.querySelector('[type=search]');
var code = document.querySelector('pre');
search.addEventListener('keyup', function(){
var xhr = new XMLHttpRequest;
xhr.open('GET', '/search/' + search.value, true);
xhr.onreadystatechange = function(){
if (4 == xhr.readyState) {
code.textContent = xhr.responseText;
}
};
xhr.send();
}, false);
+61
Ver Arquivo
@@ -0,0 +1,61 @@
// first:
// $ npm install redis
// $ redis-server
/**
* Module dependencies.
*/
var express = require('../..')
, redis = require('redis')
, db = redis.createClient();
// npm install redis
var app = express();
app.set('view engine', 'jade');
app.set('views', __dirname);
// populate search
db.sadd('ferret', 'tobi');
db.sadd('ferret', 'loki');
db.sadd('ferret', 'jane');
db.sadd('cat', 'manny');
db.sadd('cat', 'luna');
/**
* GET the search page.
*/
app.get('/', function(req, res){
res.render('search');
});
/**
* GET search for :query.
*/
app.get('/search/:query?', function(req, res){
var query = req.params.query;
db.smembers(query, function(err, vals){
if (err) return res.send(500);
res.send(vals);
});
});
/**
* GET client javascript. Here we use sendfile()
* because serving __dirname with the static() middleware
* would also mean serving our server "index.js" and the "search.jade"
* template.
*/
app.get('/client.js', function(req, res){
res.sendfile(__dirname + '/client.js');
});
app.listen(3000);
console.log('app listening on port 3000');
+15
Ver Arquivo
@@ -0,0 +1,15 @@
!!! 5
html
head
title Search example
style
body {
font: 14px "Helvetica Neue", Helvetica;
padding: 50px;
}
body
h2 Search
p Try searching for "ferret" or "cat".
input(type='search')
pre
script(src='client.js')
+5 -1
Ver Arquivo
@@ -1,4 +1,8 @@
// first:
// $ npm install redis
// $ redis-server
var express = require('../..');
var app = express();
@@ -25,4 +29,4 @@ app.get('/', function(req, res){
});
app.listen(3000);
console.log('Express app started on port 3000');
console.log('Express app started on port 3000');
+44
Ver Arquivo
@@ -0,0 +1,44 @@
var express = require('../..');
var app = express();
// log requests
app.use(express.logger('dev'));
// express on its own has no notion
// of a "file". The express.static()
// middleware checks for a file matching
// the `req.path` within the directory
// that you pass it. In this case "GET /js/app.js"
// will look for "./public/js/app.js".
app.use(express.static(__dirname + '/public'));
// if you wanted to "prefix" you may use
// the mounting feature of Connect, for example
// "GET /static/js/app.js" instead of "GET /js/app.js".
// The mount-path "/static" is simply removed before
// passing control to the express.static() middleware,
// thus it serves the file correctly by ignoring "/static"
app.use('/static', express.static(__dirname + '/public'));
// if for some reason you want to serve files from
// several directories, you can use express.static()
// multiple times! Here we're passing "./public/css",
// this will allow "GET /style.css" instead of "GET /css/style.css":
app.use(express.static(__dirname + '/public/css'));
// this examples does not have any routes, however
// you may `app.use(app.router)` before or after these
// static() middleware. If placed before them your routes
// will be matched BEFORE file serving takes place. If placed
// after as shown here then file serving is performed BEFORE
// any routes are hit:
app.use(app.router);
app.listen(3000);
console.log('listening on port 3000');
console.log('try:');
console.log(' GET /hello.txt');
console.log(' GET /js/app.js');
console.log(' GET /css/style.css');
+3
Ver Arquivo
@@ -0,0 +1,3 @@
body {
}
+1
Ver Arquivo
@@ -0,0 +1 @@
hey
+1
Ver Arquivo
@@ -0,0 +1 @@
foo
-5
Ver Arquivo
@@ -101,11 +101,6 @@ app.get('/middleware-locals', count2, users2, function(req, res, next){
res.render('user', { title: 'Users' });
});
app.get('/locals', function(req, res){
res.render('user', { title: 'Users' });
});
// keep in mind that middleware may be placed anywhere
// and in various combinations, so if you have locals
// that you wish to make available to all subsequent
+15 -19
Ver Arquivo
@@ -9,12 +9,10 @@ var connect = require('connect')
, debug = require('debug')('express:application')
, locals = require('./utils').locals
, View = require('./view')
, url = require('url')
, utils = connect.utils
, path = require('path')
, http = require('http')
, join = path.join
, fs = require('fs');
, join = path.join;
/**
* Application prototype.
@@ -33,7 +31,6 @@ var app = exports = module.exports = {};
*/
app.init = function(){
var self = this;
this.cache = {};
this.settings = {};
this.engines = {};
@@ -48,9 +45,8 @@ app.init = function(){
*/
app.defaultConfiguration = function(){
var self = this;
// default settings
this.enable('x-powered-by');
this.set('env', process.env.NODE_ENV || 'development');
debug('booting in %s mode', this.get('env'));
@@ -82,7 +78,7 @@ app.defaultConfiguration = function(){
this.locals.settings = this.settings;
// default configuration
this.enable('jsonp callback');
this.set('views', process.cwd() + '/views');
this.set('jsonp callback name', 'callback');
this.configure('development', function(){
@@ -105,7 +101,7 @@ app.defaultConfiguration = function(){
*/
app.use = function(route, fn){
var app, home, handle;
var app;
// default route to '/'
if ('string' != typeof route) fn = route, route = '/';
@@ -406,11 +402,12 @@ app.configure = function(env, fn){
methods.forEach(function(method){
app[method] = function(path){
if ('get' == method && 1 == arguments.length) return this.set(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);
}
this._router.route.apply(this._router, args);
return this;
};
});
/**
@@ -453,8 +450,7 @@ app.del = app.delete;
*/
app.render = function(name, options, fn){
var self = this
, opts = {}
var opts = {}
, cache = this.cache
, engines = this.engines
, view;
@@ -467,8 +463,8 @@ app.render = function(name, options, fn){
// merge app.locals
utils.merge(opts, this.locals);
// merge options.locals
if (options.locals) utils.merge(opts, options.locals);
// merge options._locals
if (options._locals) utils.merge(opts, options._locals);
// merge options
utils.merge(opts, options);
@@ -484,9 +480,9 @@ app.render = function(name, options, fn){
// view
if (!view) {
view = new View(name, {
defaultEngine: this.get('view engine')
, root: this.get('views') || process.cwd() + '/views'
, engines: engines
defaultEngine: this.get('view engine'),
root: this.get('views'),
engines: engines
});
if (!view.path) {
@@ -522,7 +518,7 @@ app.render = function(name, options, fn){
* , app = express();
*
* http.createServer(app).listen(80);
* http.createServer({ ... }, app).listen(443);
* https.createServer({ ... }, app).listen(443);
*
* @return {http.Server}
* @api public
+4 -7
Ver Arquivo
@@ -1,16 +1,13 @@
/**
* Module dependencies.
*/
var http = require('http')
, connect = require('connect')
var connect = require('connect')
, proto = require('./application')
, Route = require('./router/route')
, Router = require('./router')
, req = require('./request')
, res = require('./response')
, send = require('send')
, utils = connect.utils;
/**
@@ -23,13 +20,13 @@ exports = module.exports = createApplication;
* Framework version.
*/
exports.version = '3.0.0rc2';
exports.version = '3.0.5';
/**
* Expose mime.
*/
exports.mime = send.mime;
exports.mime = connect.mime;
/**
* Create an express application.
@@ -49,7 +46,7 @@ function createApplication() {
/**
* Expose connect.middleware as express.*
* for example `express.logger` etc.
* for example `express.logger` etc.
*/
for (var key in connect.middleware) {
+1 -1
Ver Arquivo
@@ -18,7 +18,7 @@ var utils = require('./utils');
exports.init = function(app){
return function expressInit(req, res, next){
req.app = res.app = app;
res.setHeader('X-Powered-By', 'Express');
if (app.settings['x-powered-by']) res.setHeader('X-Powered-By', 'Express');
req.res = res;
res.req = req;
req.next = next;
+6 -4
Ver Arquivo
@@ -377,18 +377,20 @@ req.__defineGetter__('ips', function(){
* req.auth
* // => { username: 'tobi', password: 'hello' }
*
* @return {Object}
* @return {Object} or undefined
* @api public
*/
req.__defineGetter__('auth', function(){
// missing
var auth = this.get('Authorization');
if (!auth) return {};
if (!auth) return;
// malformed
auth = auth.split(' ')[1];
if (!auth) return {};
var parts = auth.split(' ');
if ('basic' != parts[0].toLowerCase()) return;
if (!parts[1]) return;
auth = parts[1];
// credentials
auth = new Buffer(auth, 'base64').toString().split(':');
+70 -30
Ver Arquivo
@@ -2,18 +2,17 @@
* Module dependencies.
*/
var fs = require('fs')
, http = require('http')
var http = require('http')
, path = require('path')
, connect = require('connect')
, utils = connect.utils
, sign = require('cookie-signature').sign
, normalizeType = require('./utils').normalizeType
, normalizeTypes = require('./utils').normalizeTypes
, etag = require('./utils').etag
, statusCodes = http.STATUS_CODES
, send = connect.static.send
, cookie = require('cookie')
, send = require('send')
, crc = require('crc')
, mime = connect.mime
, basename = path.basename
, extname = path.extname
@@ -94,9 +93,6 @@ res.send = function(body){
}
}
// convert string objects to primitives
if (body instanceof String) body = body.toString();
switch (typeof body) {
// response status
case 'number':
@@ -133,9 +129,9 @@ res.send = function(body){
// ETag support
// TODO: W/ support
if (len > 1024) {
if (!this.get('ETag')) this.set('ETag', Buffer.isBuffer(body)
? crc.buffer.crc32(body)
: crc.crc32(body));
if (!this.get('ETag')) {
this.set('ETag', etag(body));
}
}
// freshness
@@ -145,6 +141,7 @@ res.send = function(body){
if (204 == this.statusCode || 304 == this.statusCode) {
this.removeHeader('Content-Type');
this.removeHeader('Content-Length');
this.removeHeader('Transfer-Encoding');
body = '';
}
@@ -182,21 +179,62 @@ res.json = function(obj){
}
// settings
var app = this.app
, jsonp = app.get('jsonp callback')
, replacer = app.get('json replacer')
, spaces = app.get('json spaces')
, body = JSON.stringify(obj, replacer, spaces)
, callback = this.req.query[app.get('jsonp callback name')];
var app = this.app;
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(obj, replacer, spaces);
// content-type
this.charset = this.charset || 'utf-8';
this.get('Content-Type') || this.set('Content-Type', 'application/json');
return this.send(body);
};
/**
* Send JSON response with JSONP callback support.
*
* Examples:
*
* res.jsonp(null);
* res.jsonp({ user: 'tj' });
* res.jsonp(500, 'oh noes!');
* res.jsonp(404, 'I dont have that');
*
* @param {Mixed} obj or status
* @param {Mixed} obj
* @return {ServerResponse}
* @api public
*/
res.jsonp = function(obj){
// allow status / body
if (2 == arguments.length) {
// res.json(body, status) backwards compat
if ('number' == typeof arguments[1]) {
this.statusCode = arguments[1];
} else {
this.statusCode = obj;
obj = arguments[1];
}
}
// settings
var app = this.app;
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(obj, replacer, spaces);
var callback = this.req.query[app.get('jsonp callback name')];
// content-type
this.charset = this.charset || 'utf-8';
this.set('Content-Type', 'application/json');
// jsonp
if (callback && jsonp) {
if (callback) {
this.set('Content-Type', 'text/javascript');
body = callback.replace(/[^[]\w$.]/g, '') + '(' + body + ');';
var cb = callback.replace(/[^\[\]\w$.]/g, '');
body = cb + ' && ' + cb + '(' + body + ');';
}
return this.send(body);
@@ -410,12 +448,12 @@ res.type = function(type){
*/
res.format = function(obj){
var keys = Object.keys(obj)
, req = this.req
var req = this.req
, next = req.next;
var fn = obj.default;
if (fn) delete obj.default;
var keys = Object.keys(obj);
var key = req.accepts(keys);
@@ -538,9 +576,10 @@ res.cookie = function(name, val, options){
var signed = options.signed;
if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies');
if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
if (signed) val = utils.sign(val, secret);
if (signed) val = 's:' + sign(val, secret);
if ('maxAge' in options) options.expires = new Date(Date.now() + options.maxAge);
if (null == options.path) options.path = '/';
options.maxAge /= 1000;
this.set('Set-Cookie', cookie.serialize(name, String(val), options));
return this;
};
@@ -558,6 +597,7 @@ res.cookie = function(name, val, options){
* res.redirect('/foo/bar');
* res.redirect('http://example.com');
* res.redirect(301, 'http://example.com');
* res.redirect('http://example.com', 301);
* res.redirect('../login'); // /blog/post/1 -> /blog/login
*
* Mounting:
@@ -587,8 +627,12 @@ res.redirect = function(url){
// allow status / url
if (2 == arguments.length) {
status = url;
url = arguments[1];
if ('number' == typeof url) {
status = url;
url = arguments[1];
} else {
status = arguments[1];
}
}
// setup redirect map
@@ -608,16 +652,12 @@ res.redirect = function(url){
} else if ('/' != url[0]) {
url = path + '/' + url;
}
// Absolute
var host = req.get('Host');
url = '//' + host + url;
}
// Support text/{plain,html} by default
this.format({
text: function(){
body = statusCodes[status] + '. Redirecting to ' + url;
body = statusCodes[status] + '. Redirecting to ' + encodeURI(url);
},
html: function(){
@@ -665,7 +705,7 @@ res.render = function(view, options, fn){
}
// merge res.locals
options.locals = self.locals;
options._locals = self.locals;
// default callback to respond
fn = fn || function(err, str){
@@ -675,4 +715,4 @@ res.render = function(view, options, fn){
// render
app.render(view, options, fn);
};
};
+12 -45
Ver Arquivo
@@ -5,8 +5,7 @@
var Route = require('./route')
, utils = require('../utils')
, debug = require('debug')('express:router')
, parse = require('connect').utils.parseUrl
, methods = require('methods');
, parse = require('connect').utils.parseUrl;
/**
* Expose `Router` constructor.
@@ -93,8 +92,7 @@ Router.prototype._dispatch = function(req, res, next){
, paramVal
, route
, keys
, key
, ret;
, key;
// match next route
function nextRoute(err) {
@@ -104,9 +102,6 @@ Router.prototype._dispatch = function(req, res, next){
// match route
req.route = route = self.matchRequest(req, i);
// implied OPTIONS
if (!route && 'OPTIONS' == req.method) return self._options(req, res);
// no route
if (!route) return next(err);
debug('matched %s %s', route.method, route.path);
@@ -162,7 +157,8 @@ Router.prototype._dispatch = function(req, res, next){
if (fn.length < 4) return callbacks(err);
fn(err, req, res, callbacks);
} else if (fn) {
fn(req, res, callbacks);
if (fn.length < 4) return fn(req, res, callbacks);
callbacks();
} else {
nextRoute(err);
}
@@ -173,41 +169,6 @@ Router.prototype._dispatch = function(req, res, next){
})(0);
};
/**
* Respond to __OPTIONS__ method.
*
* @param {IncomingMessage} req
* @param {ServerResponse} res
* @api private
*/
Router.prototype._options = function(req, res){
var path = parse(req).pathname
, body = this._optionsFor(path).join(',');
res.set('Allow', body).send(body);
};
/**
* Return an array of HTTP verbs or "options" for `path`.
*
* @param {String} path
* @return {Array}
* @api private
*/
Router.prototype._optionsFor = function(path){
var self = this;
return methods.filter(function(method){
var routes = self.map[method];
if (!routes || 'options' == method) return;
for (var i = 0, len = routes.length; i < len; ++i) {
if (routes[i].match(path)) return true;
}
}).map(function(method){
return method.toUpperCase();
});
};
/**
* Attempt to match a route for `req`
* with optional starting index of `i`
@@ -282,11 +243,17 @@ Router.prototype.route = function(method, path, callbacks){
// ensure path was given
if (!path) throw new Error('Router#' + method + '() requires a path');
// ensure all callbacks are functions
callbacks.forEach(function(fn){
if ('function' == typeof fn) return;
throw new Error('Router#' + method + '() requires all callbacks to be functions');
});
// create the route
debug('defined %s %s', method, path);
var route = new Route(method, path, callbacks, {
sensitive: this.caseSensitive
, strict: this.strict
sensitive: this.caseSensitive,
strict: this.strict
});
// add it
+14 -1
Ver Arquivo
@@ -3,7 +3,20 @@
* Module dependencies.
*/
var mime = require('connect').mime;
var mime = require('connect').mime
, crc32 = require('buffer-crc32');
/**
* Return ETag for `body`.
*
* @param {String|Buffer} body
* @return {String}
* @api private
*/
exports.etag = function(body){
return '"' + crc32.signed(body) + '"';
};
/**
* Make `locals()` bound to the given `obj`.
+8 -8
Ver Arquivo
@@ -1,24 +1,25 @@
{
"name": "express",
"description": "Sinatra inspired web development framework",
"version": "3.0.0rc2",
"version": "3.0.5",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
"contributors": [
{ "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" },
{ "name": "Aaron Heckmann", "email": "aaron.heckmann+github@gmail.com" },
{ "name": "Ciaran Jessup", "email": "ciaranj@gmail.com" },
{ "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }
],
"dependencies": {
"connect": "2.4.2",
"connect": "2.7.1",
"commander": "0.6.1",
"range-parser": "0.0.4",
"mkdirp": "0.3.3",
"cookie": "0.0.4",
"crc": "0.2.0",
"cookie": "0.0.5",
"buffer-crc32": "0.1.1",
"fresh": "0.1.0",
"methods": "0.0.1",
"send": "0.0.3",
"send": "0.1.0",
"cookie-signature": "0.0.1",
"debug": "*"
},
"devDependencies": {
@@ -43,7 +44,6 @@
"app",
"api"
],
"publishConfig": { "tag": "3.0" },
"repository": "git://github.com/visionmedia/express",
"main": "index",
"bin": { "express": "./bin/express" },
+1 -3
Ver Arquivo
@@ -16,8 +16,6 @@ app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.locals.self = true;
var repo = require('../package.json');
app.get('/render', function(req, res){
res.render('hello');
});
@@ -65,4 +63,4 @@ app.get('/match', function(req, res){
res.send('Hello World\n');
});
app.listen(8000);
app.listen(8000);
+25 -1
Ver Arquivo
@@ -76,4 +76,28 @@ describe('Router', function(){
.expect('foo', done);
})
})
})
describe('.multiple callbacks', function(){
it('should throw if a callback is null', function(){
assert.throws(function () {
router.route('get', '/foo', null, function(){});
})
})
it('should throw if a callback is undefined', function(){
assert.throws(function () {
router.route('get', '/foo', undefined, function(){});
})
})
it('should throw if a callback is not a function', function(){
assert.throws(function () {
router.route('get', '/foo', 'not a function', function(){});
})
})
it('should not throw if all callbacks are functions', function(){
router.route('get', '/foo', function(){}, function(){});
})
})
})
+3 -3
Ver Arquivo
@@ -10,9 +10,9 @@ describe('ejs', function(){
.end(function(err, res){
res.should.have.status(200);
res.should.have.header('Content-Type', 'text/html; charset=utf-8');
res.text.should.include('<li>tobi tobi@learnboost.com</li>');
res.text.should.include('<li>loki loki@learnboost.com</li>');
res.text.should.include('<li>jane jane@learnboost.com</li>');
res.text.should.include('<li>tobi &lt;tobi@learnboost.com&gt;</li>');
res.text.should.include('<li>loki &lt;loki@learnboost.com&gt;</li>');
res.text.should.include('<li>jane &lt;jane@learnboost.com&gt;</li>');
done();
});
})
+1 -1
Ver Arquivo
@@ -85,7 +85,7 @@ describe('error-pages', function(){
request(app)
.get('/404')
.set('Accept', 'text/plain')
.expect(200)
.expect(404)
.expect('Not found', done);
})
})
+2
Ver Arquivo
@@ -57,8 +57,10 @@ describe('app.path()', function(){
describe('in development', function(){
it('should disable "view cache"', function(){
process.env.NODE_ENV = 'development';
var app = express();
app.enabled('view cache').should.be.false;
process.env.NODE_ENV = 'test';
})
})
-37
Ver Arquivo
@@ -1,37 +0,0 @@
var express = require('../')
, request = require('./support/http');
describe('OPTIONS', function(){
it('should default to the routes defined', function(done){
var app = express();
app.del('/', function(){});
app.get('/users', function(req, res){});
app.put('/users', function(req, res){});
request(app)
.options('/users')
.expect('GET,PUT')
.expect('Allow', 'GET,PUT', done);
})
})
describe('app.options()', function(){
it('should override the default behavior', function(done){
var app = express();
app.options('/users', function(req, res){
res.set('Allow', 'GET');
res.send('GET');
});
app.get('/users', function(req, res){});
app.put('/users', function(req, res){});
request(app)
.options('/users')
.expect('GET')
.expect('Allow', 'GET', done);
})
})
+5
Ver Arquivo
@@ -596,4 +596,9 @@ describe('app.router', function(){
.get('/account/edit')
.expect('editing user 12', done);
})
it('should be chainable', function(){
var app = express();
app.get('/', function(){}).should.equal(app);
})
})
+43
Ver Arquivo
@@ -0,0 +1,43 @@
var express = require('../')
, request = require('./support/http');
describe('app', function(){
describe('.VERB()', function(){
it('should only call an error handling routing callback when an error is propagated', function(done){
var app = express();
var a = false;
var b = false;
var c = false;
var d = false;
app.get('/', function(req, res, next){
next(new Error('fabricated error'));
}, function(req, res, next) {
a = true;
next();
}, function(err, req, res, next){
b = true;
err.message.should.equal('fabricated error');
next(err);
}, function(err, req, res, next){
c = true;
err.message.should.equal('fabricated error');
next();
}, function(err, req, res, next){
d = true;
next();
}, function(req, res){
a.should.be.false;
b.should.be.true;
c.should.be.true;
d.should.be.false;
res.send(204);
});
request(app)
.get('/')
.expect(204, done);
})
})
})
+3 -2
Ver Arquivo
@@ -1,6 +1,7 @@
var express = require('../')
, request = require('./support/http');
, request = require('./support/http')
, assert = require('assert');
describe('exports', function(){
it('should have .version', function(){
@@ -14,7 +15,7 @@ describe('exports', function(){
})
it('should expose .mime', function(){
express.mime.should.equal(require('connect').mime);
assert(express.mime == require('connect').mime, 'express.mime should be connect.mime');
})
it('should expose Router', function(){
+64
Ver Arquivo
@@ -0,0 +1,64 @@
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.auth', function(){
describe('when Authorization is missing', function(){
it('should return undefined', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.expect('none', done)
})
})
describe('when Authorization is malformed', function(){
it('should return undefined', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.set('Authorization', 'meow')
.expect('none', done)
})
})
describe('when Authorization is not Basic', function(){
it('should return undefined', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.set('Authorization', 'Meow dG9iaTpmZXJyZXQ')
.expect('none', done)
})
})
it('should return .username and .password', function(done){
var app = express();
app.get('/', function(req, res){
res.send(req.auth || 'none');
});
request(app)
.get('/')
.set('Authorization', 'Basic dG9iaTpmZXJyZXQ=')
.expect('{"username":"tobi","password":"ferret"}', done)
})
})
})
+52
Ver Arquivo
@@ -0,0 +1,52 @@
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.signedCookies', function(){
it('should return a signed JSON cookie', function(done){
var app = express()
, cookieHeader
, val;
app.use(express.cookieParser('secret'));
app.use(function(req, res){
res.send(req.signedCookies);
});
app.response.req = { secret: 'secret' };
app.response.cookie('obj', { foo: 'bar' }, { signed: true });
cookieHeader = app.response.get('set-cookie');
val = JSON.stringify({ obj: { foo: 'bar' } });
request(app)
.get('/')
.set('Cookie', cookieHeader)
.expect(val, done);
})
it('should return a signed cookie', function(done){
var app = express()
, cookieHeader
, val;
app.use(express.cookieParser('secret'));
app.use(function(req, res){
res.send(req.signedCookies);
});
app.response.req = { secret: 'secret' };
app.response.cookie('foo', 'bar', { signed: true });
cookieHeader = app.response.get('set-cookie');
val = JSON.stringify({ foo: 'bar' });
request(app)
.get('/')
.set('Cookie', cookieHeader)
.expect(val, done);
})
})
})
+18 -2
Ver Arquivo
@@ -92,6 +92,22 @@ describe('res', function(){
done();
})
})
it('should set max-age', function(done){
var app = express();
app.use(function(req, res){
res.cookie('name', 'tobi', { maxAge: 1000 });
res.end();
});
request(app)
.get('/')
.end(function(err, res){
res.headers['set-cookie'][0].should.include('Max-Age=1');
done();
})
})
})
describe('signed', function(){
@@ -109,7 +125,7 @@ describe('res', function(){
.end(function(err, res){
var val = res.headers['set-cookie'][0];
val = cookie.parse(val.split('.')[0]);
val.user.should.equal('j:{"name":"tobi"}');
val.user.should.equal('s:j:{"name":"tobi"}');
done();
})
})
@@ -128,7 +144,7 @@ describe('res', function(){
request(app)
.get('/')
.end(function(err, res){
var val = ['name=tobi.xJjV2iZ6EI7C8E5kzwbfA9PVLl1ZR07UTnuTgQQ4EnQ; Path=/'];
var val = ['name=s%3Atobi.xJjV2iZ6EI7C8E5kzwbfA9PVLl1ZR07UTnuTgQQ4EnQ; Path=/'];
res.headers['set-cookie'].should.eql(val);
done();
})
+26 -47
Ver Arquivo
@@ -5,55 +5,16 @@ var express = require('../')
describe('res', function(){
describe('.json(object)', function(){
describe('when "jsonp callback" is enabled', function(){
it('should respond with jsonp', function(done){
var app = express();
it('should not support jsonp callbacks', function(done){
var app = express();
app.use(function(req, res){
res.json({ count: 1 });
});
app.use(function(req, res){
res.json({ foo: 'bar' });
});
request(app)
.get('/?callback=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something({"count":1});');
done();
})
})
it('should allow renaming callback', function(done){
var app = express();
app.set('jsonp callback name', 'clb');
app.use(function(req, res){
res.json({ count: 1 });
});
request(app)
.get('/?clb=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something({"count":1});');
done();
})
})
it('should allow []', function(done){
var app = express();
app.use(function(req, res){
res.json({ count: 1 });
});
request(app)
.get('/?callback=callbacks[123]')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('callbacks[123]({"count":1});');
done();
})
})
request(app)
.get('/?callback=foo')
.expect('{"foo":"bar"}', done);
})
describe('when given primitives', function(){
@@ -202,4 +163,22 @@ describe('res', function(){
})
})
})
it('should not override previous Content-Types', function(done){
var app = express();
app.get('/', function(req, res){
res.type('application/vnd.example+json');
res.json({ hello: 'world' });
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(200);
res.headers.should.have.property('content-type', 'application/vnd.example+json');
res.text.should.equal('{"hello":"world"}');
done();
})
})
})
+220
Ver Arquivo
@@ -0,0 +1,220 @@
var express = require('../')
, request = require('./support/http')
, assert = require('assert');
describe('res', function(){
describe('.jsonp(object)', function(){
it('should respond with jsonp', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ count: 1 });
});
request(app)
.get('/?callback=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something && something({"count":1});');
done();
})
})
it('should allow renaming callback', function(done){
var app = express();
app.set('jsonp callback name', 'clb');
app.use(function(req, res){
res.jsonp({ count: 1 });
});
request(app)
.get('/?clb=something')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('something && something({"count":1});');
done();
})
})
it('should allow []', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ count: 1 });
});
request(app)
.get('/?callback=callbacks[123]')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('callbacks[123] && callbacks[123]({"count":1});');
done();
})
})
it('should disallow arbitrary js', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({});
});
request(app)
.get('/?callback=foo;bar()')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8');
res.text.should.equal('foobar && foobar({});');
done();
})
})
describe('when given primitives', function(){
it('should respond with json', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(null);
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('null');
done();
})
})
})
describe('when given an array', function(){
it('should respond with json', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(['foo', 'bar', 'baz']);
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('["foo","bar","baz"]');
done();
})
})
})
describe('when given an object', function(){
it('should respond with json', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ name: 'tobi' });
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('{"name":"tobi"}');
done();
})
})
})
describe('"json replacer" setting', function(){
it('should be passed to JSON.stringify()', function(done){
var app = express();
app.set('json replacer', function(key, val){
return '_' == key[0]
? undefined
: val;
});
app.use(function(req, res){
res.jsonp({ name: 'tobi', _id: 12345 });
});
request(app)
.get('/')
.end(function(err, res){
res.text.should.equal('{"name":"tobi"}');
done();
});
})
})
describe('"json spaces" setting', function(){
it('should default to 2 in development', function(){
process.env.NODE_ENV = 'development';
var app = express();
app.get('json spaces').should.equal(2);
process.env.NODE_ENV = 'test';
})
it('should be undefined otherwise', function(){
var app = express();
assert(undefined === app.get('json spaces'));
})
it('should be passed to JSON.stringify()', function(done){
var app = express();
app.set('json spaces', 2);
app.use(function(req, res){
res.jsonp({ name: 'tobi', age: 2 });
});
request(app)
.get('/')
.end(function(err, res){
res.text.should.equal('{\n "name": "tobi",\n "age": 2\n}');
done();
});
})
})
})
describe('.json(status, object)', function(){
it('should respond with json and set the .statusCode', function(done){
var app = express();
app.use(function(req, res){
res.jsonp(201, { id: 1 });
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(201);
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('{"id":1}');
done();
})
})
})
describe('.json(object, status)', function(){
it('should respond with json and set the .statusCode for backwards compat', function(done){
var app = express();
app.use(function(req, res){
res.jsonp({ id: 1 }, 201);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(201);
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
res.text.should.equal('{"id":1}');
done();
})
})
})
})
+45 -10
Ver Arquivo
@@ -51,7 +51,7 @@ describe('res', function(){
.get('/')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//example.com/login');
res.headers.should.have.property('location', '/login');
done();
})
})
@@ -69,7 +69,7 @@ describe('res', function(){
.get('/post/1')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//example.com/post/1/./edit');
res.headers.should.have.property('location', '/post/1/./edit');
done();
})
})
@@ -87,7 +87,7 @@ describe('res', function(){
.get('/post/1')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//example.com/post/1/../new');
res.headers.should.have.property('location', '/post/1/../new');
done();
})
})
@@ -105,7 +105,7 @@ describe('res', function(){
.get('/')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//example.com/login');
res.headers.should.have.property('location', '/login');
done();
})
})
@@ -129,7 +129,7 @@ describe('res', function(){
.get('/blog/admin')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//example.com/blog/admin/login');
res.headers.should.have.property('location', '/blog/admin/login');
done();
})
})
@@ -150,7 +150,7 @@ describe('res', function(){
.get('/blog')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//example.com/blog/admin/login');
res.headers.should.have.property('location', '/blog/admin/login');
done();
})
})
@@ -171,7 +171,7 @@ describe('res', function(){
.get('/blog')
.set('Host', 'example.com')
.end(function(err, res){
res.headers.should.have.property('location', '//example.com/admin/login');
res.headers.should.have.property('location', '/admin/login');
done();
})
})
@@ -196,7 +196,25 @@ describe('res', function(){
})
})
})
describe('.redirect(url, status)', function(){
it('should set the response status', function(done){
var app = express();
app.use(function(req, res){
res.redirect('http://google.com', 303);
});
request(app)
.get('/')
.end(function(err, res){
res.statusCode.should.equal(303);
res.headers.should.have.property('location', 'http://google.com');
done();
})
})
})
describe('when the request method is HEAD', function(){
it('should ignore the body', function(done){
var app = express();
@@ -245,7 +263,7 @@ describe('res', function(){
.set('Host', 'http://example.com')
.set('Accept', 'text/html')
.end(function(err, res){
res.text.should.equal('<p>Moved Temporarily. Redirecting to <a href="//http://example.com/&lt;lame&gt;">//http://example.com/&lt;lame&gt;</a></p>');
res.text.should.equal('<p>Moved Temporarily. Redirecting to <a href="/&lt;lame&gt;">/&lt;lame&gt;</a></p>');
done();
})
})
@@ -269,6 +287,23 @@ describe('res', function(){
done();
})
})
it('should encode the url', function(done){
var app = express();
app.use(function(req, res){
res.redirect('http://example.com/?param=<script>alert("hax");</script>');
});
request(app)
.get('/')
.set('Host', 'http://example.com')
.set('Accept', 'text/plain, */*')
.end(function(err, res){
res.text.should.equal('Moved Temporarily. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E');
done();
})
})
})
describe('when accepting neither text or html', function(){
@@ -281,7 +316,7 @@ describe('res', function(){
request(app)
.get('/')
.set('Accept', 'foo/bar')
.set('Accept', 'application/octet-stream')
.end(function(err, res){
res.should.have.status(302);
res.headers.should.have.property('location', 'http://google.com');
+2 -2
Ver Arquivo
@@ -125,7 +125,7 @@ describe('res', function(){
app.locals.user = { name: 'tobi' };
app.use(function(req, res){
res.render('user.jade', {});
res.render('user.jade');
});
request(app)
@@ -140,7 +140,7 @@ describe('res', function(){
app.use(function(req, res){
res.locals.user = { name: 'tobi' };
res.render('user.jade', {});
res.render('user.jade');
});
request(app)
+21 -43
Ver Arquivo
@@ -104,7 +104,7 @@ describe('res', function(){
request(app)
.get('/')
.expect('ETag', '-1498647312')
.expect('ETag', '"-1498647312"')
.end(done);
})
@@ -123,42 +123,6 @@ describe('res', function(){
})
})
describe('.send(StringObj)', function(){
it('should send as html', function(done){
var app = express();
app.use(function(req, res){
res.send(new String('<p>hey</p>'));
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/html; charset=utf-8');
res.text.should.equal('<p>hey</p>');
res.statusCode.should.equal(200);
done();
})
})
it('should not override Content-Type', function(done){
var app = express();
app.use(function(req, res){
res.set('Content-Type', 'text/plain').send(new String('hey'));
});
request(app)
.get('/')
.end(function(err, res){
res.headers.should.have.property('content-type', 'text/plain');
res.text.should.equal('hey');
res.statusCode.should.equal(200);
done();
})
})
})
describe('.send(Buffer)', function(){
it('should send as octet-stream', function(done){
var app = express();
@@ -187,7 +151,7 @@ describe('res', function(){
request(app)
.get('/')
.expect('ETag', '-1498647312')
.expect('ETag', '"-1498647312"')
.end(done);
})
@@ -242,11 +206,11 @@ describe('res', function(){
})
describe('when .statusCode is 204', function(){
it('should strip Content-* fields & body', function(done){
it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
var app = express();
app.use(function(req, res){
res.status(204).send('foo');
res.status(204).set('Transfer-Encoding', 'chunked').send('foo');
});
request(app)
@@ -254,6 +218,7 @@ describe('res', function(){
.end(function(err, res){
res.headers.should.not.have.property('content-type');
res.headers.should.not.have.property('content-length');
res.headers.should.not.have.property('transfer-encoding');
res.text.should.equal('');
done();
})
@@ -261,11 +226,11 @@ describe('res', function(){
})
describe('when .statusCode is 304', function(){
it('should strip Content-* fields & body', function(done){
it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){
var app = express();
app.use(function(req, res){
res.status(304).send('foo');
res.status(304).set('Transfer-Encoding', 'chunked').send('foo');
});
request(app)
@@ -273,6 +238,7 @@ describe('res', function(){
.end(function(err, res){
res.headers.should.not.have.property('content-type');
res.headers.should.not.have.property('content-length');
res.headers.should.not.have.property('transfer-encoding');
res.text.should.equal('');
done();
})
@@ -303,7 +269,7 @@ describe('res', function(){
request(app)
.get('/')
.set('If-None-Match', '-1498647312')
.set('If-None-Match', '"-1498647312"')
.expect(304, done);
})
@@ -322,4 +288,16 @@ describe('res', function(){
.expect('hey')
.expect(500, done);
})
it('should not support jsonp callbacks', function(done){
var app = express();
app.use(function(req, res){
res.send({ foo: 'bar' });
});
request(app)
.get('/?callback=foo')
.expect('{"foo":"bar"}', done);
})
})
+20
Ver Arquivo
@@ -2,6 +2,26 @@
var utils = require('../lib/utils')
, assert = require('assert');
describe('utils.etag(body)', function(){
var str = 'Hello CRC';
var strUTF8 = '<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body><p>自動販売</p></body></html>';
it('should support strings', function(){
utils.etag(str).should.eql('"-2034458343"');
})
it('should support utf8 strings', function(){
utils.etag(strUTF8).should.eql('"1395090196"');
})
it('should support buffer', function(){
utils.etag(new Buffer(strUTF8)).should.eql('"1395090196"');
utils.etag(new Buffer(str)).should.eql('"-2034458343"');
})
})
describe('utils.isAbsolute()', function(){
it('should support windows', function(){
assert(utils.isAbsolute('c:\\'));