mirror of
https://github.com/expressjs/express.git
synced 2026-02-27 11:09:29 +00:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b91cd66fc5 | ||
|
|
787d630157 | ||
|
|
1f938c560a | ||
|
|
a96924a555 | ||
|
|
33dc6629ff | ||
|
|
1b3fb0af8c | ||
|
|
12da523ff7 | ||
|
|
0f49d80623 | ||
|
|
1717516a78 | ||
|
|
328c6d3060 | ||
|
|
566720be15 | ||
|
|
65f13c3cc6 | ||
|
|
d98e2e7498 | ||
|
|
f7be983a77 | ||
|
|
a2553126dd | ||
|
|
0639c45acd | ||
|
|
920f46ad65 | ||
|
|
35a66d8a14 | ||
|
|
4e1e252e17 | ||
|
|
0461e55380 | ||
|
|
8dc4ff26f9 | ||
|
|
6f9e927633 | ||
|
|
40a43eb753 | ||
|
|
a8bb4bab2b | ||
|
|
417999884b | ||
|
|
17a739e35f | ||
|
|
66b38b58bc | ||
|
|
dc31ea34b8 | ||
|
|
d58ca520c8 | ||
|
|
4b646c2f8d | ||
|
|
35757ed1f5 | ||
|
|
fed0d5df5c | ||
|
|
c99fa6a192 | ||
|
|
0d468cbe6c | ||
|
|
f92ba6d0cf | ||
|
|
0408e3727e | ||
|
|
d5815922ca | ||
|
|
972c01afc9 | ||
|
|
8894e30869 | ||
|
|
5d8dba5fe0 | ||
|
|
90fbc1a33e | ||
|
|
55dea47b94 | ||
|
|
c7791a207b | ||
|
|
30d18888b9 | ||
|
|
df50669092 | ||
|
|
abd6b7c5c3 | ||
|
|
87912103c9 | ||
|
|
4ce1ee458e | ||
|
|
8aff64f89a | ||
|
|
ff23423d34 | ||
|
|
1d97599f8b | ||
|
|
e465624fd0 | ||
|
|
dc5932d177 | ||
|
|
cfd93b7529 | ||
|
|
8b2208f394 | ||
|
|
00a3b01f39 | ||
|
|
3baca251f0 | ||
|
|
72daae1d92 | ||
|
|
fcbe53ddb5 | ||
|
|
e9851672eb | ||
|
|
9a45f7bd3d | ||
|
|
85834fd146 | ||
|
|
a0c1ac7b45 | ||
|
|
7b0dca0f9c | ||
|
|
34c83d7d29 | ||
|
|
7c6882234e | ||
|
|
2e68ddbae9 | ||
|
|
7724fc6af7 | ||
|
|
2939075f03 | ||
|
|
606f68de02 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,6 +1,5 @@
|
||||
coverage.html
|
||||
coverage/
|
||||
.DS_Store
|
||||
lib-cov
|
||||
*.seed
|
||||
*.log
|
||||
*.csv
|
||||
@@ -13,7 +12,5 @@ benchmarks/graphs
|
||||
testing
|
||||
node_modules/
|
||||
testing
|
||||
.coverage_data
|
||||
cover_html
|
||||
test.js
|
||||
.idea
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
.git*
|
||||
benchmarks/
|
||||
coverage/
|
||||
docs/
|
||||
examples/
|
||||
support/
|
||||
test/
|
||||
testing.js
|
||||
.DS_Store
|
||||
coverage.html
|
||||
lib-cov
|
||||
.travis.yml
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.8"
|
||||
- "0.10"
|
||||
- "0.10"
|
||||
- "0.11"
|
||||
matrix:
|
||||
allow_failures:
|
||||
- node_js: "0.11"
|
||||
fast_finish: true
|
||||
script: "npm run-script test-travis"
|
||||
|
||||
97
History.md
97
History.md
@@ -1,3 +1,100 @@
|
||||
3.7.0 / 2014-05-18
|
||||
==================
|
||||
|
||||
* proper proxy trust with `app.set('trust proxy', trust)`
|
||||
- `app.set('trust proxy', 1)` trust first hop
|
||||
- `app.set('trust proxy', 'loopback')` trust loopback addresses
|
||||
- `app.set('trust proxy', '10.0.0.1')` trust single IP
|
||||
- `app.set('trust proxy', '10.0.0.1/16')` trust subnet
|
||||
- `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list
|
||||
- `app.set('trust proxy', false)` turn off
|
||||
- `app.set('trust proxy', true)` trust everything
|
||||
* update connect to 2.16.2
|
||||
- deprecate `res.headerSent` -- use `res.headersSent`
|
||||
- deprecate `res.on("header")` -- use on-headers module instead
|
||||
- fix edge-case in `res.appendHeader` that would append in wrong order
|
||||
- json: use body-parser
|
||||
- urlencoded: use body-parser
|
||||
- dep: bytes@1.0.0
|
||||
- dep: cookie-parser@1.1.0
|
||||
- dep: csurf@1.2.0
|
||||
- dep: express-session@1.1.0
|
||||
- dep: method-override@1.0.1
|
||||
|
||||
3.6.0 / 2014-05-09
|
||||
==================
|
||||
|
||||
* deprecate `app.del()` -- use `app.delete()` instead
|
||||
* deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead
|
||||
- the edge-case `res.json(status, num)` requires `res.status(status).json(num)`
|
||||
* deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead
|
||||
- the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)`
|
||||
* support PURGE method
|
||||
- add `app.purge`
|
||||
- add `router.purge`
|
||||
- include PURGE in `app.all`
|
||||
* update connect to 2.15.0
|
||||
* Add `res.appendHeader`
|
||||
* Call error stack even when response has been sent
|
||||
* Patch `res.headerSent` to return Boolean
|
||||
* Patch `res.headersSent` for node.js 0.8
|
||||
* Prevent default 404 handler after response sent
|
||||
* dep: compression@1.0.2
|
||||
* dep: connect-timeout@1.1.0
|
||||
* dep: debug@^0.8.0
|
||||
* dep: errorhandler@1.0.1
|
||||
* dep: express-session@1.0.4
|
||||
* dep: morgan@1.0.1
|
||||
* dep: serve-favicon@2.0.0
|
||||
* dep: serve-index@1.0.2
|
||||
* update debug to 0.8.0
|
||||
* add `enable()` method
|
||||
* change from stderr to stdout
|
||||
* update methods to 1.0.0
|
||||
- add PURGE
|
||||
* update mkdirp to 0.5.0
|
||||
|
||||
3.5.3 / 2014-05-08
|
||||
==================
|
||||
|
||||
* fix `req.host` for IPv6 literals
|
||||
* fix `res.jsonp` error if callback param is object
|
||||
|
||||
3.5.2 / 2014-04-24
|
||||
==================
|
||||
|
||||
* update connect to 2.14.5
|
||||
* update cookie to 0.1.2
|
||||
* update mkdirp to 0.4.0
|
||||
* update send to 0.3.0
|
||||
|
||||
3.5.1 / 2014-03-25
|
||||
==================
|
||||
|
||||
* pin less-middleware in generated app
|
||||
|
||||
3.5.0 / 2014-03-06
|
||||
==================
|
||||
|
||||
* bump deps
|
||||
|
||||
3.4.8 / 2014-01-13
|
||||
==================
|
||||
|
||||
* prevent incorrect automatic OPTIONS responses #1868 @dpatti
|
||||
* update binary and examples for jade 1.0 #1876 @yossi, #1877 @reqshark, #1892 @matheusazzi
|
||||
* throw 400 in case of malformed paths @rlidwka
|
||||
|
||||
3.4.7 / 2013-12-10
|
||||
==================
|
||||
|
||||
* update connect
|
||||
|
||||
3.4.6 / 2013-12-01
|
||||
==================
|
||||
|
||||
* update connect (raw-body)
|
||||
|
||||
3.4.5 / 2013-11-27
|
||||
==================
|
||||
|
||||
|
||||
34
Makefile
34
Makefile
@@ -1,34 +0,0 @@
|
||||
|
||||
MOCHA_OPTS= --check-leaks
|
||||
REPORTER = dot
|
||||
|
||||
check: test
|
||||
|
||||
test: test-unit test-acceptance
|
||||
|
||||
test-unit:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
--reporter $(REPORTER) \
|
||||
--globals setImmediate,clearImmediate \
|
||||
$(MOCHA_OPTS)
|
||||
|
||||
test-acceptance:
|
||||
@NODE_ENV=test ./node_modules/.bin/mocha \
|
||||
--reporter $(REPORTER) \
|
||||
--bail \
|
||||
test/acceptance/*.js
|
||||
|
||||
test-cov: lib-cov
|
||||
@EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html
|
||||
|
||||
lib-cov:
|
||||
@jscoverage lib lib-cov
|
||||
|
||||
benchmark:
|
||||
@./support/bench
|
||||
|
||||
clean:
|
||||
rm -f coverage.html
|
||||
rm -fr lib-cov
|
||||
|
||||
.PHONY: test test-unit test-acceptance benchmark clean
|
||||
22
Readme.md
22
Readme.md
@@ -2,7 +2,7 @@
|
||||
|
||||
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
|
||||
|
||||
[](http://travis-ci.org/visionmedia/express) [](https://www.gittip.com/visionmedia/)
|
||||
[](http://badge.fury.io/js/express) [](https://travis-ci.org/visionmedia/express) [](https://coveralls.io/r/visionmedia/express) [](https://www.gittip.com/visionmedia/)
|
||||
|
||||
```js
|
||||
var express = require('express');
|
||||
@@ -50,14 +50,14 @@ app.listen(3000);
|
||||
|
||||
## Philosophy
|
||||
|
||||
The Express philosophy is to provide small, robust tooling for HTTP servers. Making
|
||||
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
|
||||
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](http://github.com/visionmedia/consolidate.js)
|
||||
14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js),
|
||||
you can quickly craft your perfect framework.
|
||||
|
||||
## More Information
|
||||
@@ -72,29 +72,31 @@ app.listen(3000);
|
||||
|
||||
## Viewing Examples
|
||||
|
||||
Clone the Express repo, then 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 dependencies:
|
||||
|
||||
$ git clone git://github.com/visionmedia/express.git --depth 1
|
||||
$ cd express
|
||||
$ npm install
|
||||
|
||||
then run whichever tests you want:
|
||||
Then run whichever tests you want:
|
||||
|
||||
$ node examples/content-negotiation
|
||||
|
||||
You can also view live examples here
|
||||
You can also view live examples here:
|
||||
|
||||
<a href="https://runnable.com/express" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png" style="width:67px;height:25px;"></a>
|
||||
|
||||
## Running Tests
|
||||
|
||||
To run the test suite first invoke the following command within the repo, installing the development dependencies:
|
||||
To run the test suite, first invoke the following command within the repo, installing the development dependencies:
|
||||
|
||||
$ npm install
|
||||
|
||||
then run the tests:
|
||||
Then run the tests:
|
||||
|
||||
$ make test
|
||||
```sh
|
||||
$ npm test
|
||||
```
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
13
benchmarks/Makefile
Normal file
13
benchmarks/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
all:
|
||||
@./run 1 middleware
|
||||
@./run 5 middleware
|
||||
@./run 10 middleware
|
||||
@./run 15 middleware
|
||||
@./run 20 middleware
|
||||
@./run 30 middleware
|
||||
@./run 50 middleware
|
||||
@./run 100 middleware
|
||||
@echo
|
||||
|
||||
.PHONY: all
|
||||
23
benchmarks/middleware.js
Normal file
23
benchmarks/middleware.js
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
var http = require('http');
|
||||
var express = require('..');
|
||||
var app = express();
|
||||
|
||||
// number of middleware
|
||||
|
||||
var n = parseInt(process.env.MW || '1', 10);
|
||||
console.log(' %s middleware', n);
|
||||
|
||||
while (n--) {
|
||||
app.use(function(req, res, next){
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
var body = new Buffer('Hello World');
|
||||
|
||||
app.use(function(req, res, next){
|
||||
res.send(body);
|
||||
});
|
||||
|
||||
app.listen(3333);
|
||||
16
benchmarks/run
Executable file
16
benchmarks/run
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo
|
||||
MW=$1 node $2 &
|
||||
pid=$!
|
||||
|
||||
sleep 2
|
||||
|
||||
wrk 'http://localhost:3333/?foo[bar]=baz' \
|
||||
-d 3 \
|
||||
-c 50 \
|
||||
-t 8 \
|
||||
| grep 'Requests/sec' \
|
||||
| awk '{ print " " $2 }'
|
||||
|
||||
kill $pid
|
||||
@@ -74,7 +74,7 @@ var users = [
|
||||
*/
|
||||
|
||||
var jadeLayout = [
|
||||
'doctype 5'
|
||||
'doctype html'
|
||||
, 'html'
|
||||
, ' head'
|
||||
, ' title= title'
|
||||
@@ -357,7 +357,7 @@ function createApplicationAt(path) {
|
||||
// CSS Engine support
|
||||
switch (program.css) {
|
||||
case 'less':
|
||||
pkg.dependencies['less-middleware'] = '*';
|
||||
pkg.dependencies['less-middleware'] = '~0.1.15';
|
||||
break;
|
||||
default:
|
||||
if (program.css) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
!!! 5
|
||||
doctype html
|
||||
html
|
||||
include header
|
||||
body
|
||||
block content
|
||||
block content
|
||||
|
||||
@@ -18,7 +18,7 @@ app.resource = function(path, obj) {
|
||||
obj.range(req, res, a, b, format);
|
||||
});
|
||||
this.get(path + '/:id', obj.show);
|
||||
this.del(path + '/:id', obj.destroy);
|
||||
this.delete(path + '/:id', obj.destroy);
|
||||
};
|
||||
|
||||
// Fake records
|
||||
|
||||
@@ -29,7 +29,7 @@ var users = {
|
||||
res.send('user ' + req.params.uid);
|
||||
},
|
||||
|
||||
del: function(req, res){
|
||||
delete: function(req, res){
|
||||
res.send('delete users');
|
||||
}
|
||||
};
|
||||
@@ -39,7 +39,7 @@ var pets = {
|
||||
res.send('user ' + req.params.uid + '\'s pets');
|
||||
},
|
||||
|
||||
del: function(req, res){
|
||||
delete: function(req, res){
|
||||
res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
|
||||
}
|
||||
};
|
||||
@@ -47,13 +47,13 @@ var pets = {
|
||||
app.map({
|
||||
'/users': {
|
||||
get: users.list,
|
||||
del: users.del,
|
||||
delete: users.delete,
|
||||
'/:uid': {
|
||||
get: users.get,
|
||||
'/pets': {
|
||||
get: pets.list,
|
||||
'/:pid': {
|
||||
del: pets.del
|
||||
delete: pets.delete
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
|
||||
res.send('Editing user ' + req.user.name);
|
||||
});
|
||||
|
||||
app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
|
||||
app.delete('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
|
||||
res.send('Deleted user ' + req.user.name);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
doctype 5
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
title= title
|
||||
|
||||
4
index.js
4
index.js
@@ -1,4 +1,2 @@
|
||||
|
||||
module.exports = process.env.EXPRESS_COV
|
||||
? require('./lib-cov/express')
|
||||
: require('./lib/express');
|
||||
module.exports = require('./lib/express');
|
||||
|
||||
@@ -8,8 +8,10 @@ var connect = require('connect')
|
||||
, middleware = require('./middleware')
|
||||
, debug = require('debug')('express:application')
|
||||
, locals = require('./utils').locals
|
||||
, compileTrust = require('./utils').compileTrust
|
||||
, View = require('./view')
|
||||
, utils = connect.utils
|
||||
, deprecate = require('./utils').deprecate
|
||||
, http = require('http');
|
||||
|
||||
/**
|
||||
@@ -47,6 +49,7 @@ app.defaultConfiguration = function(){
|
||||
this.enable('etag');
|
||||
this.set('env', process.env.NODE_ENV || 'development');
|
||||
this.set('subdomain offset', 2);
|
||||
this.set('trust proxy', false);
|
||||
debug('booting in %s mode', this.get('env'));
|
||||
|
||||
// implicit middleware
|
||||
@@ -242,7 +245,7 @@ app.param = function(name, fn){
|
||||
* Mounted servers inherit their parent server's settings.
|
||||
*
|
||||
* @param {String} setting
|
||||
* @param {String} val
|
||||
* @param {*} [val]
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
@@ -252,6 +255,12 @@ app.set = function(setting, val){
|
||||
return this.settings[setting];
|
||||
} else {
|
||||
this.settings[setting] = val;
|
||||
|
||||
if (setting === 'trust proxy') {
|
||||
debug('compile trust proxy %j', val);
|
||||
this.set('trust proxy fn', compileTrust(val));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
@@ -400,11 +409,6 @@ methods.forEach(function(method){
|
||||
app[method] = function(path){
|
||||
if ('get' == method && 1 == arguments.length) return this.set(path);
|
||||
|
||||
// deprecated
|
||||
if (Array.isArray(path)) {
|
||||
console.trace('passing an array to app.VERB() is deprecated and will be removed in 4.0');
|
||||
}
|
||||
|
||||
// if no router attached yet, attach the router
|
||||
if (!this._usedRouter) this.use(this.router);
|
||||
|
||||
@@ -434,7 +438,7 @@ app.all = function(path){
|
||||
|
||||
// del -> delete alias
|
||||
|
||||
app.del = app.delete;
|
||||
app.del = deprecate(app.delete, 'app.del: Use app.delete instead');
|
||||
|
||||
/**
|
||||
* Render the given view `name` name with `options`
|
||||
@@ -490,7 +494,7 @@ app.render = function(name, options, fn){
|
||||
});
|
||||
|
||||
if (!view.path) {
|
||||
var err = new Error('Failed to lookup view "' + name + '"');
|
||||
var err = new Error('Failed to lookup view "' + name + '" in views directory "' + view.root + '"');
|
||||
err.view = view;
|
||||
return fn(err);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var merge = require('merge-descriptors');
|
||||
var connect = require('connect')
|
||||
, proto = require('./application')
|
||||
, Route = require('./router/route')
|
||||
, Router = require('./router')
|
||||
, req = require('./request')
|
||||
, res = require('./response')
|
||||
, deprecate = require('./utils').deprecate
|
||||
, utils = connect.utils;
|
||||
|
||||
/**
|
||||
@@ -43,27 +45,21 @@ function createApplication() {
|
||||
* for example `express.logger` etc.
|
||||
*/
|
||||
|
||||
for (var key in connect.middleware) {
|
||||
Object.defineProperty(
|
||||
exports
|
||||
, key
|
||||
, Object.getOwnPropertyDescriptor(connect.middleware, key));
|
||||
}
|
||||
merge(exports, connect.middleware);
|
||||
|
||||
/**
|
||||
* Error on createServer().
|
||||
* Deprecated createServer().
|
||||
*/
|
||||
|
||||
exports.createServer = function(){
|
||||
console.warn('Warning: express.createServer() is deprecated, express');
|
||||
console.warn('applications no longer inherit from http.Server,');
|
||||
console.warn('please use:');
|
||||
console.warn('');
|
||||
console.warn(' var express = require("express");');
|
||||
console.warn(' var app = express();');
|
||||
console.warn('');
|
||||
return createApplication();
|
||||
};
|
||||
exports.createServer = deprecate(createApplication,
|
||||
'createServer() is deprecated\n' +
|
||||
'express applications no longer inherit from http.Server\n' +
|
||||
'please use:\n' +
|
||||
'\n' +
|
||||
' var express = require("express");\n' +
|
||||
' var app = express();\n' +
|
||||
'\n'
|
||||
);
|
||||
|
||||
/**
|
||||
* Expose the prototypes.
|
||||
|
||||
@@ -8,7 +8,8 @@ var http = require('http')
|
||||
, connect = require('connect')
|
||||
, fresh = require('fresh')
|
||||
, parseRange = require('range-parser')
|
||||
, parse = connect.utils.parseUrl
|
||||
, parse = require('parseurl')
|
||||
, proxyaddr = require('proxy-addr')
|
||||
, mime = connect.mime;
|
||||
|
||||
/**
|
||||
@@ -337,19 +338,26 @@ req.is = function(type){
|
||||
/**
|
||||
* Return the protocol string "http" or "https"
|
||||
* when requested with TLS. When the "trust proxy"
|
||||
* setting is enabled the "X-Forwarded-Proto" header
|
||||
* field will be trusted. If you're running behind
|
||||
* a reverse proxy that supplies https for you this
|
||||
* may be enabled.
|
||||
* setting trusts the socket address, the
|
||||
* "X-Forwarded-Proto" header field will be trusted.
|
||||
* If you're running behind a reverse proxy that
|
||||
* supplies https for you this may be enabled.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('protocol', function(){
|
||||
var trustProxy = this.app.get('trust proxy');
|
||||
if (this.connection.encrypted) return 'https';
|
||||
if (!trustProxy) return 'http';
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
|
||||
if (!trust(this.connection.remoteAddress)) {
|
||||
return this.connection.encrypted
|
||||
? 'https'
|
||||
: 'http';
|
||||
}
|
||||
|
||||
// Note: X-Forwarded-Proto is normally only ever a
|
||||
// single value, but this is to be safe.
|
||||
var proto = this.get('X-Forwarded-Proto') || 'http';
|
||||
return proto.split(/\s*,\s*/)[0];
|
||||
});
|
||||
@@ -368,36 +376,36 @@ req.__defineGetter__('secure', function(){
|
||||
});
|
||||
|
||||
/**
|
||||
* Return the remote address, or when
|
||||
* "trust proxy" is `true` return
|
||||
* the upstream addr.
|
||||
* Return the remote address from the trusted proxy.
|
||||
*
|
||||
* The is the remote address on the socket unless
|
||||
* "trust proxy" is set.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('ip', function(){
|
||||
return this.ips[0] || this.connection.remoteAddress;
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
return proxyaddr(this, trust);
|
||||
});
|
||||
|
||||
/**
|
||||
* When "trust proxy" is `true`, parse
|
||||
* the "X-Forwarded-For" ip address list.
|
||||
* When "trust proxy" is set, trusted proxy addresses + client.
|
||||
*
|
||||
* For example if the value were "client, proxy1, proxy2"
|
||||
* you would receive the array `["client", "proxy1", "proxy2"]`
|
||||
* where "proxy2" is the furthest down-stream.
|
||||
* where "proxy2" is the furthest down-stream and "proxy1" and
|
||||
* "proxy2" were trusted.
|
||||
*
|
||||
* @return {Array}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('ips', function(){
|
||||
var trustProxy = this.app.get('trust proxy');
|
||||
var val = this.get('X-Forwarded-For');
|
||||
return trustProxy && val
|
||||
? val.split(/ *, */)
|
||||
: [];
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
var addrs = proxyaddr.all(this, trust);
|
||||
return addrs.slice(1).reverse();
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -467,16 +475,33 @@ req.__defineGetter__('path', function(){
|
||||
/**
|
||||
* Parse the "Host" header field hostname.
|
||||
*
|
||||
* When the "trust proxy" setting trusts the socket
|
||||
* address, the "X-Forwarded-Host" header field will
|
||||
* be trusted.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('host', function(){
|
||||
var trustProxy = this.app.get('trust proxy');
|
||||
var host = trustProxy && this.get('X-Forwarded-Host');
|
||||
host = host || this.get('Host');
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
var host = this.get('X-Forwarded-Host');
|
||||
|
||||
if (!host || !trust(this.connection.remoteAddress)) {
|
||||
host = this.get('Host');
|
||||
}
|
||||
|
||||
if (!host) return;
|
||||
return host.split(':')[0];
|
||||
|
||||
// IPv6 literal support
|
||||
var offset = host[0] === '['
|
||||
? host.indexOf(']') + 1
|
||||
: 0;
|
||||
var index = host.indexOf(':', offset);
|
||||
|
||||
return ~index
|
||||
? host.substring(0, index)
|
||||
: host;
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,7 @@ var http = require('http')
|
||||
, sign = require('cookie-signature').sign
|
||||
, normalizeType = require('./utils').normalizeType
|
||||
, normalizeTypes = require('./utils').normalizeTypes
|
||||
, deprecate = require('./utils').deprecate
|
||||
, etag = require('./utils').etag
|
||||
, statusCodes = http.STATUS_CODES
|
||||
, cookie = require('cookie')
|
||||
@@ -177,6 +178,9 @@ res.json = function(obj){
|
||||
// res.json(body, status) backwards compat
|
||||
if ('number' == typeof arguments[1]) {
|
||||
this.statusCode = arguments[1];
|
||||
return 'number' === typeof obj
|
||||
? jsonNumDeprecated.call(this, obj)
|
||||
: jsonDeprecated.call(this, obj);
|
||||
} else {
|
||||
this.statusCode = obj;
|
||||
obj = arguments[1];
|
||||
@@ -196,6 +200,12 @@ res.json = function(obj){
|
||||
return this.send(body);
|
||||
};
|
||||
|
||||
var jsonDeprecated = deprecate(res.json,
|
||||
'res.json(obj, status): Use res.json(status, obj) instead');
|
||||
|
||||
var jsonNumDeprecated = deprecate(res.json,
|
||||
'res.json(num, status): Use res.status(status).json(num) instead');
|
||||
|
||||
/**
|
||||
* Send JSON response with JSONP callback support.
|
||||
*
|
||||
@@ -218,6 +228,9 @@ res.jsonp = function(obj){
|
||||
// res.json(body, status) backwards compat
|
||||
if ('number' == typeof arguments[1]) {
|
||||
this.statusCode = arguments[1];
|
||||
return 'number' === typeof obj
|
||||
? jsonpNumDeprecated.call(this, obj)
|
||||
: jsonpDeprecated.call(this, obj);
|
||||
} else {
|
||||
this.statusCode = obj;
|
||||
obj = arguments[1];
|
||||
@@ -237,9 +250,13 @@ res.jsonp = function(obj){
|
||||
this.charset = this.charset || 'utf-8';
|
||||
this.set('Content-Type', 'application/json');
|
||||
|
||||
// fixup callback
|
||||
if (Array.isArray(callback)) {
|
||||
callback = callback[0];
|
||||
}
|
||||
|
||||
// jsonp
|
||||
if (callback) {
|
||||
if (Array.isArray(callback)) callback = callback[0];
|
||||
if (callback && 'string' === typeof callback) {
|
||||
this.set('Content-Type', 'text/javascript');
|
||||
var cb = callback.replace(/[^\[\]\w$.]/g, '');
|
||||
body = 'typeof ' + cb + ' === \'function\' && ' + cb + '(' + body + ');';
|
||||
@@ -248,6 +265,12 @@ res.jsonp = function(obj){
|
||||
return this.send(body);
|
||||
};
|
||||
|
||||
var jsonpDeprecated = deprecate(res.json,
|
||||
'res.jsonp(obj, status): Use res.jsonp(status, obj) instead');
|
||||
|
||||
var jsonpNumDeprecated = deprecate(res.json,
|
||||
'res.jsonp(num, status): Use res.status(status).jsonp(num) instead');
|
||||
|
||||
/**
|
||||
* Transfer the file at the given `path`.
|
||||
*
|
||||
@@ -311,13 +334,13 @@ res.sendfile = function(path, options, fn){
|
||||
|
||||
// clean up
|
||||
cleanup();
|
||||
if (!self.headerSent) self.removeHeader('Content-Disposition');
|
||||
if (!self.headersSent) self.removeHeader('Content-Disposition');
|
||||
|
||||
// callback available
|
||||
if (fn) return fn(err);
|
||||
|
||||
// list in limbo if there's no callback
|
||||
if (self.headerSent) return;
|
||||
if (self.headersSent) return;
|
||||
|
||||
// delegate
|
||||
next(err);
|
||||
@@ -352,7 +375,7 @@ res.sendfile = function(path, options, fn){
|
||||
* Optionally providing an alternate attachment `filename`,
|
||||
* and optional callback `fn(err)`. The callback is invoked
|
||||
* when the data transfer is complete, or when an error has
|
||||
* ocurred. Be sure to check `res.headerSent` if you plan to respond.
|
||||
* ocurred. Be sure to check `res.headersSent` if you plan to respond.
|
||||
*
|
||||
* This method uses `res.sendfile()`.
|
||||
*
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var Route = require('./route')
|
||||
, utils = require('../utils')
|
||||
, methods = require('methods')
|
||||
, debug = require('debug')('express:router')
|
||||
, parse = require('connect').utils.parseUrl;
|
||||
var Route = require('./route');
|
||||
var utils = require('../utils');
|
||||
var methods = require('methods');
|
||||
var debug = require('debug')('express:router');
|
||||
var parseUrl = require('parseurl');
|
||||
|
||||
/**
|
||||
* Expose `Router` constructor.
|
||||
@@ -104,7 +104,7 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
req.route = route = self.matchRequest(req, i);
|
||||
|
||||
// implied OPTIONS
|
||||
if (!route && 'OPTIONS' == req.method) return self._options(req, res);
|
||||
if (!route && 'OPTIONS' == req.method) return self._options(req, res, next);
|
||||
|
||||
// no route
|
||||
if (!route) return next(err);
|
||||
@@ -181,9 +181,10 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Router.prototype._options = function(req, res){
|
||||
var path = parse(req).pathname
|
||||
Router.prototype._options = function(req, res, next){
|
||||
var path = parseUrl(req).pathname
|
||||
, body = this._optionsFor(path).join(',');
|
||||
if (!body) return next();
|
||||
res.set('Allow', body).send(body);
|
||||
};
|
||||
|
||||
@@ -221,7 +222,7 @@ Router.prototype._optionsFor = function(path){
|
||||
|
||||
Router.prototype.matchRequest = function(req, i, head){
|
||||
var method = req.method.toLowerCase()
|
||||
, url = parse(req)
|
||||
, url = parseUrl(req)
|
||||
, path = url.pathname
|
||||
, routes = this.map
|
||||
, i = i || 0
|
||||
|
||||
@@ -57,9 +57,15 @@ Route.prototype.match = function(path){
|
||||
for (var i = 1, len = m.length; i < len; ++i) {
|
||||
var key = keys[i - 1];
|
||||
|
||||
var val = 'string' == typeof m[i]
|
||||
? utils.decode(m[i])
|
||||
: m[i];
|
||||
try {
|
||||
var val = 'string' == typeof m[i]
|
||||
? decodeURIComponent(m[i])
|
||||
: m[i];
|
||||
} catch(e) {
|
||||
var err = new Error("Failed to decode param '" + m[i] + "'");
|
||||
err.status = 400;
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (key) {
|
||||
params[key.name] = val;
|
||||
|
||||
58
lib/utils.js
58
lib/utils.js
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
|
||||
var mime = require('connect').mime
|
||||
, deprecate = require('util').deprecate
|
||||
, proxyaddr = require('proxy-addr')
|
||||
, crc32 = require('buffer-crc32');
|
||||
|
||||
/**
|
||||
@@ -12,6 +14,30 @@ var mime = require('connect').mime
|
||||
|
||||
var toString = {}.toString;
|
||||
|
||||
/**
|
||||
* Deprecate function, like core `util.deprecate`,
|
||||
* but with NODE_ENV and color support.
|
||||
*
|
||||
* @param {Function} fn
|
||||
* @param {String} msg
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.deprecate = function(fn, msg){
|
||||
if (process.env.NODE_ENV === 'test') return fn;
|
||||
|
||||
// prepend module name
|
||||
msg = 'express: ' + msg;
|
||||
|
||||
if (process.stderr.isTTY) {
|
||||
// colorize
|
||||
msg = '\x1b[31;1m' + msg + '\x1b[0m';
|
||||
}
|
||||
|
||||
return deprecate(fn, msg);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return ETag for `body`.
|
||||
*
|
||||
@@ -313,21 +339,31 @@ exports.pathRegexp = function(path, keys, sensitive, strict) {
|
||||
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes a URI component. Returns
|
||||
* the original string if the component
|
||||
* is malformed.
|
||||
* Compile "proxy trust" value to function.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {String}
|
||||
* @param {Boolean|String|Number|Array|Function} val
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.decode = function(str) {
|
||||
try {
|
||||
return decodeURIComponent(str);
|
||||
} catch (e) {
|
||||
return str;
|
||||
exports.compileTrust = function(val) {
|
||||
if (typeof val === 'function') return val;
|
||||
|
||||
if (val === true) {
|
||||
// Support plain true/false
|
||||
return function(){ return true };
|
||||
}
|
||||
|
||||
if (typeof val === 'number') {
|
||||
// Support trusting hop count
|
||||
return function(a, i){ return i < val };
|
||||
}
|
||||
|
||||
if (typeof val === 'string') {
|
||||
// Support comma-separated values
|
||||
val = val.split(/ *, */);
|
||||
}
|
||||
|
||||
return proxyaddr.compile(val || []);
|
||||
}
|
||||
|
||||
79
package.json
79
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "express",
|
||||
"description": "Sinatra inspired web development framework",
|
||||
"version": "3.4.5",
|
||||
"version": "3.7.0",
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"contributors": [
|
||||
{
|
||||
@@ -16,35 +16,23 @@
|
||||
"name": "Ciaran Jessup",
|
||||
"email": "ciaranj@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Douglas Christopher Wilson",
|
||||
"email": "doug@somethingdoug.com"
|
||||
},
|
||||
{
|
||||
"name": "Guillermo Rauch",
|
||||
"email": "rauchg@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Ong",
|
||||
"email": "me@jongleberry.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Shtylman",
|
||||
"email": "shtylman+expressjs@gmail.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"connect": "2.11.1",
|
||||
"commander": "1.3.2",
|
||||
"range-parser": "0.0.4",
|
||||
"mkdirp": "0.3.5",
|
||||
"cookie": "0.1.0",
|
||||
"buffer-crc32": "0.2.1",
|
||||
"fresh": "0.2.0",
|
||||
"methods": "0.1.0",
|
||||
"send": "0.1.4",
|
||||
"cookie-signature": "1.0.1",
|
||||
"debug": ">= 0.7.3 < 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ejs": "~0.8.4",
|
||||
"mocha": "~1.14.0",
|
||||
"jade": "~0.30.0",
|
||||
"hjs": "~0.0.6",
|
||||
"stylus": "~0.40.0",
|
||||
"should": "~2.0.2",
|
||||
"connect-redis": "~1.4.5",
|
||||
"marked": "0.2.10",
|
||||
"supertest": "~0.8.1"
|
||||
},
|
||||
"keywords": [
|
||||
"express",
|
||||
"framework",
|
||||
@@ -57,15 +45,46 @@
|
||||
"api"
|
||||
],
|
||||
"repository": "git://github.com/visionmedia/express",
|
||||
"main": "index",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"connect": "2.16.2",
|
||||
"commander": "1.3.2",
|
||||
"methods": "1.0.0",
|
||||
"mkdirp": "0.5.0",
|
||||
"parseurl": "1.0.1",
|
||||
"proxy-addr": "1.0.0",
|
||||
"range-parser": "1.0.0",
|
||||
"cookie": "0.1.2",
|
||||
"buffer-crc32": "0.2.1",
|
||||
"fresh": "0.2.2",
|
||||
"send": "0.3.0",
|
||||
"cookie-signature": "1.0.3",
|
||||
"merge-descriptors": "0.0.2",
|
||||
"debug": ">= 0.8.0 < 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"coveralls": "2.10.0",
|
||||
"ejs": "~0.8.4",
|
||||
"istanbul": "0.2.10",
|
||||
"mocha": "~1.18.2",
|
||||
"should": "~3.3.1",
|
||||
"jade": "~0.30.0",
|
||||
"hjs": "~0.0.6",
|
||||
"stylus": "~0.40.0",
|
||||
"connect-redis": "~1.4.5",
|
||||
"marked": "0.2.10",
|
||||
"supertest": "~0.12.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
},
|
||||
"bin": {
|
||||
"express": "./bin/express"
|
||||
},
|
||||
"scripts": {
|
||||
"prepublish": "npm prune",
|
||||
"test": "make test"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
"test": "mocha --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
|
||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
|
||||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/ && cat ./coverage/lcov.info | coveralls"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
NODE_ENV=production node ./support/app &
|
||||
pid=$!
|
||||
|
||||
bench() {
|
||||
ab -n 5000 -c 50 -k -q http://127.0.0.1:8000$1 \
|
||||
| grep "Requests per" \
|
||||
| cut -d ' ' -f 7 \
|
||||
| xargs echo "$2:"
|
||||
}
|
||||
|
||||
bench_conditional() {
|
||||
ab -n 5000 -c 50 -H "If-None-Match: $3" -k -q http://127.0.0.1:8000$1 \
|
||||
| grep "Requests per" \
|
||||
| cut -d ' ' -f 7 \
|
||||
| xargs echo "$2:"
|
||||
}
|
||||
|
||||
sleep .5
|
||||
bench / "Hello World"
|
||||
bench /blog "Mounted Hello World"
|
||||
bench /blog/admin "Mounted 2 Hello World"
|
||||
bench /middleware "Middleware"
|
||||
bench /match "Router"
|
||||
bench /render "Render"
|
||||
bench /json "JSON tiny"
|
||||
bench /json/15 "JSON small"
|
||||
bench /json/50 "JSON medium"
|
||||
bench /json/150 "JSON large"
|
||||
|
||||
kill -9 $pid
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
var express = require('../')
|
||||
, Router = express.Router
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, methods = require('methods')
|
||||
, assert = require('assert');
|
||||
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
var app = require('../../examples/auth/app')
|
||||
, request = require('../support/http');
|
||||
|
||||
function redirects(to, fn){
|
||||
return function(err, res){
|
||||
res.statusCode.should.equal(302)
|
||||
res.headers.should.have.property('location').match(to);
|
||||
fn()
|
||||
}
|
||||
}
|
||||
var request = require('supertest')
|
||||
|
||||
function getCookie(res) {
|
||||
return res.headers['set-cookie'][0].split(';')[0];
|
||||
@@ -18,25 +10,93 @@ describe('auth', function(){
|
||||
it('should redirect to /login', function(done){
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(redirects(/\/login$/, done))
|
||||
.expect('Location', '/login')
|
||||
.expect(302, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('GET /restricted (w/o cookie)',function(){
|
||||
it('should redirect to /login', function(done){
|
||||
describe('GET /login',function(){
|
||||
it('should render login form', function(done){
|
||||
request(app)
|
||||
.get('/restricted')
|
||||
.end(redirects(/\/login$/,done))
|
||||
.get('/login')
|
||||
.expect(200, /<form/, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('POST /login', function(){
|
||||
it('should fail without proper credentials', function(done){
|
||||
it('should display login error', function(done){
|
||||
request(app)
|
||||
.post('/login')
|
||||
.type('urlencoded')
|
||||
.send('username=not-tj&password=foobar')
|
||||
.end(redirects(/\/login$/, done))
|
||||
.expect('Location', '/login')
|
||||
.expect(302, function(err, res){
|
||||
if (err) return done(err)
|
||||
request(app)
|
||||
.get('/login')
|
||||
.set('Cookie', getCookie(res))
|
||||
.expect(200, /Authentication failed/, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('GET /logout',function(){
|
||||
it('should redirect to /', function(done){
|
||||
request(app)
|
||||
.get('/logout')
|
||||
.expect('Location', '/')
|
||||
.expect(302, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('GET /restricted',function(){
|
||||
it('should redirect to /login without cookie', function(done){
|
||||
request(app)
|
||||
.get('/restricted')
|
||||
.expect('Location', '/login')
|
||||
.expect(302, done)
|
||||
})
|
||||
|
||||
it('should succeed with proper cookie', function(done){
|
||||
request(app)
|
||||
.post('/login')
|
||||
.type('urlencoded')
|
||||
.send('username=tj&password=foobar')
|
||||
.expect('Location', '/')
|
||||
.expect(302, function(err, res){
|
||||
if (err) return done(err)
|
||||
request(app)
|
||||
.get('/restricted')
|
||||
.set('Cookie', getCookie(res))
|
||||
.expect(200, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('POST /login', function(){
|
||||
it('should fail without proper username', function(done){
|
||||
request(app)
|
||||
.post('/login')
|
||||
.type('urlencoded')
|
||||
.send('username=not-tj&password=foobar')
|
||||
.expect('Location', '/login')
|
||||
.expect(302, done)
|
||||
})
|
||||
|
||||
it('should fail without proper password', function(done){
|
||||
request(app)
|
||||
.post('/login')
|
||||
.type('urlencoded')
|
||||
.send('username=tj&password=baz')
|
||||
.expect('Location', '/login')
|
||||
.expect(302, done)
|
||||
})
|
||||
|
||||
it('should succeed with proper credentials', function(done){
|
||||
request(app)
|
||||
.post('/login')
|
||||
.type('urlencoded')
|
||||
.send('username=tj&password=foobar')
|
||||
.expect('Location', '/')
|
||||
.expect(302, done)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
var request = require('../support/http')
|
||||
var request = require('supertest')
|
||||
, app = require('../../examples/content-negotiation');
|
||||
|
||||
describe('content-negotiation', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var app = require('../../examples/cookies/app')
|
||||
, request = require('../support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('cookies', function(){
|
||||
describe('GET /', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var app = require('../../examples/downloads/app')
|
||||
, request = require('../support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('downloads', function(){
|
||||
describe('GET /', function(){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
var request = require('../support/http')
|
||||
var request = require('supertest')
|
||||
, app = require('../../examples/ejs');
|
||||
|
||||
describe('ejs', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var app = require('../../examples/error-pages')
|
||||
, request = require('../support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('error-pages', function(){
|
||||
describe('GET /', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var app = require('../../examples/error')
|
||||
, request = require('../support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('error', function(){
|
||||
describe('GET /', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var app = require('../../examples/markdown')
|
||||
, request = require('../support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('markdown', function(){
|
||||
describe('GET /', function(){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
var request = require('../support/http')
|
||||
var request = require('supertest')
|
||||
, app = require('../../examples/mvc');
|
||||
|
||||
describe('mvc', function(){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var app = require('../../examples/params/app')
|
||||
, request = require('../support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('params', function(){
|
||||
describe('GET /', function(){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var app = require('../../examples/resource/app')
|
||||
, request = require('../support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('resource', function(){
|
||||
describe('GET /', function(){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
var request = require('../support/http')
|
||||
var request = require('supertest')
|
||||
, app = require('../../examples/web-service');
|
||||
|
||||
describe('web-service', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app.all()', function(){
|
||||
it('should add a router per method', function(done){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app.del()', function(){
|
||||
it('should alias app.delete()', function(done){
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, assert = require('assert');
|
||||
var express = require('../');
|
||||
var request = require('supertest');
|
||||
var assert = require('assert');
|
||||
|
||||
describe('HEAD', function(){
|
||||
it('should default to GET', function(done){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app.listen()', function(){
|
||||
it('should wrap with an HTTP server', function(done){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app', function(){
|
||||
describe('.locals(obj)', function(){
|
||||
@@ -14,7 +14,7 @@ describe('app', function(){
|
||||
app.locals.age.should.equal(2);
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('.locals.settings', function(){
|
||||
it('should expose app settings', function(){
|
||||
var app = express();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('OPTIONS', function(){
|
||||
it('should default to the routes defined', function(done){
|
||||
@@ -15,6 +15,30 @@ describe('OPTIONS', function(){
|
||||
.expect('GET,PUT')
|
||||
.expect('Allow', 'GET,PUT', done);
|
||||
})
|
||||
|
||||
it('should not respond if the path is not defined', function(done){
|
||||
var app = express();
|
||||
|
||||
app.get('/users', function(req, res){});
|
||||
|
||||
request(app)
|
||||
.options('/other')
|
||||
.expect(404, done);
|
||||
})
|
||||
|
||||
it('should forward requests down the middleware chain', function(done){
|
||||
var app = express();
|
||||
var router = new express.Router();
|
||||
|
||||
router.get('/users', function(req, res){});
|
||||
app.use(router.middleware);
|
||||
app.get('/other', function(req, res){});
|
||||
|
||||
request(app)
|
||||
.options('/other')
|
||||
.expect('GET')
|
||||
.expect('Allow', 'GET', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('app.options()', function(){
|
||||
@@ -34,4 +58,4 @@ describe('app.options()', function(){
|
||||
.expect('GET')
|
||||
.expect('Allow', 'GET', done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app', function(){
|
||||
describe('.param(fn)', function(){
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('app', function(){
|
||||
var app = express();
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.render('rawr.jade', function(err){
|
||||
err.message.should.equal('Failed to lookup view "rawr.jade"');
|
||||
err.message.should.equal('Failed to lookup view "rawr.jade" in views directory "' + __dirname + '/fixtures"');
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app', function(){
|
||||
describe('.request', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app', function(){
|
||||
describe('.response', function(){
|
||||
@@ -19,7 +19,7 @@ describe('app', function(){
|
||||
.get('/')
|
||||
.expect('HEY', done);
|
||||
})
|
||||
|
||||
|
||||
it('should not be influenced by other app protos', function(done){
|
||||
var app = express()
|
||||
, app2 = express();
|
||||
@@ -27,7 +27,7 @@ describe('app', function(){
|
||||
app.response.shout = function(str){
|
||||
this.send(str.toUpperCase());
|
||||
};
|
||||
|
||||
|
||||
app2.response.shout = function(str){
|
||||
this.send(str);
|
||||
};
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert')
|
||||
, methods = require('methods');
|
||||
|
||||
describe('app.router', function(){
|
||||
describe('methods supported', function(){
|
||||
methods.forEach(function(method){
|
||||
methods.concat('del').forEach(function(method){
|
||||
if (method === 'connect') return;
|
||||
|
||||
it('should include ' + method.toUpperCase(), function(done){
|
||||
if (method == 'delete') method = 'del';
|
||||
var app = express();
|
||||
var calls = [];
|
||||
|
||||
@@ -27,28 +28,54 @@ describe('app.router', function(){
|
||||
});
|
||||
})
|
||||
|
||||
it('should decode params', function(done){
|
||||
var app = express();
|
||||
describe('decode querystring', function(){
|
||||
it('should decode correct params', function(done){
|
||||
var app = express();
|
||||
|
||||
app.get('/:name', function(req, res, next){
|
||||
res.send(req.params.name);
|
||||
});
|
||||
app.get('/:name', function(req, res, next){
|
||||
res.send(req.params.name);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/foo%2Fbar')
|
||||
.expect('foo/bar', done);
|
||||
})
|
||||
request(app)
|
||||
.get('/foo%2Fbar')
|
||||
.expect('foo/bar', done);
|
||||
})
|
||||
|
||||
it('should accept params in malformed paths', function(done) {
|
||||
var app = express();
|
||||
it('should not accept params in malformed paths', function(done) {
|
||||
var app = express();
|
||||
|
||||
app.get('/:name', function(req, res, next){
|
||||
res.send(req.params.name);
|
||||
});
|
||||
app.get('/:name', function(req, res, next){
|
||||
res.send(req.params.name);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/%foobar')
|
||||
.expect('%foobar', done);
|
||||
request(app)
|
||||
.get('/%foobar')
|
||||
.expect(400, done);
|
||||
})
|
||||
|
||||
it('should not decode spaces', function(done) {
|
||||
var app = express();
|
||||
|
||||
app.get('/:name', function(req, res, next){
|
||||
res.send(req.params.name);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/foo+bar')
|
||||
.expect('foo+bar', done);
|
||||
})
|
||||
|
||||
it('should work with unicode', function(done) {
|
||||
var app = express();
|
||||
|
||||
app.get('/:name', function(req, res, next){
|
||||
res.send(req.params.name);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/%ce%b1')
|
||||
.expect('\u03b1', done);
|
||||
})
|
||||
})
|
||||
|
||||
it('should be .use()able', function(done){
|
||||
@@ -126,8 +153,8 @@ describe('app.router', function(){
|
||||
var app = express();
|
||||
|
||||
app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function(req, res){
|
||||
var id = req.params.shift()
|
||||
, op = req.params.shift();
|
||||
var id = req.params[0]
|
||||
, op = req.params[1];
|
||||
res.end(op + 'ing user ' + id);
|
||||
});
|
||||
|
||||
@@ -302,8 +329,8 @@ describe('app.router', function(){
|
||||
var app = express();
|
||||
|
||||
app.get('/api/*.*', function(req, res){
|
||||
var resource = req.params.shift()
|
||||
, format = req.params.shift();
|
||||
var resource = req.params[0]
|
||||
, format = req.params[1];
|
||||
res.end(resource + ' as ' + format);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app', function(){
|
||||
describe('.VERB()', function(){
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
var express = require('../')
|
||||
, assert = require('assert')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app.routes', function(){
|
||||
it('should be initialized', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('app', function(){
|
||||
it('should emit "mount" when mounted', function(done){
|
||||
@@ -23,7 +23,7 @@ describe('app', function(){
|
||||
blog.get('/blog', function(req, res){
|
||||
res.end('blog');
|
||||
});
|
||||
|
||||
|
||||
app.use(blog);
|
||||
|
||||
request(app)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, assert = require('assert');
|
||||
var express = require('../');
|
||||
var request = require('supertest');
|
||||
var assert = require('assert');
|
||||
|
||||
describe('exports', function(){
|
||||
it('should expose connect middleware', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//
|
||||
// var express = require('../')
|
||||
// , request = require('./support/http');
|
||||
// , request = require('supertest');
|
||||
//
|
||||
// describe('middleware', function(){
|
||||
// describe('.next()', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('throw after .end()', function(){
|
||||
it('should fail gracefully', function(done){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.accepted', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.acceptedCharsets', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.acceptedEncodings', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.acceptedLanguages', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.accepts(type)', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.acceptsCharset(type)', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.auth', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.fresh', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('req', function(){
|
||||
|
||||
106
test/req.host.js
106
test/req.host.js
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('req', function(){
|
||||
@@ -18,6 +18,19 @@ describe('req', function(){
|
||||
.expect('example.com', done);
|
||||
})
|
||||
|
||||
it('should strip port number', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.host);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post('/')
|
||||
.set('Host', 'example.com:3000')
|
||||
.expect('example.com', done);
|
||||
})
|
||||
|
||||
it('should return undefined otherwise', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -30,5 +43,96 @@ describe('req', function(){
|
||||
.post('/')
|
||||
.expect('undefined', done);
|
||||
})
|
||||
|
||||
it('should work with IPv6 Host', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.host);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post('/')
|
||||
.set('Host', '[::1]')
|
||||
.expect('[::1]', done);
|
||||
})
|
||||
|
||||
it('should work with IPv6 Host and port', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.host);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post('/')
|
||||
.set('Host', '[::1]:3000')
|
||||
.expect('[::1]', done);
|
||||
})
|
||||
|
||||
describe('when "trust proxy" is enabled', function(){
|
||||
it('should respect X-Forwarded-Host', function(done){
|
||||
var app = express();
|
||||
|
||||
app.enable('trust proxy');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.host);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'localhost')
|
||||
.set('X-Forwarded-Host', 'example.com')
|
||||
.expect('example.com', done);
|
||||
})
|
||||
|
||||
it('should ignore X-Forwarded-Host if socket addr not trusted', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', '10.0.0.1');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.host);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'localhost')
|
||||
.set('X-Forwarded-Host', 'example.com')
|
||||
.expect('localhost', done);
|
||||
})
|
||||
|
||||
it('should default to Host', function(done){
|
||||
var app = express();
|
||||
|
||||
app.enable('trust proxy');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.host);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'example.com')
|
||||
.expect('example.com', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when "trust proxy" is disabled', function(){
|
||||
it('should ignore X-Forwarded-Host', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.host);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'localhost')
|
||||
.set('X-Forwarded-Host', 'evil')
|
||||
.expect('localhost', done);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.ip', function(){
|
||||
@@ -20,6 +20,21 @@ describe('req', function(){
|
||||
.set('X-Forwarded-For', 'client, p1, p2')
|
||||
.expect('client', done);
|
||||
})
|
||||
|
||||
it('should return the addr after trusted proxy', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', 2);
|
||||
|
||||
app.use(function(req, res, next){
|
||||
res.send(req.ip);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-For', 'client, p1, p2')
|
||||
.expect('p1', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when "trust proxy" is disabled', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.ips', function(){
|
||||
@@ -20,6 +20,21 @@ describe('req', function(){
|
||||
.set('X-Forwarded-For', 'client, p1, p2')
|
||||
.expect('["client","p1","p2"]', done);
|
||||
})
|
||||
|
||||
it('should stop at first untrusted', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', 2);
|
||||
|
||||
app.use(function(req, res, next){
|
||||
res.send(req.ips);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-For', 'client, p1, p2')
|
||||
.expect('["p1","p2"]', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when "trust proxy" is disabled', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
function req(ct) {
|
||||
var req = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest')
|
||||
|
||||
describe('req', function(){
|
||||
describe('.param(name, default)', function(){
|
||||
@@ -29,7 +29,7 @@ describe('req', function(){
|
||||
.get('/?name=tj')
|
||||
.expect('tj', done);
|
||||
})
|
||||
|
||||
|
||||
it('should check req.body', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('req', function(){
|
||||
.send({ name: 'tj' })
|
||||
.expect('tj', done);
|
||||
})
|
||||
|
||||
|
||||
it('should check req.params', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.path', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.protocol', function(){
|
||||
@@ -32,6 +32,21 @@ describe('req', function(){
|
||||
.expect('https', done);
|
||||
})
|
||||
|
||||
it('should ignore X-Forwarded-Proto if socket addr not trusted', function(done){
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', '10.0.0.1');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.end(req.protocol);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-Proto', 'https')
|
||||
.expect('http', done);
|
||||
})
|
||||
|
||||
it('should default to http', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.query', function(){
|
||||
@@ -18,7 +18,7 @@ describe('req', function(){
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
it('should contain the parsed query-string', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.route', function(){
|
||||
@@ -12,7 +12,7 @@ describe('req', function(){
|
||||
req.route.path.should.equal('/user/:id/:op?');
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
app.get('/user/:id/edit', function(req, res){
|
||||
req.route.method.should.equal('get');
|
||||
req.route.path.should.equal('/user/:id/edit');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.secure', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest')
|
||||
|
||||
describe('req', function(){
|
||||
describe('.signedCookies', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.stale', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.subdomains', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('req', function(){
|
||||
describe('.xhr', function(){
|
||||
@@ -19,7 +19,7 @@ describe('req', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it('should case-insensitive', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('req', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it('should return false otherwise', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('req', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it('should return false when not present', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.attachment()', function(){
|
||||
@@ -16,7 +16,7 @@ describe('res', function(){
|
||||
.expect('Content-Disposition', 'attachment', done);
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('.attachment(filename)', function(){
|
||||
it('should add the filename param', function(done){
|
||||
var app = express();
|
||||
@@ -30,7 +30,7 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.expect('Content-Disposition', 'attachment; filename="image.png"', done);
|
||||
})
|
||||
|
||||
|
||||
it('should set the Content-Type', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.charset', function(){
|
||||
@@ -17,7 +17,7 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.expect("text/x-foo; charset=utf-8", done);
|
||||
})
|
||||
|
||||
|
||||
it('should take precedence over res.send() defaults', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.clearCookie(name)', function(){
|
||||
@@ -20,7 +20,7 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('.clearCookie(name, options)', function(){
|
||||
it('should set the given params', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, utils = require('connect').utils
|
||||
, cookie = require('cookie');
|
||||
|
||||
@@ -39,7 +39,7 @@ describe('res', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
it('should allow multiple calls', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('.cookie(name, string, options)', function(){
|
||||
it('should set params', function(done){
|
||||
var app = express();
|
||||
@@ -76,7 +76,7 @@ describe('res', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('maxAge', function(){
|
||||
it('should set relative expires', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('res', function(){
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, utils = require('../lib/utils')
|
||||
, assert = require('assert');
|
||||
|
||||
var app = express();
|
||||
var app1 = express();
|
||||
|
||||
app.use(function(req, res, next){
|
||||
app1.use(function(req, res, next){
|
||||
res.format({
|
||||
'text/plain': function(){
|
||||
res.send('hey');
|
||||
@@ -15,7 +15,7 @@ app.use(function(req, res, next){
|
||||
'text/html': function(){
|
||||
res.send('<p>hey</p>');
|
||||
},
|
||||
|
||||
|
||||
'application/json': function(a, b, c){
|
||||
assert(req == a);
|
||||
assert(res == b);
|
||||
@@ -25,7 +25,7 @@ app.use(function(req, res, next){
|
||||
});
|
||||
});
|
||||
|
||||
app.use(function(err, req, res, next){
|
||||
app1.use(function(err, req, res, next){
|
||||
if (!err.types) throw err;
|
||||
res.send(err.status, 'Supports: ' + err.types.join(', '));
|
||||
})
|
||||
@@ -53,10 +53,24 @@ app3.use(function(req, res, next){
|
||||
})
|
||||
});
|
||||
|
||||
var app4 = express();
|
||||
|
||||
app4.get('/', function(req, res, next){
|
||||
res.format({
|
||||
text: function(){ res.send('hey') },
|
||||
html: function(){ res.send('<p>hey</p>') },
|
||||
json: function(){ res.send({ message: 'hey' }) }
|
||||
});
|
||||
});
|
||||
|
||||
app4.use(function(err, req, res, next){
|
||||
res.send(err.status, 'Supports: ' + err.types.join(', '));
|
||||
})
|
||||
|
||||
describe('res', function(){
|
||||
describe('.format(obj)', function(){
|
||||
describe('with canonicalized mime types', function(){
|
||||
test(app);
|
||||
test(app1);
|
||||
})
|
||||
|
||||
describe('with extnames', function(){
|
||||
@@ -71,6 +85,10 @@ describe('res', function(){
|
||||
.expect('default', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('in router', function(){
|
||||
test(app4);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('res', function(){
|
||||
@@ -18,7 +18,7 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
describe('when given primitives', function(){
|
||||
it('should respond with json', function(done){
|
||||
it('should respond with json for null', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
@@ -33,6 +33,40 @@ describe('res', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should respond with json for Number', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.json(300);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(200);
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('300');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should respond with json for String', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.json('str');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(200);
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('"str"');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when given an array', function(){
|
||||
@@ -162,6 +196,23 @@ describe('res', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should use status as second number for backwards compat', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.json(200, 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('200');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should not override previous Content-Types', function(done){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('res', function(){
|
||||
@@ -37,6 +37,22 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
it('should ignore object callback parameter with jsonp', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp({ count: 1 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/?callback[a]=something')
|
||||
.end(function(err, res){
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('{"count":1}');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow renaming callback', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -157,6 +173,58 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
describe('when given primitives', function(){
|
||||
it('should respond with json for null', 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();
|
||||
})
|
||||
})
|
||||
|
||||
it('should respond with json for Number', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp(300);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(200);
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('300');
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should respond with json for String', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp('str');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.statusCode.should.equal(200);
|
||||
res.headers.should.have.property('content-type', 'application/json; charset=utf-8');
|
||||
res.text.should.equal('"str"');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('"json replacer" setting', function(){
|
||||
it('should be passed to JSON.stringify()', function(done){
|
||||
var app = express();
|
||||
@@ -212,7 +280,7 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
describe('.json(status, object)', function(){
|
||||
describe('.jsonp(status, object)', function(){
|
||||
it('should respond with json and set the .statusCode', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -231,7 +299,7 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
describe('.json(object, status)', function(){
|
||||
describe('.jsonp(object, status)', function(){
|
||||
it('should respond with json and set the .statusCode for backwards compat', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -248,5 +316,22 @@ describe('res', function(){
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should use status as second number for backwards compat', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.jsonp(200, 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('200');
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.locals(obj)', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.location(url)', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.redirect(url)', function(){
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.render(name)', function(){
|
||||
it('should support absolute paths', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
@@ -17,10 +17,10 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.expect('<p>tobi</p>', done);
|
||||
})
|
||||
|
||||
|
||||
it('should support absolute paths with "view engine"', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.locals.user = { name: 'tobi' };
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('res', function(){
|
||||
|
||||
it('should expose app.locals', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
@@ -50,29 +50,29 @@ describe('res', function(){
|
||||
|
||||
it('should support index.<engine>', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('blog/post');
|
||||
});
|
||||
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('<h1>blog post</h1>', done);
|
||||
})
|
||||
|
||||
|
||||
describe('when an error occurs', function(){
|
||||
it('should next(err)', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade');
|
||||
});
|
||||
|
||||
|
||||
app.use(function(err, req, res, next){
|
||||
res.end(err.message);
|
||||
});
|
||||
@@ -82,11 +82,11 @@ describe('res', function(){
|
||||
.expect(/user is not defined/, done);
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('when "view engine" is given', function(){
|
||||
it('should render the template', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
@@ -104,9 +104,9 @@ describe('res', function(){
|
||||
describe('.render(name, option)', function(){
|
||||
it('should render the template', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
|
||||
var user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
@@ -117,10 +117,10 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.expect('<p>tobi</p>', done);
|
||||
})
|
||||
|
||||
|
||||
it('should expose app.locals', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
@@ -132,10 +132,10 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.expect('<p>tobi</p>', done);
|
||||
})
|
||||
|
||||
|
||||
it('should expose res.locals', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
@@ -147,10 +147,10 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.expect('<p>tobi</p>', done);
|
||||
})
|
||||
|
||||
|
||||
it('should give precedence to res.locals over app.locals', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
@@ -166,10 +166,10 @@ describe('res', function(){
|
||||
|
||||
it('should give precedence to res.render() locals over res.locals', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
var jane = { name: 'jane' };
|
||||
|
||||
|
||||
app.use(function(req, res){
|
||||
res.locals.user = { name: 'tobi' };
|
||||
res.render('user.jade', { user: jane });
|
||||
@@ -179,14 +179,14 @@ describe('res', function(){
|
||||
.get('/')
|
||||
.expect('<p>jane</p>', done);
|
||||
})
|
||||
|
||||
|
||||
it('should give precedence to res.render() locals over app.locals', function(done){
|
||||
var app = express();
|
||||
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
var jane = { name: 'jane' };
|
||||
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade', { user: jane });
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('res', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
|
||||
describe('res', function(){
|
||||
@@ -42,7 +42,7 @@ describe('res', function(){
|
||||
app.use(function(req, res){
|
||||
res.sendfile('test/fixtures/nope.html', function(err){
|
||||
++calls;
|
||||
assert(!res.headerSent);
|
||||
assert(!res.headersSent);
|
||||
res.send(err.message);
|
||||
});
|
||||
});
|
||||
@@ -77,7 +77,7 @@ describe('res', function(){
|
||||
|
||||
app.use(function(req, res){
|
||||
res.sendfile('test/fixtures/foo/../user.html', function(err){
|
||||
assert(!res.headerSent);
|
||||
assert(!res.headersSent);
|
||||
++calls;
|
||||
res.send(err.message);
|
||||
});
|
||||
@@ -95,7 +95,7 @@ describe('res', function(){
|
||||
|
||||
app.use(function(req, res){
|
||||
res.sendfile('test/fixtures/user.html', function(err){
|
||||
assert(!res.headerSent);
|
||||
assert(!res.headersSent);
|
||||
req.socket.listeners('error').should.have.length(1); // node's original handler
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http')
|
||||
, request = require('supertest')
|
||||
, res = express.response;
|
||||
|
||||
describe('res', function(){
|
||||
@@ -45,7 +45,7 @@ describe('res', function(){
|
||||
JSON.stringify(res.get('ETag')).should.equal('["123","456"]');
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('.set(object)', function(){
|
||||
it('should set multiple fields', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.status(code)', function(){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('./support/http');
|
||||
, request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.type(str)', function(){
|
||||
|
||||
2
test/support/env.js
Normal file
2
test/support/env.js
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
process.env.NODE_ENV = 'test';
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
module.exports = require('supertest');
|
||||
Reference in New Issue
Block a user