mirror of
https://github.com/expressjs/express.git
synced 2026-02-26 18:57:43 +00:00
Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
011e5dc241 | ||
|
|
389ab1b19f | ||
|
|
279c8bbec3 | ||
|
|
6744f811b4 | ||
|
|
d7a6d709af | ||
|
|
ff44e0f9ae | ||
|
|
100e50f23d | ||
|
|
20c040db22 | ||
|
|
5d8a7a610f | ||
|
|
d34d60ce92 | ||
|
|
b2311c7402 | ||
|
|
9ca0c66e23 | ||
|
|
ef71373fa3 | ||
|
|
5873d335bd | ||
|
|
2e0f5e7817 | ||
|
|
20aa12616a | ||
|
|
bb4703e199 | ||
|
|
85755e32d9 | ||
|
|
b40e74d6b6 | ||
|
|
eaf3318dd3 | ||
|
|
e1057bd7fd | ||
|
|
f22937f3d1 | ||
|
|
69a4869db0 | ||
|
|
c2a6c8d338 | ||
|
|
2ce05047f8 | ||
|
|
829fa34581 | ||
|
|
3610fdce36 | ||
|
|
86328767fe | ||
|
|
e497d068a1 | ||
|
|
926a71f5ac | ||
|
|
55f5a2dc8d | ||
|
|
fe435e497e | ||
|
|
0c567b3282 | ||
|
|
855176b633 | ||
|
|
b95f2ee820 | ||
|
|
ae92db98f3 | ||
|
|
0b25547ca0 | ||
|
|
548f2865e2 | ||
|
|
ee3f2b073c | ||
|
|
34b6385dc3 | ||
|
|
11529a2ea0 | ||
|
|
b0f8809e3d | ||
|
|
ec1175daa3 | ||
|
|
3a1d9b8289 | ||
|
|
192be8fea3 | ||
|
|
1afcff955b | ||
|
|
224fe05697 | ||
|
|
2dd332b491 | ||
|
|
33e4193f45 | ||
|
|
c163d2f33d | ||
|
|
a715ba6be4 | ||
|
|
4405b849a9 | ||
|
|
5d74a553d6 | ||
|
|
262b60537f | ||
|
|
e77e644224 | ||
|
|
ce89c00cd9 | ||
|
|
d5ad34b0e9 | ||
|
|
ebfa00a9c0 | ||
|
|
d23417e6e8 | ||
|
|
91824514ce | ||
|
|
6c8bcd5c4e | ||
|
|
95e63ec287 | ||
|
|
ebca5887cc | ||
|
|
8535d3a990 | ||
|
|
13184c4379 | ||
|
|
eaba4eeb70 | ||
|
|
28c6952d1c | ||
|
|
01e3530a31 | ||
|
|
77c83d0c57 | ||
|
|
a12ae729bd | ||
|
|
d53a0cd91e | ||
|
|
88dfd36eaa | ||
|
|
5759b3e9f5 | ||
|
|
c939a771c0 | ||
|
|
af1043844f | ||
|
|
dd763ec5b8 | ||
|
|
9c2c21aaaf | ||
|
|
366000184f | ||
|
|
4d1ee23f84 | ||
|
|
0e5613363f | ||
|
|
7a7f18c20b | ||
|
|
b766aad112 | ||
|
|
7488e27609 | ||
|
|
bc9d854763 | ||
|
|
2e20a85810 | ||
|
|
a706408208 | ||
|
|
6d39d0f8a8 | ||
|
|
159ea67713 | ||
|
|
33959ed350 | ||
|
|
be478d348c | ||
|
|
9f292d873e | ||
|
|
ef3e95ca73 | ||
|
|
f45bd632df | ||
|
|
cc18da5cdf | ||
|
|
5603f86edd | ||
|
|
43e2cd79cb | ||
|
|
653270bb43 | ||
|
|
734bdf5ca1 | ||
|
|
341c1919d9 | ||
|
|
b09afad7b1 | ||
|
|
0e0b259556 | ||
|
|
63286e1192 | ||
|
|
c00f2f8596 | ||
|
|
f29399c4e1 | ||
|
|
f6ac068ab0 | ||
|
|
7eb65eeca2 | ||
|
|
178fe15091 | ||
|
|
381f278d0a | ||
|
|
534fa181c6 | ||
|
|
80847d8c82 | ||
|
|
4b1b8e420f | ||
|
|
70767b19ac | ||
|
|
7d277c1c15 | ||
|
|
fa1fcd9fec | ||
|
|
2de6514b4b | ||
|
|
d07c06363f | ||
|
|
4e97533fd2 | ||
|
|
d7d6219a1e | ||
|
|
9b18461bbc | ||
|
|
b77aa38c98 | ||
|
|
cbb251377e | ||
|
|
d6ed469de3 | ||
|
|
49284c236b | ||
|
|
be18487f7d | ||
|
|
094ff11949 | ||
|
|
b97f6eb506 | ||
|
|
3d188fe13e | ||
|
|
8327708ec2 | ||
|
|
c8640b3465 | ||
|
|
3ce5f9b493 | ||
|
|
4d032cda05 | ||
|
|
4127ba10b0 | ||
|
|
0299bee8fa | ||
|
|
6a581c9961 | ||
|
|
0b12cc0cac | ||
|
|
fdd0ccabe8 | ||
|
|
8c36eab679 | ||
|
|
5c145b5490 | ||
|
|
d7bef52591 | ||
|
|
1576a95e87 | ||
|
|
7f92fe66e0 | ||
|
|
f13f4652da | ||
|
|
059c068c7b | ||
|
|
49947f1476 | ||
|
|
0dddd772c0 | ||
|
|
0f87c6f392 | ||
|
|
7119f2b16d | ||
|
|
a57efea173 | ||
|
|
4a4ca7347a | ||
|
|
570f60d36e | ||
|
|
d13e613584 | ||
|
|
9204e1f42a | ||
|
|
ddac571fdf | ||
|
|
982d24b475 | ||
|
|
ea427c1bb4 | ||
|
|
0bd6c311cf | ||
|
|
7f606ebf29 | ||
|
|
c652cf7eed | ||
|
|
19fd6f85b0 | ||
|
|
b6c5b0511f | ||
|
|
0e42a37edd | ||
|
|
b24ed15878 | ||
|
|
15590d75b2 | ||
|
|
e8b471ff4f | ||
|
|
767db01b79 |
38
.gitignore
vendored
38
.gitignore
vendored
@@ -1,16 +1,26 @@
|
||||
coverage/
|
||||
.DS_Store
|
||||
*.seed
|
||||
# OS X
|
||||
.DS_Store*
|
||||
Icon?
|
||||
._*
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# Linux
|
||||
.directory
|
||||
*~
|
||||
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
*.log
|
||||
*.csv
|
||||
*.dat
|
||||
*.out
|
||||
*.pid
|
||||
*.swp
|
||||
*.swo
|
||||
*.gz
|
||||
|
||||
|
||||
# Coveralls
|
||||
coverage
|
||||
|
||||
# Benchmarking
|
||||
benchmarks/graphs
|
||||
testing
|
||||
node_modules/
|
||||
testing
|
||||
test.js
|
||||
.idea
|
||||
|
||||
10
.npmignore
10
.npmignore
@@ -1,10 +0,0 @@
|
||||
.git*
|
||||
benchmarks/
|
||||
coverage/
|
||||
docs/
|
||||
examples/
|
||||
support/
|
||||
test/
|
||||
testing.js
|
||||
.DS_Store
|
||||
.travis.yml
|
||||
@@ -2,10 +2,8 @@ language: node_js
|
||||
node_js:
|
||||
- "0.8"
|
||||
- "0.10"
|
||||
- "0.11"
|
||||
matrix:
|
||||
allow_failures:
|
||||
- node_js: "0.11"
|
||||
fast_finish: true
|
||||
- "0.12"
|
||||
sudo: false
|
||||
before_install: "npm rm --save-dev connect-redis"
|
||||
script: "npm run-script test-travis"
|
||||
after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls"
|
||||
|
||||
429
History.md
429
History.md
@@ -1,3 +1,432 @@
|
||||
3.20.2 / 2015-03-16
|
||||
===================
|
||||
|
||||
* deps: connect@2.29.1
|
||||
- deps: body-parser@~1.12.2
|
||||
- deps: compression@~1.4.3
|
||||
- deps: connect-timeout@~1.6.1
|
||||
- deps: debug@~2.1.3
|
||||
- deps: errorhandler@~1.3.5
|
||||
- deps: express-session@~1.10.4
|
||||
- deps: finalhandler@0.3.4
|
||||
- deps: method-override@~2.3.2
|
||||
- deps: morgan@~1.5.2
|
||||
- deps: qs@2.4.1
|
||||
- deps: serve-index@~1.6.3
|
||||
- deps: serve-static@~1.9.2
|
||||
- deps: type-is@~1.6.1
|
||||
* deps: debug@~2.1.3
|
||||
- Fix high intensity foreground color for bold
|
||||
- deps: ms@0.7.0
|
||||
* deps: merge-descriptors@1.0.0
|
||||
* deps: proxy-addr@~1.0.7
|
||||
- deps: ipaddr.js@0.1.9
|
||||
* deps: send@0.12.2
|
||||
- Throw errors early for invalid `extensions` or `index` options
|
||||
- deps: debug@~2.1.3
|
||||
|
||||
3.20.1 / 2015-02-28
|
||||
===================
|
||||
|
||||
* Fix `req.host` when using "trust proxy" hops count
|
||||
* Fix `req.protocol`/`req.secure` when using "trust proxy" hops count
|
||||
|
||||
3.20.0 / 2015-02-18
|
||||
===================
|
||||
|
||||
* Fix `"trust proxy"` setting to inherit when app is mounted
|
||||
* Generate `ETag`s for all request responses
|
||||
- No longer restricted to only responses for `GET` and `HEAD` requests
|
||||
* Use `content-type` to parse `Content-Type` headers
|
||||
* deps: connect@2.29.0
|
||||
- Use `content-type` to parse `Content-Type` headers
|
||||
- deps: body-parser@~1.12.0
|
||||
- deps: compression@~1.4.1
|
||||
- deps: connect-timeout@~1.6.0
|
||||
- deps: cookie-parser@~1.3.4
|
||||
- deps: cookie-signature@1.0.6
|
||||
- deps: csurf@~1.7.0
|
||||
- deps: errorhandler@~1.3.4
|
||||
- deps: express-session@~1.10.3
|
||||
- deps: http-errors@~1.3.1
|
||||
- deps: response-time@~2.3.0
|
||||
- deps: serve-index@~1.6.2
|
||||
- deps: serve-static@~1.9.1
|
||||
- deps: type-is@~1.6.0
|
||||
* deps: cookie-signature@1.0.6
|
||||
* deps: send@0.12.1
|
||||
- Always read the stat size from the file
|
||||
- Fix mutating passed-in `options`
|
||||
- deps: mime@1.3.4
|
||||
|
||||
3.19.2 / 2015-02-01
|
||||
===================
|
||||
|
||||
* deps: connect@2.28.3
|
||||
- deps: compression@~1.3.1
|
||||
- deps: csurf@~1.6.6
|
||||
- deps: errorhandler@~1.3.3
|
||||
- deps: express-session@~1.10.2
|
||||
- deps: serve-index@~1.6.1
|
||||
- deps: type-is@~1.5.6
|
||||
* deps: proxy-addr@~1.0.6
|
||||
- deps: ipaddr.js@0.1.8
|
||||
|
||||
3.19.1 / 2015-01-20
|
||||
===================
|
||||
|
||||
* deps: connect@2.28.2
|
||||
- deps: body-parser@~1.10.2
|
||||
- deps: serve-static@~1.8.1
|
||||
* deps: send@0.11.1
|
||||
- Fix root path disclosure
|
||||
|
||||
3.19.0 / 2015-01-09
|
||||
===================
|
||||
|
||||
* Fix `OPTIONS` responses to include the `HEAD` method property
|
||||
* Use `readline` for prompt in `express(1)`
|
||||
* deps: commander@2.6.0
|
||||
* deps: connect@2.28.1
|
||||
- deps: body-parser@~1.10.1
|
||||
- deps: compression@~1.3.0
|
||||
- deps: connect-timeout@~1.5.0
|
||||
- deps: csurf@~1.6.4
|
||||
- deps: debug@~2.1.1
|
||||
- deps: errorhandler@~1.3.2
|
||||
- deps: express-session@~1.10.1
|
||||
- deps: finalhandler@0.3.3
|
||||
- deps: method-override@~2.3.1
|
||||
- deps: morgan@~1.5.1
|
||||
- deps: serve-favicon@~2.2.0
|
||||
- deps: serve-index@~1.6.0
|
||||
- deps: serve-static@~1.8.0
|
||||
- deps: type-is@~1.5.5
|
||||
* deps: debug@~2.1.1
|
||||
* deps: methods@~1.1.1
|
||||
* deps: proxy-addr@~1.0.5
|
||||
- deps: ipaddr.js@0.1.6
|
||||
* deps: send@0.11.0
|
||||
- deps: debug@~2.1.1
|
||||
- deps: etag@~1.5.1
|
||||
- deps: ms@0.7.0
|
||||
- deps: on-finished@~2.2.0
|
||||
|
||||
3.18.6 / 2014-12-12
|
||||
===================
|
||||
|
||||
* Fix exception in `req.fresh`/`req.stale` without response headers
|
||||
|
||||
3.18.5 / 2014-12-11
|
||||
===================
|
||||
|
||||
* deps: connect@2.27.6
|
||||
- deps: compression@~1.2.2
|
||||
- deps: express-session@~1.9.3
|
||||
- deps: http-errors@~1.2.8
|
||||
- deps: serve-index@~1.5.3
|
||||
- deps: type-is@~1.5.4
|
||||
|
||||
3.18.4 / 2014-11-23
|
||||
===================
|
||||
|
||||
* deps: connect@2.27.4
|
||||
- deps: body-parser@~1.9.3
|
||||
- deps: compression@~1.2.1
|
||||
- deps: errorhandler@~1.2.3
|
||||
- deps: express-session@~1.9.2
|
||||
- deps: qs@2.3.3
|
||||
- deps: serve-favicon@~2.1.7
|
||||
- deps: serve-static@~1.5.1
|
||||
- deps: type-is@~1.5.3
|
||||
* deps: etag@~1.5.1
|
||||
* deps: proxy-addr@~1.0.4
|
||||
- deps: ipaddr.js@0.1.5
|
||||
|
||||
3.18.3 / 2014-11-09
|
||||
===================
|
||||
|
||||
* deps: connect@2.27.3
|
||||
- Correctly invoke async callback asynchronously
|
||||
- deps: csurf@~1.6.3
|
||||
|
||||
3.18.2 / 2014-10-28
|
||||
===================
|
||||
|
||||
* deps: connect@2.27.2
|
||||
- Fix handling of URLs containing `://` in the path
|
||||
- deps: body-parser@~1.9.2
|
||||
- deps: qs@2.3.2
|
||||
|
||||
3.18.1 / 2014-10-22
|
||||
===================
|
||||
|
||||
* Fix internal `utils.merge` deprecation warnings
|
||||
* deps: connect@2.27.1
|
||||
- deps: body-parser@~1.9.1
|
||||
- deps: express-session@~1.9.1
|
||||
- deps: finalhandler@0.3.2
|
||||
- deps: morgan@~1.4.1
|
||||
- deps: qs@2.3.0
|
||||
- deps: serve-static@~1.7.1
|
||||
* deps: send@0.10.1
|
||||
- deps: on-finished@~2.1.1
|
||||
|
||||
3.18.0 / 2014-10-17
|
||||
===================
|
||||
|
||||
* Use `content-disposition` module for `res.attachment`/`res.download`
|
||||
- Sends standards-compliant `Content-Disposition` header
|
||||
- Full Unicode support
|
||||
* Use `etag` module to generate `ETag` headers
|
||||
* deps: connect@2.27.0
|
||||
- Use `http-errors` module for creating errors
|
||||
- Use `utils-merge` module for merging objects
|
||||
- deps: body-parser@~1.9.0
|
||||
- deps: compression@~1.2.0
|
||||
- deps: connect-timeout@~1.4.0
|
||||
- deps: debug@~2.1.0
|
||||
- deps: depd@~1.0.0
|
||||
- deps: express-session@~1.9.0
|
||||
- deps: finalhandler@0.3.1
|
||||
- deps: method-override@~2.3.0
|
||||
- deps: morgan@~1.4.0
|
||||
- deps: response-time@~2.2.0
|
||||
- deps: serve-favicon@~2.1.6
|
||||
- deps: serve-index@~1.5.0
|
||||
- deps: serve-static@~1.7.0
|
||||
* deps: debug@~2.1.0
|
||||
- Implement `DEBUG_FD` env variable support
|
||||
* deps: depd@~1.0.0
|
||||
* deps: send@0.10.0
|
||||
- deps: debug@~2.1.0
|
||||
- deps: depd@~1.0.0
|
||||
- deps: etag@~1.5.0
|
||||
|
||||
3.17.8 / 2014-10-15
|
||||
===================
|
||||
|
||||
* deps: connect@2.26.6
|
||||
- deps: compression@~1.1.2
|
||||
- deps: csurf@~1.6.2
|
||||
- deps: errorhandler@~1.2.2
|
||||
|
||||
3.17.7 / 2014-10-08
|
||||
===================
|
||||
|
||||
* deps: connect@2.26.5
|
||||
- Fix accepting non-object arguments to `logger`
|
||||
- deps: serve-static@~1.6.4
|
||||
|
||||
3.17.6 / 2014-10-02
|
||||
===================
|
||||
|
||||
* deps: connect@2.26.4
|
||||
- deps: morgan@~1.3.2
|
||||
- deps: type-is@~1.5.2
|
||||
|
||||
3.17.5 / 2014-09-24
|
||||
===================
|
||||
|
||||
* deps: connect@2.26.3
|
||||
- deps: body-parser@~1.8.4
|
||||
- deps: serve-favicon@~2.1.5
|
||||
- deps: serve-static@~1.6.3
|
||||
* deps: proxy-addr@~1.0.3
|
||||
- Use `forwarded` npm module
|
||||
* deps: send@0.9.3
|
||||
- deps: etag@~1.4.0
|
||||
|
||||
3.17.4 / 2014-09-19
|
||||
===================
|
||||
|
||||
* deps: connect@2.26.2
|
||||
- deps: body-parser@~1.8.3
|
||||
- deps: qs@2.2.4
|
||||
|
||||
3.17.3 / 2014-09-18
|
||||
===================
|
||||
|
||||
* deps: proxy-addr@~1.0.2
|
||||
- Fix a global leak when multiple subnets are trusted
|
||||
- deps: ipaddr.js@0.1.3
|
||||
|
||||
3.17.2 / 2014-09-15
|
||||
===================
|
||||
|
||||
* Use `crc` instead of `buffer-crc32` for speed
|
||||
* deps: connect@2.26.1
|
||||
- deps: body-parser@~1.8.2
|
||||
- deps: depd@0.4.5
|
||||
- deps: express-session@~1.8.2
|
||||
- deps: morgan@~1.3.1
|
||||
- deps: serve-favicon@~2.1.3
|
||||
- deps: serve-static@~1.6.2
|
||||
* deps: depd@0.4.5
|
||||
* deps: send@0.9.2
|
||||
- deps: depd@0.4.5
|
||||
- deps: etag@~1.3.1
|
||||
- deps: range-parser@~1.0.2
|
||||
|
||||
3.17.1 / 2014-09-08
|
||||
===================
|
||||
|
||||
* Fix error in `req.subdomains` on empty host
|
||||
|
||||
3.17.0 / 2014-09-08
|
||||
===================
|
||||
|
||||
* Support IP address host in `req.subdomains`
|
||||
* deps: connect@2.26.0
|
||||
- deps: body-parser@~1.8.1
|
||||
- deps: compression@~1.1.0
|
||||
- deps: connect-timeout@~1.3.0
|
||||
- deps: cookie-parser@~1.3.3
|
||||
- deps: cookie-signature@1.0.5
|
||||
- deps: csurf@~1.6.1
|
||||
- deps: debug@~2.0.0
|
||||
- deps: errorhandler@~1.2.0
|
||||
- deps: express-session@~1.8.1
|
||||
- deps: finalhandler@0.2.0
|
||||
- deps: fresh@0.2.4
|
||||
- deps: media-typer@0.3.0
|
||||
- deps: method-override@~2.2.0
|
||||
- deps: morgan@~1.3.0
|
||||
- deps: qs@2.2.3
|
||||
- deps: serve-favicon@~2.1.3
|
||||
- deps: serve-index@~1.2.1
|
||||
- deps: serve-static@~1.6.1
|
||||
- deps: type-is@~1.5.1
|
||||
- deps: vhost@~3.0.0
|
||||
* deps: cookie-signature@1.0.5
|
||||
* deps: debug@~2.0.0
|
||||
* deps: fresh@0.2.4
|
||||
* deps: media-typer@0.3.0
|
||||
- Throw error when parameter format invalid on parse
|
||||
* deps: range-parser@~1.0.2
|
||||
* deps: send@0.9.1
|
||||
- Add `lastModified` option
|
||||
- Use `etag` to generate `ETag` header
|
||||
- deps: debug@~2.0.0
|
||||
- deps: fresh@0.2.4
|
||||
* deps: vary@~1.0.0
|
||||
- Accept valid `Vary` header string as `field`
|
||||
|
||||
3.16.10 / 2014-09-04
|
||||
====================
|
||||
|
||||
* deps: connect@2.25.10
|
||||
- deps: serve-static@~1.5.4
|
||||
* deps: send@0.8.5
|
||||
- Fix a path traversal issue when using `root`
|
||||
- Fix malicious path detection for empty string path
|
||||
|
||||
3.16.9 / 2014-08-29
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.9
|
||||
- deps: body-parser@~1.6.7
|
||||
- deps: qs@2.2.2
|
||||
|
||||
3.16.8 / 2014-08-27
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.8
|
||||
- deps: body-parser@~1.6.6
|
||||
- deps: csurf@~1.4.1
|
||||
- deps: qs@2.2.0
|
||||
|
||||
3.16.7 / 2014-08-18
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.7
|
||||
- deps: body-parser@~1.6.5
|
||||
- deps: express-session@~1.7.6
|
||||
- deps: morgan@~1.2.3
|
||||
- deps: serve-static@~1.5.3
|
||||
* deps: send@0.8.3
|
||||
- deps: destroy@1.0.3
|
||||
- deps: on-finished@2.1.0
|
||||
|
||||
3.16.6 / 2014-08-14
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.6
|
||||
- deps: body-parser@~1.6.4
|
||||
- deps: qs@1.2.2
|
||||
- deps: serve-static@~1.5.2
|
||||
* deps: send@0.8.2
|
||||
- Work around `fd` leak in Node.js 0.10 for `fs.ReadStream`
|
||||
|
||||
3.16.5 / 2014-08-11
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.5
|
||||
- Fix backwards compatibility in `logger`
|
||||
|
||||
3.16.4 / 2014-08-10
|
||||
===================
|
||||
|
||||
* Fix original URL parsing in `res.location`
|
||||
* deps: connect@2.25.4
|
||||
- Fix `query` middleware breaking with argument
|
||||
- deps: body-parser@~1.6.3
|
||||
- deps: compression@~1.0.11
|
||||
- deps: connect-timeout@~1.2.2
|
||||
- deps: express-session@~1.7.5
|
||||
- deps: method-override@~2.1.3
|
||||
- deps: on-headers@~1.0.0
|
||||
- deps: parseurl@~1.3.0
|
||||
- deps: qs@1.2.1
|
||||
- deps: response-time@~2.0.1
|
||||
- deps: serve-index@~1.1.6
|
||||
- deps: serve-static@~1.5.1
|
||||
* deps: parseurl@~1.3.0
|
||||
|
||||
3.16.3 / 2014-08-07
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.3
|
||||
- deps: multiparty@3.3.2
|
||||
|
||||
3.16.2 / 2014-08-07
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.2
|
||||
- deps: body-parser@~1.6.2
|
||||
- deps: qs@1.2.0
|
||||
|
||||
3.16.1 / 2014-08-06
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.1
|
||||
- deps: body-parser@~1.6.1
|
||||
- deps: qs@1.1.0
|
||||
|
||||
3.16.0 / 2014-08-05
|
||||
===================
|
||||
|
||||
* deps: connect@2.25.0
|
||||
- deps: body-parser@~1.6.0
|
||||
- deps: compression@~1.0.10
|
||||
- deps: csurf@~1.4.0
|
||||
- deps: express-session@~1.7.4
|
||||
- deps: qs@1.0.2
|
||||
- deps: serve-static@~1.5.0
|
||||
* deps: send@0.8.1
|
||||
- Add `extensions` option
|
||||
|
||||
3.15.3 / 2014-08-04
|
||||
===================
|
||||
|
||||
* fix `res.sendfile` regression for serving directory index files
|
||||
* deps: connect@2.24.3
|
||||
- deps: serve-index@~1.1.5
|
||||
- deps: serve-static@~1.4.4
|
||||
* deps: send@0.7.4
|
||||
- Fix incorrect 403 on Windows and Node.js 0.11
|
||||
- Fix serving index files without root dir
|
||||
|
||||
3.15.2 / 2014-07-27
|
||||
===================
|
||||
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,8 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2009-2013 TJ Holowaychuk <tj@vision-media.ca>
|
||||
Copyright (c) 2013 Roman Shtylman <shtylman+expressjs@gmail.com>
|
||||
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
16
Readme.md
16
Readme.md
@@ -2,10 +2,10 @@
|
||||
|
||||
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
|
||||
|
||||
[](http://badge.fury.io/js/express)
|
||||
[](https://travis-ci.org/visionmedia/express)
|
||||
[](https://coveralls.io/r/visionmedia/express)
|
||||
[](https://www.gittip.com/dougwilson/)
|
||||
[](https://www.npmjs.org/package/express)
|
||||
[](https://travis-ci.org/strongloop/express)
|
||||
[](https://coveralls.io/r/strongloop/express)
|
||||
[](https://gratipay.com/dougwilson/)
|
||||
|
||||
```js
|
||||
var express = require('express');
|
||||
@@ -65,11 +65,11 @@ app.listen(3000);
|
||||
|
||||
## More Information
|
||||
|
||||
* [Website and Documentation](http://expressjs.com/) stored at [visionmedia/expressjs.com](https://github.com/visionmedia/expressjs.com)
|
||||
* [Website and Documentation](http://expressjs.com/) stored at [strongloop/expressjs.com](https://github.com/strongloop/expressjs.com)
|
||||
* Join #express on freenode
|
||||
* [Google Group](http://groups.google.com/group/express-js) for discussion
|
||||
* Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) on twitter for updates
|
||||
* Visit the [Wiki](http://github.com/visionmedia/express/wiki)
|
||||
* Visit the [Wiki](http://github.com/strongloop/express/wiki)
|
||||
* [Русскоязычная документация](http://jsman.ru/express/)
|
||||
* Run express examples [online](https://runnable.com/express)
|
||||
|
||||
@@ -77,7 +77,7 @@ app.listen(3000);
|
||||
|
||||
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
|
||||
$ git clone git://github.com/strongloop/express.git --depth 1
|
||||
$ cd express
|
||||
$ npm install
|
||||
|
||||
@@ -103,7 +103,7 @@ $ npm test
|
||||
|
||||
## Contributors
|
||||
|
||||
https://github.com/visionmedia/express/graphs/contributors
|
||||
https://github.com/strongloop/express/graphs/contributors
|
||||
|
||||
## License
|
||||
|
||||
|
||||
19
bin/express
19
bin/express
@@ -7,6 +7,7 @@
|
||||
var program = require('commander')
|
||||
, mkdirp = require('mkdirp')
|
||||
, pkg = require('../package.json')
|
||||
, readline = require('readline')
|
||||
, version = pkg.version
|
||||
, os = require('os')
|
||||
, fs = require('fs');
|
||||
@@ -249,7 +250,7 @@ var app = [
|
||||
if (empty || program.force) {
|
||||
createApplicationAt(path);
|
||||
} else {
|
||||
program.confirm('destination is not empty, continue? ', function(ok){
|
||||
confirm('destination is not empty, continue? [y/N] ', function (ok) {
|
||||
if (ok) {
|
||||
process.stdin.destroy();
|
||||
createApplicationAt(path);
|
||||
@@ -261,6 +262,22 @@ var app = [
|
||||
});
|
||||
})(path);
|
||||
|
||||
/**
|
||||
* Prompt for confirmation on STDOUT/STDIN
|
||||
*/
|
||||
|
||||
function confirm(msg, callback) {
|
||||
var rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
rl.question(msg, function (input) {
|
||||
rl.close();
|
||||
callback(/^y|yes|ok|true$/i.test(input));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create application at the given directory `path`.
|
||||
*
|
||||
|
||||
@@ -8,7 +8,7 @@ var express = require('../../')
|
||||
|
||||
// general config
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
// our custom "verbose errors" setting
|
||||
// which we can use in the templates
|
||||
@@ -82,7 +82,7 @@ app.use(function(err, req, res, next){
|
||||
// Routes
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index.jade');
|
||||
res.render('index.ejs');
|
||||
});
|
||||
|
||||
app.get('/404', function(req, res, next){
|
||||
|
||||
3
examples/error-pages/views/404.ejs
Normal file
3
examples/error-pages/views/404.ejs
Normal file
@@ -0,0 +1,3 @@
|
||||
<% include error_header %>
|
||||
<h2>Cannot find <%= url %></h2>
|
||||
<% include footer %>
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
extends error
|
||||
|
||||
block content
|
||||
h2 Cannot find #{url}
|
||||
8
examples/error-pages/views/500.ejs
Normal file
8
examples/error-pages/views/500.ejs
Normal file
@@ -0,0 +1,8 @@
|
||||
<% include error_header %>
|
||||
<h2>Error: <%= error.message %></h2>
|
||||
<% if (settings['verbose errors']) { %>
|
||||
<pre><%= error.stack %></pre>
|
||||
<% } else { %>
|
||||
<p>An error occurred!</p>
|
||||
<% } %>
|
||||
<% include footer %>
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
// note that we extend a different
|
||||
// layout with jade for 4xx & 5xx
|
||||
// responses
|
||||
|
||||
extends error
|
||||
|
||||
block content
|
||||
h1 Error: #{error.message}
|
||||
if settings['verbose errors']
|
||||
pre= error.stack
|
||||
else
|
||||
p An error ocurred!
|
||||
@@ -1,6 +0,0 @@
|
||||
html
|
||||
head
|
||||
title Error
|
||||
body
|
||||
h1 An error occurred!
|
||||
block content
|
||||
8
examples/error-pages/views/error_header.ejs
Normal file
8
examples/error-pages/views/error_header.ejs
Normal file
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Error</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>An error occurred!</h1>
|
||||
2
examples/error-pages/views/footer.ejs
Normal file
2
examples/error-pages/views/footer.ejs
Normal file
@@ -0,0 +1,2 @@
|
||||
</body>
|
||||
</html>
|
||||
18
examples/error-pages/views/index.ejs
Normal file
18
examples/error-pages/views/index.ejs
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Custom Pages Example</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>My Site</h1>
|
||||
<h2>Pages Example</h2>
|
||||
|
||||
<ul>
|
||||
<li>visit <a href="/500">500</a></li>
|
||||
<li>visit <a href="/404">404</a></li>
|
||||
<li>visit <a href="/403">403</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
extends layout
|
||||
|
||||
block content
|
||||
h2 Pages Example
|
||||
ul
|
||||
li
|
||||
| visit
|
||||
a(href="/500") 500
|
||||
li
|
||||
| visit
|
||||
a(href="/404") 404
|
||||
li
|
||||
| visit
|
||||
a(href='/403') 403
|
||||
@@ -1,6 +0,0 @@
|
||||
html
|
||||
head
|
||||
title Custom Pages Example
|
||||
body
|
||||
h1 My Site
|
||||
block content
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
var db = require('../../db');
|
||||
|
||||
exports.engine = 'jade';
|
||||
exports.engine = 'ejs';
|
||||
|
||||
exports.before = function(req, res, next){
|
||||
var pet = db.pets[req.params.pet_id];
|
||||
|
||||
16
examples/mvc/controllers/pet/views/edit.ejs
Normal file
16
examples/mvc/controllers/pet/views/edit.ejs
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<title>Edit <%= pet.name %></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><%= pet.name %></h1>
|
||||
<form action="/pet/<%= pet.id %>" method="post">
|
||||
<input type="hidden" name="_method" value="put">
|
||||
<label>Name: <input type="text" name="user[name]" value="<%= pet.name %>"></label>
|
||||
<input type="submit" value="Update">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,7 +0,0 @@
|
||||
link(rel='stylesheet', href='/style.css')
|
||||
h1= pet.name
|
||||
form(action='/pet/#{pet.id}', method='post')
|
||||
input(type='hidden', name='_method', value='put')
|
||||
label Name:
|
||||
input(type='text', name='user[name]', value=pet.name)
|
||||
input(type='submit', value='Update')
|
||||
13
examples/mvc/controllers/pet/views/show.ejs
Normal file
13
examples/mvc/controllers/pet/views/show.ejs
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
<title><%= pet.name %></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1><%= pet.name %> <a href="/pet/<%= pet.id %>/edit">edit</a></h1>
|
||||
|
||||
<p>You are viewing <%= pet.name %></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +0,0 @@
|
||||
link(rel='stylesheet', href='/style.css')
|
||||
|
||||
h1= pet.name
|
||||
a(href='/pet/#{pet.id}/edit') edit
|
||||
|
||||
p You are viewing #{pet.name}
|
||||
@@ -35,13 +35,13 @@ function GithubView(name, options){
|
||||
GithubView.prototype.render = function(options, fn){
|
||||
var self = this;
|
||||
var opts = {
|
||||
host: 'rawgithub.com',
|
||||
port: 80,
|
||||
host: 'raw.githubusercontent.com',
|
||||
port: 443,
|
||||
path: this.path,
|
||||
method: 'GET'
|
||||
};
|
||||
|
||||
http.request(opts, function(res) {
|
||||
https.request(opts, function(res) {
|
||||
var buf = '';
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(str){ buf += str });
|
||||
|
||||
@@ -24,7 +24,7 @@ app.engine('md', function(str, options, fn){
|
||||
})
|
||||
|
||||
// pointing to a particular github repo to load files from it
|
||||
app.set('views', 'visionmedia/express');
|
||||
app.set('views', 'strongloop/express');
|
||||
|
||||
// register a new view constructor
|
||||
app.set('view', GithubView);
|
||||
@@ -37,7 +37,7 @@ app.get('/', function(req, res){
|
||||
})
|
||||
|
||||
app.get('/Readme.md', function(req, res){
|
||||
// rendering a view from https://github.com/visionmedia/express/blob/master/Readme.md
|
||||
// rendering a view from https://github.com/strongloop/express/blob/master/Readme.md
|
||||
res.render('Readme.md');
|
||||
})
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ var apiKeys = ['foo', 'bar', 'baz'];
|
||||
// these two objects will serve as our faux database
|
||||
|
||||
var repos = [
|
||||
{ name: 'express', url: 'http://github.com/visionmedia/express' }
|
||||
{ name: 'express', url: 'http://github.com/strongloop/express' }
|
||||
, { name: 'stylus', url: 'http://github.com/learnboost/stylus' }
|
||||
, { name: 'cluster', url: 'http://github.com/learnboost/cluster' }
|
||||
];
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
/*!
|
||||
* express
|
||||
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||
* Copyright(c) 2013 Roman Shtylman
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var connect = require('connect')
|
||||
@@ -11,9 +20,9 @@ var connect = require('connect')
|
||||
, compileETag = require('./utils').compileETag
|
||||
, compileTrust = require('./utils').compileTrust
|
||||
, View = require('./view')
|
||||
, utils = connect.utils
|
||||
, http = require('http');
|
||||
var deprecate = require('depd')('express');
|
||||
var merge = require('utils-merge');
|
||||
|
||||
/**
|
||||
* Application prototype.
|
||||
@@ -21,6 +30,13 @@ var deprecate = require('depd')('express');
|
||||
|
||||
var app = exports = module.exports = {};
|
||||
|
||||
/**
|
||||
* Variable for trust proxy inheritance back-compat
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';
|
||||
|
||||
/**
|
||||
* Initialize the server.
|
||||
*
|
||||
@@ -53,14 +69,27 @@ app.defaultConfiguration = function(){
|
||||
this.set('subdomain offset', 2);
|
||||
this.set('trust proxy', false);
|
||||
|
||||
// trust proxy inherit back-compat
|
||||
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
|
||||
configurable: true,
|
||||
value: true
|
||||
});
|
||||
|
||||
debug('booting in %s mode', env);
|
||||
|
||||
// implicit middleware
|
||||
this.use(connect.query());
|
||||
this.use(middleware.init(this));
|
||||
|
||||
// inherit protos
|
||||
this.on('mount', function(parent){
|
||||
this.on('mount', function onmount(parent) {
|
||||
// inherit trust proxy
|
||||
if (this.settings[trustProxyDefaultSymbol] === true
|
||||
&& typeof parent.settings['trust proxy fn'] === 'function') {
|
||||
delete this.settings['trust proxy'];
|
||||
delete this.settings['trust proxy fn'];
|
||||
}
|
||||
|
||||
// inherit protos
|
||||
this.request.__proto__ = parent.request;
|
||||
this.response.__proto__ = parent.response;
|
||||
this.engines.__proto__ = parent.engines;
|
||||
@@ -271,6 +300,13 @@ app.set = function(setting, val){
|
||||
case 'trust proxy':
|
||||
debug('compile trust proxy %s', val);
|
||||
this.set('trust proxy fn', compileTrust(val));
|
||||
|
||||
// trust proxy inherit back-compat
|
||||
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
|
||||
configurable: true,
|
||||
value: false
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -484,13 +520,15 @@ app.render = function(name, options, fn){
|
||||
}
|
||||
|
||||
// merge app.locals
|
||||
utils.merge(opts, this.locals);
|
||||
merge(opts, this.locals);
|
||||
|
||||
// merge options._locals
|
||||
if (options._locals) utils.merge(opts, options._locals);
|
||||
if (options._locals) {
|
||||
merge(opts, options._locals);
|
||||
}
|
||||
|
||||
// merge options
|
||||
utils.merge(opts, options);
|
||||
merge(opts, options);
|
||||
|
||||
// set .cache unless explicitly provided
|
||||
opts.cache = null == opts.cache
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
*/
|
||||
|
||||
var deprecate = require('depd')('express');
|
||||
var merge = require('merge-descriptors');
|
||||
var mixin = require('merge-descriptors');
|
||||
var merge = require('utils-merge');
|
||||
var connect = require('connect')
|
||||
, proto = require('./application')
|
||||
, Route = require('./router/route')
|
||||
, Router = require('./router')
|
||||
, req = require('./request')
|
||||
, res = require('./response')
|
||||
, utils = connect.utils;
|
||||
, res = require('./response');
|
||||
|
||||
/**
|
||||
* Expose `createApplication()`.
|
||||
@@ -33,7 +33,7 @@ exports.mime = connect.mime;
|
||||
|
||||
function createApplication() {
|
||||
var app = connect();
|
||||
utils.merge(app, proto);
|
||||
merge(app, proto);
|
||||
app.request = { __proto__: req, app: app };
|
||||
app.response = { __proto__: res, app: app };
|
||||
app.init();
|
||||
@@ -45,7 +45,7 @@ function createApplication() {
|
||||
* for example `express.logger` etc.
|
||||
*/
|
||||
|
||||
merge(exports, connect.middleware);
|
||||
mixin(exports, connect.middleware);
|
||||
|
||||
/**
|
||||
* Deprecated createServer().
|
||||
|
||||
@@ -13,6 +13,7 @@ var http = require('http')
|
||||
, parse = require('parseurl')
|
||||
, proxyaddr = require('proxy-addr')
|
||||
, mime = connect.mime;
|
||||
var isIP = require('net').isIP;
|
||||
|
||||
/**
|
||||
* Request prototype.
|
||||
@@ -357,7 +358,7 @@ req.__defineGetter__('protocol', function(){
|
||||
: 'http';
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
|
||||
if (!trust(this.connection.remoteAddress)) {
|
||||
if (!trust(this.connection.remoteAddress, 0)) {
|
||||
return proto;
|
||||
}
|
||||
|
||||
@@ -452,11 +453,16 @@ req.__defineGetter__('auth', function(){
|
||||
*/
|
||||
|
||||
req.__defineGetter__('subdomains', function(){
|
||||
var host = this.host;
|
||||
|
||||
if (!host) return [];
|
||||
|
||||
var offset = this.app.get('subdomain offset');
|
||||
return (this.host || '')
|
||||
.split('.')
|
||||
.reverse()
|
||||
.slice(offset);
|
||||
var subdomains = !isIP(host)
|
||||
? host.split('.').reverse()
|
||||
: [host];
|
||||
|
||||
return subdomains.slice(offset);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -485,7 +491,7 @@ req.__defineGetter__('host', function(){
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
var host = this.get('X-Forwarded-Host');
|
||||
|
||||
if (!host || !trust(this.connection.remoteAddress)) {
|
||||
if (!host || !trust(this.connection.remoteAddress, 0)) {
|
||||
host = this.get('Host');
|
||||
}
|
||||
|
||||
@@ -520,7 +526,7 @@ req.__defineGetter__('fresh', function(){
|
||||
|
||||
// 2xx or 304 as per rfc2616 14.26
|
||||
if ((s >= 200 && s < 300) || 304 == s) {
|
||||
return fresh(this.headers, this.res._headers);
|
||||
return fresh(this.headers, (this.res._headers || {}));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
/*!
|
||||
* express
|
||||
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var contentDisposition = require('content-disposition');
|
||||
var deprecate = require('depd')('express');
|
||||
var escapeHtml = require('escape-html');
|
||||
var merge = require('utils-merge');
|
||||
var parseUrl = require('parseurl');
|
||||
var vary = require('vary');
|
||||
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
|
||||
@@ -84,7 +94,6 @@ res.links = function(links){
|
||||
|
||||
res.send = function(body){
|
||||
var req = this.req;
|
||||
var head = 'HEAD' == req.method;
|
||||
var type;
|
||||
var encoding;
|
||||
var len;
|
||||
@@ -151,12 +160,12 @@ res.send = function(body){
|
||||
this.set('Content-Length', len);
|
||||
}
|
||||
|
||||
// ETag support
|
||||
var etag = len !== undefined && app.get('etag fn');
|
||||
if (etag && ('GET' === req.method || 'HEAD' === req.method)) {
|
||||
if (!this.get('ETag')) {
|
||||
etag = etag(body, encoding);
|
||||
etag && this.set('ETag', etag);
|
||||
// populate ETag
|
||||
var etag;
|
||||
var generateETag = len !== undefined && app.get('etag fn');
|
||||
if (typeof generateETag === 'function' && !this.get('ETag')) {
|
||||
if ((etag = generateETag(body, encoding))) {
|
||||
this.set('ETag', etag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,8 +180,13 @@ res.send = function(body){
|
||||
body = '';
|
||||
}
|
||||
|
||||
// respond
|
||||
this.end((head ? null : body), encoding);
|
||||
if (req.method === 'HEAD') {
|
||||
// skip body for HEAD
|
||||
this.end();
|
||||
} else {
|
||||
// respond
|
||||
this.end(body, encoding);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -412,15 +426,17 @@ res.sendfile = function(path, options, fn){
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.download = function(path, filename, fn){
|
||||
res.download = function download(path, filename, fn) {
|
||||
// support function as second arg
|
||||
if ('function' == typeof filename) {
|
||||
if (typeof filename === 'function') {
|
||||
fn = filename;
|
||||
filename = null;
|
||||
}
|
||||
|
||||
filename = filename || path;
|
||||
this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"');
|
||||
|
||||
this.set('Content-Disposition', contentDisposition(filename));
|
||||
|
||||
return this.sendfile(path, fn);
|
||||
};
|
||||
|
||||
@@ -543,11 +559,13 @@ res.format = function(obj){
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.attachment = function(filename){
|
||||
if (filename) this.type(extname(filename));
|
||||
this.set('Content-Disposition', filename
|
||||
? 'attachment; filename="' + basename(filename) + '"'
|
||||
: 'attachment');
|
||||
res.attachment = function attachment(filename) {
|
||||
if (filename) {
|
||||
this.type(extname(filename));
|
||||
}
|
||||
|
||||
this.set('Content-Disposition', contentDisposition(filename));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -607,7 +625,7 @@ res.get = function(field){
|
||||
res.clearCookie = function(name, options){
|
||||
var opts = { expires: new Date(1), path: '/' };
|
||||
return this.cookie(name, '', options
|
||||
? utils.merge(opts, options)
|
||||
? merge(opts, options)
|
||||
: opts);
|
||||
};
|
||||
|
||||
@@ -635,7 +653,7 @@ res.clearCookie = function(name, options){
|
||||
*/
|
||||
|
||||
res.cookie = function(name, val, options){
|
||||
options = utils.merge({}, options);
|
||||
options = merge({}, options);
|
||||
var secret = this.req.secret;
|
||||
var signed = options.signed;
|
||||
if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies');
|
||||
@@ -693,7 +711,7 @@ res.location = function(url){
|
||||
if (!~url.indexOf('://') && 0 != url.indexOf('//')) {
|
||||
// relative to path
|
||||
if ('.' == url[0]) {
|
||||
path = req.originalUrl.split('?')[0];
|
||||
path = parseUrl.original(req).pathname;
|
||||
path = path + ('/' == path[path.length - 1] ? '' : '/');
|
||||
url = resolve(path, url);
|
||||
// relative to mount-point
|
||||
@@ -737,7 +755,7 @@ res.redirect = function(url){
|
||||
status = url;
|
||||
url = arguments[1];
|
||||
} else {
|
||||
deprecate('res.redirect(ur, status): Use res.redirect(status, url) instead');
|
||||
deprecate('res.redirect(url, status): Use res.redirect(status, url) instead');
|
||||
status = arguments[1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,17 +196,32 @@ Router.prototype._options = function(req, res, next){
|
||||
* @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;
|
||||
Router.prototype._optionsFor = function _optionsFor(path) {
|
||||
var options = [];
|
||||
|
||||
for (var i = 0; i < methods.length; i++) {
|
||||
var method = methods[i];
|
||||
|
||||
if (method === 'options') continue;
|
||||
|
||||
var routes = this.map[method];
|
||||
|
||||
// HEAD methods include GET routes
|
||||
if (!routes && method === 'head') {
|
||||
routes = this.map.get;
|
||||
}
|
||||
}).map(function(method){
|
||||
return method.toUpperCase();
|
||||
});
|
||||
|
||||
if (!routes) continue;
|
||||
|
||||
for (var j = 0; j < routes.length; j++) {
|
||||
if (routes[j].match(path)) {
|
||||
options.push(method.toUpperCase());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return options.sort();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
54
lib/utils.js
54
lib/utils.js
@@ -1,13 +1,19 @@
|
||||
/*!
|
||||
* express
|
||||
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var mime = require('connect').mime
|
||||
, proxyaddr = require('proxy-addr')
|
||||
, crc32 = require('buffer-crc32')
|
||||
, crypto = require('crypto');
|
||||
var typer = require('media-typer');
|
||||
var contentType = require('content-type');
|
||||
var etag = require('etag');
|
||||
var mime = require('connect').mime;
|
||||
var proxyaddr = require('proxy-addr');
|
||||
|
||||
/**
|
||||
* toString ref.
|
||||
@@ -24,17 +30,12 @@ var toString = {}.toString;
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.etag = function etag(body, encoding){
|
||||
if (body.length === 0) {
|
||||
// fast-path empty body
|
||||
return '"1B2M2Y8AsgTpgAmY7PhCfg=="'
|
||||
}
|
||||
exports.etag = function (body, encoding) {
|
||||
var buf = !Buffer.isBuffer(body)
|
||||
? new Buffer(body, encoding)
|
||||
: body;
|
||||
|
||||
var hash = crypto
|
||||
.createHash('md5')
|
||||
.update(body, encoding)
|
||||
.digest('base64')
|
||||
return '"' + hash + '"'
|
||||
return etag(buf, {weak: false});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -47,16 +48,11 @@ exports.etag = function etag(body, encoding){
|
||||
*/
|
||||
|
||||
exports.wetag = function wetag(body, encoding){
|
||||
if (body.length === 0) {
|
||||
// fast-path empty body
|
||||
return 'W/"0-0"'
|
||||
}
|
||||
var buf = !Buffer.isBuffer(body)
|
||||
? new Buffer(body, encoding)
|
||||
: body;
|
||||
|
||||
var buf = Buffer.isBuffer(body)
|
||||
? body
|
||||
: new Buffer(body, encoding)
|
||||
var len = buf.length
|
||||
return 'W/"' + len.toString(16) + '-' + crc32.unsigned(buf) + '"'
|
||||
return etag(buf, {weak: true});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -404,15 +400,17 @@ exports.compileTrust = function(val) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.setCharset = function(type, charset){
|
||||
if (!type || !charset) return type;
|
||||
exports.setCharset = function setCharset(type, charset) {
|
||||
if (!type || !charset) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// parse type
|
||||
var parsed = typer.parse(type);
|
||||
var parsed = contentType.parse(type);
|
||||
|
||||
// set charset
|
||||
parsed.parameters.charset = charset;
|
||||
|
||||
// format type
|
||||
return typer.format(parsed);
|
||||
return contentType.format(parsed);
|
||||
};
|
||||
|
||||
69
package.json
69
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "express",
|
||||
"description": "Sinatra inspired web development framework",
|
||||
"version": "3.15.2",
|
||||
"version": "3.20.2",
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"contributors": [
|
||||
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
|
||||
@@ -11,6 +11,9 @@
|
||||
"Jonathan Ong <me@jongleberry.com>",
|
||||
"Roman Shtylman <shtylman+expressjs@gmail.com"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": "strongloop/express",
|
||||
"homepage": "http://expressjs.com/",
|
||||
"keywords": [
|
||||
"express",
|
||||
"framework",
|
||||
@@ -22,39 +25,37 @@
|
||||
"app",
|
||||
"api"
|
||||
],
|
||||
"repository": "visionmedia/express",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"basic-auth": "1.0.0",
|
||||
"buffer-crc32": "0.2.3",
|
||||
"connect": "2.24.2",
|
||||
"commander": "1.3.2",
|
||||
"debug": "1.0.4",
|
||||
"depd": "0.4.4",
|
||||
"escape-html": "1.0.1",
|
||||
"media-typer": "0.2.0",
|
||||
"methods": "1.1.0",
|
||||
"mkdirp": "0.5.0",
|
||||
"parseurl": "~1.2.0",
|
||||
"proxy-addr": "1.0.1",
|
||||
"range-parser": "1.0.0",
|
||||
"send": "0.7.2",
|
||||
"vary": "0.1.0",
|
||||
"connect": "2.29.1",
|
||||
"content-disposition": "0.5.0",
|
||||
"content-type": "~1.0.1",
|
||||
"commander": "2.6.0",
|
||||
"cookie": "0.1.2",
|
||||
"fresh": "0.2.2",
|
||||
"cookie-signature": "1.0.4",
|
||||
"merge-descriptors": "0.0.2"
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "~2.1.3",
|
||||
"depd": "~1.0.0",
|
||||
"escape-html": "1.0.1",
|
||||
"etag": "~1.5.1",
|
||||
"fresh": "0.2.4",
|
||||
"merge-descriptors": "1.0.0",
|
||||
"methods": "~1.1.1",
|
||||
"mkdirp": "0.5.0",
|
||||
"parseurl": "~1.3.0",
|
||||
"proxy-addr": "~1.0.7",
|
||||
"range-parser": "~1.0.2",
|
||||
"send": "0.12.2",
|
||||
"utils-merge": "1.0.0",
|
||||
"vary": "~1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "0.3.0",
|
||||
"mocha": "~1.21.0",
|
||||
"should": "~4.0.0",
|
||||
"ejs": "~1.0.0",
|
||||
"jade": "~1.3.1",
|
||||
"hjs": "~0.0.6",
|
||||
"marked": "0.3.2",
|
||||
"connect-redis": "~1.4.5",
|
||||
"supertest": "~0.13.0"
|
||||
"connect-redis": "~1.5.0",
|
||||
"ejs": "2.3.1",
|
||||
"istanbul": "0.3.8",
|
||||
"marked": "0.3.3",
|
||||
"mocha": "~2.2.1",
|
||||
"should": "~5.2.0",
|
||||
"supertest": "~0.15.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
@@ -62,10 +63,18 @@
|
||||
"bin": {
|
||||
"express": "./bin/express"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"History.md",
|
||||
"Readme.md",
|
||||
"index.js",
|
||||
"bin/",
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"prepublish": "npm prune",
|
||||
"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-tap": "mocha --require test/support/env --reporter tap --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/"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('../');
|
||||
|
||||
var app = express()
|
||||
, blog = express()
|
||||
, admin = express();
|
||||
|
||||
// app.use(express.logger('dev'))
|
||||
blog.use('/admin', admin);
|
||||
app.use('/blog', blog);
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade');
|
||||
app.locals.self = true;
|
||||
|
||||
app.get('/render', function(req, res){
|
||||
res.render('hello');
|
||||
});
|
||||
|
||||
admin.get('/', function(req, res){
|
||||
res.send('Hello World\n');
|
||||
});
|
||||
|
||||
blog.get('/', function(req, res){
|
||||
res.send('Hello World\n');
|
||||
});
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.send('Hello World\n');
|
||||
});
|
||||
|
||||
app.get('/json', function(req, res){
|
||||
res.send({ name: 'Tobi', role: 'admin' });
|
||||
});
|
||||
|
||||
app.get('/json/:n', function(req, res){
|
||||
var n = ~~req.params.n;
|
||||
var arr = [];
|
||||
var obj = { name: 'Tobi', role: 'admin' };
|
||||
while (n--) arr.push(obj);
|
||||
res.send(arr);
|
||||
});
|
||||
|
||||
function foo(req, res, next) {
|
||||
next();
|
||||
}
|
||||
|
||||
app.get('/middleware', foo, foo, foo, foo, function(req, res){
|
||||
res.send('Hello World\n');
|
||||
});
|
||||
|
||||
var n = 100;
|
||||
while (n--) {
|
||||
app.get('/foo', foo, foo, function(req, res){
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
app.get('/match', function(req, res){
|
||||
res.send('Hello World\n');
|
||||
});
|
||||
|
||||
app.listen(8000);
|
||||
21
support/docs
21
support/docs
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var buf = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', function(chunk){
|
||||
buf += chunk;
|
||||
}).on('end', function(){
|
||||
var comments = JSON.parse(buf);
|
||||
comments.forEach(function(comment){
|
||||
if (comment.ignore) return;
|
||||
if (comment.isPrivate) return;
|
||||
if (!comment.ctx) return;
|
||||
if (!comment.description.full.indexOf('Module dep')) return;
|
||||
var ctx = comment.ctx;
|
||||
console.log();
|
||||
console.log('# %s', ctx.string);
|
||||
console.log();
|
||||
console.log(comment.description.full.trim().replace(/^/gm, ' '));
|
||||
});
|
||||
console.log();
|
||||
}).resume();
|
||||
@@ -1 +0,0 @@
|
||||
p Hello
|
||||
36
test/acceptance/cookie-sessions.js
Normal file
36
test/acceptance/cookie-sessions.js
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
var app = require('../../examples/cookie-sessions')
|
||||
var request = require('supertest')
|
||||
|
||||
function getCookie(res) {
|
||||
return res.headers['set-cookie'][0].split(';')[0]
|
||||
}
|
||||
|
||||
describe('cookie-sessions', function () {
|
||||
describe('GET /', function () {
|
||||
it('should display no views', function (done) {
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'viewed 0 times\n', done)
|
||||
})
|
||||
|
||||
it('should set a session cookie', function (done) {
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Set-Cookie', /connect\.sess=/)
|
||||
.expect(200, done)
|
||||
})
|
||||
|
||||
it('should display 1 view on revisit', function (done) {
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'viewed 0 times\n', function (err, res) {
|
||||
if (err) return done(err)
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Cookie', getCookie(res))
|
||||
.expect(200, 'viewed 1 times\n', done)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -53,7 +53,7 @@ describe('web-service', function(){
|
||||
.get('/api/repos?api-key=foo')
|
||||
.expect('Content-Type', 'application/json; charset=utf-8')
|
||||
.expect(/"name":"express"/)
|
||||
.expect(/"url":"http:\/\/github.com\/visionmedia\/express"/)
|
||||
.expect(/"url":"http:\/\/github.com\/strongloop\/express"/)
|
||||
.expect(200, done)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -12,8 +12,8 @@ describe('OPTIONS', function(){
|
||||
|
||||
request(app)
|
||||
.options('/users')
|
||||
.expect('GET,PUT')
|
||||
.expect('Allow', 'GET,PUT', done);
|
||||
.expect('GET,HEAD,PUT')
|
||||
.expect('Allow', 'GET,HEAD,PUT', done);
|
||||
})
|
||||
|
||||
it('should not respond if the path is not defined', function(done){
|
||||
@@ -36,8 +36,8 @@ describe('OPTIONS', function(){
|
||||
|
||||
request(app)
|
||||
.options('/other')
|
||||
.expect('GET')
|
||||
.expect('Allow', 'GET', done);
|
||||
.expect('GET,HEAD')
|
||||
.expect('Allow', 'GET,HEAD', done);
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
|
||||
var express = require('../');
|
||||
var express = require('..');
|
||||
var tmpl = require('./support/tmpl');
|
||||
|
||||
describe('app', function(){
|
||||
describe('.render(name, fn)', function(){
|
||||
it('should support absolute paths', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.render(__dirname + '/fixtures/user.jade', function(err, str){
|
||||
app.render(__dirname + '/fixtures/user.tmpl', function (err, str) {
|
||||
if (err) return done(err);
|
||||
str.should.equal('<p>tobi</p>');
|
||||
done();
|
||||
@@ -16,9 +17,9 @@ describe('app', function(){
|
||||
})
|
||||
|
||||
it('should support absolute paths with "view engine"', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'tmpl');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.render(__dirname + '/fixtures/user', function(err, str){
|
||||
@@ -29,12 +30,12 @@ describe('app', function(){
|
||||
})
|
||||
|
||||
it('should expose app.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.render('user.jade', function(err, str){
|
||||
app.render('user.tmpl', function (err, str) {
|
||||
if (err) return done(err);
|
||||
str.should.equal('<p>tobi</p>');
|
||||
done();
|
||||
@@ -42,12 +43,12 @@ describe('app', function(){
|
||||
})
|
||||
|
||||
it('should support index.<engine>', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'tmpl');
|
||||
|
||||
app.render('blog/post', function(err, str){
|
||||
app.render('blog/post', function (err, str) {
|
||||
if (err) return done(err);
|
||||
str.should.equal('<h1>blog post</h1>');
|
||||
done();
|
||||
@@ -77,10 +78,11 @@ describe('app', function(){
|
||||
|
||||
describe('when the file does not exist', function(){
|
||||
it('should provide a helpful error', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.render('rawr.jade', function(err){
|
||||
err.message.should.equal('Failed to lookup view "rawr.jade" in views directory "' + __dirname + '/fixtures"');
|
||||
app.render('rawr.tmpl', function (err) {
|
||||
err.message.should.equal('Failed to lookup view "rawr.tmpl" in views directory "' + __dirname + '/fixtures"');
|
||||
done();
|
||||
});
|
||||
})
|
||||
@@ -88,11 +90,11 @@ describe('app', function(){
|
||||
|
||||
describe('when an error occurs', function(){
|
||||
it('should invoke the callback', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.render('user.jade', function(err, str){
|
||||
app.render('user.tmpl', function (err, str) {
|
||||
// nextTick to prevent cyclic
|
||||
process.nextTick(function(){
|
||||
err.message.should.match(/Cannot read property 'name' of undefined/);
|
||||
@@ -104,11 +106,11 @@ describe('app', function(){
|
||||
|
||||
describe('when an extension is given', function(){
|
||||
it('should render the template', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.render('email.jade', function(err, str){
|
||||
app.render('email.tmpl', function (err, str) {
|
||||
if (err) return done(err);
|
||||
str.should.equal('<p>This is an email</p>');
|
||||
done();
|
||||
@@ -118,9 +120,9 @@ describe('app', function(){
|
||||
|
||||
describe('when "view engine" is given', function(){
|
||||
it('should render the template', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'tmpl');
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.render('email', function(err, str){
|
||||
@@ -219,13 +221,13 @@ describe('app', function(){
|
||||
|
||||
describe('.render(name, options, fn)', function(){
|
||||
it('should render the template', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
var user = { name: 'tobi' };
|
||||
|
||||
app.render('user.jade', { user: user }, function(err, str){
|
||||
app.render('user.tmpl', { user: user }, function (err, str) {
|
||||
if (err) return done(err);
|
||||
str.should.equal('<p>tobi</p>');
|
||||
done();
|
||||
@@ -233,12 +235,12 @@ describe('app', function(){
|
||||
})
|
||||
|
||||
it('should expose app.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.render('user.jade', {}, function(err, str){
|
||||
app.render('user.tmpl', {}, function (err, str) {
|
||||
if (err) return done(err);
|
||||
str.should.equal('<p>tobi</p>');
|
||||
done();
|
||||
@@ -246,13 +248,13 @@ describe('app', function(){
|
||||
})
|
||||
|
||||
it('should give precedence to app.render() locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
var jane = { name: 'jane' };
|
||||
|
||||
app.render('user.jade', { user: jane }, function(err, str){
|
||||
app.render('user.tmpl', { user: jane }, function (err, str) {
|
||||
if (err) return done(err);
|
||||
str.should.equal('<p>jane</p>');
|
||||
done();
|
||||
@@ -292,3 +294,11 @@ describe('app', function(){
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function createApp() {
|
||||
var app = express();
|
||||
|
||||
app.engine('.tmpl', tmpl);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('supertest');
|
||||
var assert = require('assert');
|
||||
var express = require('..');
|
||||
var request = require('supertest');
|
||||
|
||||
describe('app', function(){
|
||||
it('should emit "mount" when mounted', function(done){
|
||||
|
||||
103
test/config.js
103
test/config.js
@@ -1,30 +1,36 @@
|
||||
|
||||
var express = require('../')
|
||||
, assert = require('assert');
|
||||
var assert = require('assert');
|
||||
var express = require('..');
|
||||
|
||||
describe('config', function(){
|
||||
describe('.set()', function(){
|
||||
it('should set a value', function(){
|
||||
describe('config', function () {
|
||||
describe('.set()', function () {
|
||||
it('should set a value', function () {
|
||||
var app = express();
|
||||
app.set('foo', 'bar').should.equal(app);
|
||||
app.set('foo', 'bar');
|
||||
assert.equal(app.get('foo'), 'bar');
|
||||
})
|
||||
|
||||
it('should return the app when undefined', function(){
|
||||
it('should return the app', function () {
|
||||
var app = express();
|
||||
app.set('foo', undefined).should.equal(app);
|
||||
assert.equal(app.set('foo', 'bar'), app);
|
||||
})
|
||||
|
||||
it('should return the app when undefined', function () {
|
||||
var app = express();
|
||||
assert.equal(app.set('foo', undefined), app);
|
||||
})
|
||||
|
||||
describe('"etag"', function(){
|
||||
it('should throw on bad value', function(){
|
||||
var app = express()
|
||||
app.set.bind(app, 'etag', 42).should.throw(/unknown value/)
|
||||
var app = express();
|
||||
assert.throws(app.set.bind(app, 'etag', 42), /unknown value/);
|
||||
})
|
||||
|
||||
it('should set "etag fn"', function(){
|
||||
var app = express()
|
||||
var fn = function(){}
|
||||
app.set('etag', fn)
|
||||
app.get('etag fn').should.equal(fn)
|
||||
assert.equal(app.get('etag fn'), fn)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -33,7 +39,7 @@ describe('config', function(){
|
||||
var app = express()
|
||||
var fn = function(){}
|
||||
app.set('trust proxy', fn)
|
||||
app.get('trust proxy fn').should.equal(fn)
|
||||
assert.equal(app.get('trust proxy fn'), fn)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -41,34 +47,73 @@ describe('config', function(){
|
||||
describe('.get()', function(){
|
||||
it('should return undefined when unset', function(){
|
||||
var app = express();
|
||||
assert(undefined === app.get('foo'));
|
||||
assert.strictEqual(app.get('foo'), undefined);
|
||||
})
|
||||
|
||||
it('should otherwise return the value', function(){
|
||||
var app = express();
|
||||
app.set('foo', 'bar');
|
||||
app.get('foo').should.equal('bar');
|
||||
assert.equal(app.get('foo'), 'bar');
|
||||
})
|
||||
|
||||
describe('when mounted', function(){
|
||||
it('should default to the parent app', function(){
|
||||
var app = express()
|
||||
, blog = express();
|
||||
var app = express();
|
||||
var blog = express();
|
||||
|
||||
app.set('title', 'Express');
|
||||
app.use(blog);
|
||||
blog.get('title').should.equal('Express');
|
||||
assert.equal(blog.get('title'), 'Express');
|
||||
})
|
||||
|
||||
|
||||
it('should given precedence to the child', function(){
|
||||
var app = express()
|
||||
, blog = express();
|
||||
var app = express();
|
||||
var blog = express();
|
||||
|
||||
app.use(blog);
|
||||
app.set('title', 'Express');
|
||||
blog.set('title', 'Some Blog');
|
||||
|
||||
blog.get('title').should.equal('Some Blog');
|
||||
assert.equal(blog.get('title'), 'Some Blog');
|
||||
})
|
||||
|
||||
it('should inherit "trust proxy" setting', function () {
|
||||
var app = express();
|
||||
var blog = express();
|
||||
|
||||
function fn() { return false }
|
||||
|
||||
app.set('trust proxy', fn);
|
||||
assert.equal(app.get('trust proxy'), fn);
|
||||
assert.equal(app.get('trust proxy fn'), fn);
|
||||
|
||||
app.use(blog);
|
||||
|
||||
assert.equal(blog.get('trust proxy'), fn);
|
||||
assert.equal(blog.get('trust proxy fn'), fn);
|
||||
})
|
||||
|
||||
it('should prefer child "trust proxy" setting', function () {
|
||||
var app = express();
|
||||
var blog = express();
|
||||
|
||||
function fn1() { return false }
|
||||
function fn2() { return true }
|
||||
|
||||
app.set('trust proxy', fn1);
|
||||
assert.equal(app.get('trust proxy'), fn1);
|
||||
assert.equal(app.get('trust proxy fn'), fn1);
|
||||
|
||||
blog.set('trust proxy', fn2);
|
||||
assert.equal(blog.get('trust proxy'), fn2);
|
||||
assert.equal(blog.get('trust proxy fn'), fn2);
|
||||
|
||||
app.use(blog);
|
||||
|
||||
assert.equal(app.get('trust proxy'), fn1);
|
||||
assert.equal(app.get('trust proxy fn'), fn1);
|
||||
assert.equal(blog.get('trust proxy'), fn2);
|
||||
assert.equal(blog.get('trust proxy fn'), fn2);
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -76,42 +121,42 @@ describe('config', function(){
|
||||
describe('.enable()', function(){
|
||||
it('should set the value to true', function(){
|
||||
var app = express();
|
||||
app.enable('tobi').should.equal(app);
|
||||
app.get('tobi').should.be.true;
|
||||
assert.equal(app.enable('tobi'), app);
|
||||
assert.strictEqual(app.get('tobi'), true);
|
||||
})
|
||||
})
|
||||
|
||||
describe('.disable()', function(){
|
||||
it('should set the value to false', function(){
|
||||
var app = express();
|
||||
app.disable('tobi').should.equal(app);
|
||||
app.get('tobi').should.be.false;
|
||||
assert.equal(app.disable('tobi'), app);
|
||||
assert.strictEqual(app.get('tobi'), false);
|
||||
})
|
||||
})
|
||||
|
||||
describe('.enabled()', function(){
|
||||
it('should default to false', function(){
|
||||
var app = express();
|
||||
app.enabled('foo').should.be.false;
|
||||
assert.strictEqual(app.enabled('foo'), false);
|
||||
})
|
||||
|
||||
it('should return true when set', function(){
|
||||
var app = express();
|
||||
app.set('foo', 'bar');
|
||||
app.enabled('foo').should.be.true;
|
||||
assert.strictEqual(app.enabled('foo'), true);
|
||||
})
|
||||
})
|
||||
|
||||
describe('.disabled()', function(){
|
||||
it('should default to true', function(){
|
||||
var app = express();
|
||||
app.disabled('foo').should.be.true;
|
||||
assert.strictEqual(app.disabled('foo'), true);
|
||||
})
|
||||
|
||||
it('should return false when set', function(){
|
||||
var app = express();
|
||||
app.set('foo', 'bar');
|
||||
app.disabled('foo').should.be.false;
|
||||
assert.strictEqual(app.disabled('foo'), false);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
1
test/fixtures/blog/index.html
vendored
Normal file
1
test/fixtures/blog/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<b>index</b>
|
||||
1
test/fixtures/blog/post/index.jade
vendored
1
test/fixtures/blog/post/index.jade
vendored
@@ -1 +0,0 @@
|
||||
h1 blog post
|
||||
1
test/fixtures/blog/post/index.tmpl
vendored
Normal file
1
test/fixtures/blog/post/index.tmpl
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<h1>blog post</h1>
|
||||
1
test/fixtures/email.jade
vendored
1
test/fixtures/email.jade
vendored
@@ -1 +0,0 @@
|
||||
p This is an email
|
||||
1
test/fixtures/email.tmpl
vendored
Normal file
1
test/fixtures/email.tmpl
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<p>This is an email</p>
|
||||
1
test/fixtures/pet.jade
vendored
1
test/fixtures/pet.jade
vendored
@@ -1 +0,0 @@
|
||||
p #{first} #{last} is a #{species}
|
||||
1
test/fixtures/user.jade
vendored
1
test/fixtures/user.jade
vendored
@@ -1 +0,0 @@
|
||||
p= user.name
|
||||
1
test/fixtures/user.tmpl
vendored
Normal file
1
test/fixtures/user.tmpl
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<p>$user.name</p>
|
||||
@@ -32,5 +32,18 @@ describe('req', function(){
|
||||
.set('If-None-Match', '"12345"')
|
||||
.expect(200, 'false', done);
|
||||
})
|
||||
|
||||
it('should return false without response headers', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res._headers = null;
|
||||
res.send(req.fresh);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'false', done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -117,6 +117,24 @@ describe('req', function(){
|
||||
.set('Host', 'example.com')
|
||||
.expect('example.com', done);
|
||||
})
|
||||
|
||||
describe('when trusting hop count', function () {
|
||||
it('should respect X-Forwarded-Host', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', 1);
|
||||
|
||||
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);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when "trust proxy" is disabled', function(){
|
||||
|
||||
@@ -35,6 +35,23 @@ describe('req', function(){
|
||||
.set('X-Forwarded-For', 'client, p1, p2')
|
||||
.expect('p1', done);
|
||||
})
|
||||
|
||||
it('should return the addr after trusted proxy, from sub app', function (done) {
|
||||
var app = express();
|
||||
var sub = express();
|
||||
|
||||
app.set('trust proxy', 2);
|
||||
app.use(sub);
|
||||
|
||||
sub.use(function (req, res, next) {
|
||||
res.send(req.ip);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-For', 'client, p1, p2')
|
||||
.expect(200, 'p1', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when "trust proxy" is disabled', function(){
|
||||
@@ -45,10 +62,9 @@ describe('req', function(){
|
||||
res.send(req.ip);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-For', 'client, p1, p2')
|
||||
.expect('127.0.0.1', done);
|
||||
var test = request(app).get('/')
|
||||
test.set('X-Forwarded-For', 'client, p1, p2')
|
||||
test.expect(200, getExpectedClientAddress(test._server), done);
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -63,10 +79,19 @@ describe('req', function(){
|
||||
res.send(req.ip);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('127.0.0.1', done);
|
||||
var test = request(app).get('/')
|
||||
test.expect(200, getExpectedClientAddress(test._server), done);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Get the local client address depending on AF_NET of server
|
||||
*/
|
||||
|
||||
function getExpectedClientAddress(server) {
|
||||
return server.address().address === '::'
|
||||
? '::ffff:127.0.0.1'
|
||||
: '127.0.0.1';
|
||||
}
|
||||
|
||||
@@ -75,6 +75,23 @@ describe('req', function(){
|
||||
.get('/')
|
||||
.expect('http', done);
|
||||
})
|
||||
|
||||
describe('when trusting hop count', function () {
|
||||
it('should respect X-Forwarded-Proto', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', 1);
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.end(req.protocol);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-Proto', 'https')
|
||||
.expect('https', done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('when "trust proxy" is disabled', function(){
|
||||
|
||||
@@ -78,6 +78,23 @@ describe('req', function(){
|
||||
.set('X-Forwarded-Proto', 'https, http')
|
||||
.expect('yes', done)
|
||||
})
|
||||
|
||||
describe('when "trust proxy" trusting hop count', function () {
|
||||
it('should respect X-Forwarded-Proto', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', 1);
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
res.send(req.secure ? 'yes' : 'no');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-Proto', 'https')
|
||||
.expect('yes', done)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -32,5 +32,18 @@ describe('req', function(){
|
||||
.set('If-None-Match', '"12345"')
|
||||
.expect(200, 'true', done);
|
||||
})
|
||||
|
||||
it('should return true without response headers', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res._headers = null;
|
||||
res.send(req.stale);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'true', done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -15,7 +15,33 @@ describe('req', function(){
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'tobi.ferrets.example.com')
|
||||
.expect(["ferrets","tobi"], done);
|
||||
.expect(200, ['ferrets', 'tobi'], done);
|
||||
})
|
||||
|
||||
it('should work with IPv4 address', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send(req.subdomains);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', '127.0.0.1')
|
||||
.expect(200, [], done);
|
||||
})
|
||||
|
||||
it('should work with IPv6 address', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send(req.subdomains);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', '[::1]')
|
||||
.expect(200, [], done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -30,7 +56,7 @@ describe('req', function(){
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'example.com')
|
||||
.expect([], done);
|
||||
.expect(200, [], done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -45,7 +71,23 @@ describe('req', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect([], done);
|
||||
.expect(200, [], done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('with trusted X-Forwarded-Host', function () {
|
||||
it('should return an array', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('trust proxy', true);
|
||||
app.use(function (req, res) {
|
||||
res.send(req.subdomains);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('X-Forwarded-Host', 'tobi.ferrets.example.com')
|
||||
.expect(200, ['ferrets', 'tobi'], done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -62,7 +104,35 @@ describe('req', function(){
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'tobi.ferrets.sub.example.com')
|
||||
.expect(["com","example","sub","ferrets","tobi"], done);
|
||||
.expect(200, ['com', 'example', 'sub', 'ferrets', 'tobi'], done);
|
||||
})
|
||||
|
||||
it('should return an array with the whole IPv4', function (done) {
|
||||
var app = express();
|
||||
app.set('subdomain offset', 0);
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send(req.subdomains);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', '127.0.0.1')
|
||||
.expect(200, ['127.0.0.1'], done);
|
||||
})
|
||||
|
||||
it('should return an array with the whole IPv6', function (done) {
|
||||
var app = express();
|
||||
app.set('subdomain offset', 0);
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send(req.subdomains);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', '[::1]')
|
||||
.expect(200, ['[::1]'], done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -78,7 +148,7 @@ describe('req', function(){
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'tobi.ferrets.sub.example.com')
|
||||
.expect(["ferrets","tobi"], done);
|
||||
.expect(200, ['ferrets', 'tobi'], done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -94,7 +164,7 @@ describe('req', function(){
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'sub.example.com')
|
||||
.expect([], done);
|
||||
.expect(200, [], done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('supertest')
|
||||
, utils = require('connect').utils
|
||||
, cookie = require('cookie');
|
||||
var merge = require('utils-merge');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.cookie(name, object)', function(){
|
||||
@@ -111,7 +111,7 @@ describe('res', function(){
|
||||
var app = express();
|
||||
|
||||
var options = { maxAge: 1000 };
|
||||
var optionsCopy = utils.merge({}, options);
|
||||
var optionsCopy = merge({}, options);
|
||||
|
||||
app.use(function(req, res){
|
||||
res.cookie('name', 'tobi', options)
|
||||
|
||||
@@ -81,7 +81,7 @@ describe('res', function(){
|
||||
it('should be invoked instead of auto-responding', function(done){
|
||||
request(app3)
|
||||
.get('/')
|
||||
.set('Accept: text/html')
|
||||
.set('Accept', 'text/html')
|
||||
.expect('default', done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
|
||||
var express = require('../')
|
||||
, res = express.response;
|
||||
var express = require('..');
|
||||
var request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.get(field)', function(){
|
||||
it('should get the response header field', function(){
|
||||
res.setHeader('Content-Type', 'text/x-foo');
|
||||
res.get('Content-Type').should.equal('text/x-foo');
|
||||
res.get('Content-type').should.equal('text/x-foo');
|
||||
res.get('content-type').should.equal('text/x-foo');
|
||||
it('should get the response header field', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.setHeader('Content-Type', 'text/x-foo');
|
||||
res.send(res.get('Content-Type'));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'text/x-foo', done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,41 +1,46 @@
|
||||
|
||||
var express = require('../')
|
||||
, res = express.response;
|
||||
var express = require('..');
|
||||
var request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
|
||||
beforeEach(function() {
|
||||
res.removeHeader('link');
|
||||
});
|
||||
|
||||
describe('.links(obj)', function(){
|
||||
it('should set Link header field', function(){
|
||||
res.links({
|
||||
next: 'http://api.example.com/users?page=2',
|
||||
last: 'http://api.example.com/users?page=5'
|
||||
it('should set Link header field', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.links({
|
||||
next: 'http://api.example.com/users?page=2',
|
||||
last: 'http://api.example.com/users?page=5'
|
||||
});
|
||||
res.end();
|
||||
});
|
||||
|
||||
res.get('link')
|
||||
.should.equal(
|
||||
'<http://api.example.com/users?page=2>; rel="next", '
|
||||
+ '<http://api.example.com/users?page=5>; rel="last"');
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Link', '<http://api.example.com/users?page=2>; rel="next", <http://api.example.com/users?page=5>; rel="last"')
|
||||
.expect(200, done);
|
||||
})
|
||||
|
||||
it('should set Link header field for multiple calls', function() {
|
||||
res.links({
|
||||
next: 'http://api.example.com/users?page=2',
|
||||
last: 'http://api.example.com/users?page=5'
|
||||
it('should set Link header field for multiple calls', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.links({
|
||||
next: 'http://api.example.com/users?page=2',
|
||||
last: 'http://api.example.com/users?page=5'
|
||||
});
|
||||
|
||||
res.links({
|
||||
prev: 'http://api.example.com/users?page=1'
|
||||
});
|
||||
|
||||
res.end();
|
||||
});
|
||||
|
||||
res.links({
|
||||
prev: 'http://api.example.com/users?page=1',
|
||||
});
|
||||
|
||||
res.get('link')
|
||||
.should.equal(
|
||||
'<http://api.example.com/users?page=2>; rel="next", '
|
||||
+ '<http://api.example.com/users?page=5>; rel="last", '
|
||||
+ '<http://api.example.com/users?page=1>; rel="prev"');
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Link', '<http://api.example.com/users?page=2>; rel="next", <http://api.example.com/users?page=5>; rel="last", <http://api.example.com/users?page=1>; rel="prev"')
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('supertest');
|
||||
var express = require('..');
|
||||
var request = require('supertest');
|
||||
var tmpl = require('./support/tmpl');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.render(name)', function(){
|
||||
it('should support absolute paths', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render(__dirname + '/fixtures/user.jade');
|
||||
res.render(__dirname + '/fixtures/user.tmpl');
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -19,10 +20,10 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should support absolute paths with "view engine"', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.locals.user = { name: 'tobi' };
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'tmpl');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render(__dirname + '/fixtures/user');
|
||||
@@ -34,13 +35,13 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should expose app.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade');
|
||||
res.render('user.tmpl');
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -49,10 +50,10 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should support index.<engine>', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'tmpl');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('blog/post');
|
||||
@@ -65,12 +66,12 @@ describe('res', function(){
|
||||
|
||||
describe('when an error occurs', function(){
|
||||
it('should next(err)', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade');
|
||||
res.render('user.tmpl');
|
||||
});
|
||||
|
||||
app.use(function(err, req, res, next){
|
||||
@@ -85,9 +86,9 @@ describe('res', function(){
|
||||
|
||||
describe('when "view engine" is given', function(){
|
||||
it('should render the template', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('view engine', 'jade');
|
||||
app.set('view engine', 'tmpl');
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
@@ -103,14 +104,14 @@ describe('res', function(){
|
||||
|
||||
describe('.render(name, option)', function(){
|
||||
it('should render the template', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
var user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade', { user: user });
|
||||
res.render('user.tmpl', { user: user });
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -119,13 +120,13 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should expose app.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade');
|
||||
res.render('user.tmpl');
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -134,13 +135,13 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should expose res.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.locals.user = { name: 'tobi' };
|
||||
res.render('user.jade');
|
||||
res.render('user.tmpl');
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -149,14 +150,14 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should give precedence to res.locals over app.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
app.locals.user = { name: 'tobi' };
|
||||
|
||||
app.use(function(req, res){
|
||||
res.locals.user = { name: 'jane' };
|
||||
res.render('user.jade', {});
|
||||
res.render('user.tmpl', {});
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -165,14 +166,14 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should give precedence to res.render() locals over res.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
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 });
|
||||
res.render('user.tmpl', { user: jane });
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -181,14 +182,14 @@ describe('res', function(){
|
||||
})
|
||||
|
||||
it('should give precedence to res.render() locals over app.locals', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
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 });
|
||||
res.render('user.tmpl', { user: jane });
|
||||
});
|
||||
|
||||
request(app)
|
||||
@@ -199,13 +200,13 @@ describe('res', function(){
|
||||
|
||||
describe('.render(name, options, fn)', function(){
|
||||
it('should pass the resulting string', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
var tobi = { name: 'tobi' };
|
||||
res.render('user.jade', { user: tobi }, function(err, html){
|
||||
res.render('user.tmpl', { user: tobi }, function (err, html) {
|
||||
html = html.replace('tobi', 'loki');
|
||||
res.end(html);
|
||||
});
|
||||
@@ -219,13 +220,13 @@ describe('res', function(){
|
||||
|
||||
describe('.render(name, fn)', function(){
|
||||
it('should pass the resulting string', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.locals.user = { name: 'tobi' };
|
||||
res.render('user.jade', function(err, html){
|
||||
res.render('user.tmpl', function (err, html) {
|
||||
html = html.replace('tobi', 'loki');
|
||||
res.end(html);
|
||||
});
|
||||
@@ -238,12 +239,12 @@ describe('res', function(){
|
||||
|
||||
describe('when an error occurs', function(){
|
||||
it('should pass it to the callback', function(done){
|
||||
var app = express();
|
||||
var app = createApp();
|
||||
|
||||
app.set('views', __dirname + '/fixtures');
|
||||
|
||||
app.use(function(req, res){
|
||||
res.render('user.jade', function(err){
|
||||
res.render('user.tmpl', function (err) {
|
||||
res.end(err.message);
|
||||
});
|
||||
});
|
||||
@@ -255,3 +256,11 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function createApp() {
|
||||
var app = express();
|
||||
|
||||
app.engine('.tmpl', tmpl);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
263
test/res.send.js
263
test/res.send.js
@@ -1,7 +1,8 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('supertest')
|
||||
, assert = require('assert');
|
||||
var assert = require('assert');
|
||||
var express = require('..');
|
||||
var methods = require('methods');
|
||||
var request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.send(null)', function(){
|
||||
@@ -110,35 +111,18 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
it('should set ETag', function(done){
|
||||
it('should set ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1024 * 2).join('-');
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('ETag', 'W/"7ff-2796319984"')
|
||||
.end(done);
|
||||
})
|
||||
|
||||
it('should not set ETag for non-GET/HEAD', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
var str = Array(1024 * 2).join('-');
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post('/')
|
||||
.end(function(err, res){
|
||||
if (err) return done(err);
|
||||
assert(!res.header.etag, 'has an ETag');
|
||||
done();
|
||||
});
|
||||
.expect('ETag', 'W/"fz/jGo0ONwzb+aKy/rWipg=="')
|
||||
.expect(200, done);
|
||||
})
|
||||
|
||||
it('should not override Content-Type', function(done){
|
||||
@@ -199,18 +183,18 @@ describe('res', function(){
|
||||
})
|
||||
})
|
||||
|
||||
it('should set ETag', function(done){
|
||||
it('should set ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1024 * 2).join('-');
|
||||
res.send(new Buffer(str));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('ETag', 'W/"7ff-2796319984"')
|
||||
.end(done);
|
||||
.expect('ETag', 'W/"fz/jGo0ONwzb+aKy/rWipg=="')
|
||||
.expect(200, done);
|
||||
})
|
||||
|
||||
it('should not override Content-Type', function(done){
|
||||
@@ -325,7 +309,7 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('If-None-Match', 'W/"7ff-2796319984"')
|
||||
.set('If-None-Match', 'W/"fz/jGo0ONwzb+aKy/rWipg=="')
|
||||
.expect(304, done);
|
||||
})
|
||||
|
||||
@@ -358,12 +342,12 @@ describe('res', function(){
|
||||
.expect('{"foo":"bar"}', done);
|
||||
})
|
||||
|
||||
describe('"etag" setting', function(){
|
||||
describe('when enabled', function(){
|
||||
it('should send ETag', function(done){
|
||||
describe('"etag" setting', function () {
|
||||
describe('when enabled', function () {
|
||||
it('should send ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
res.send('kajdslfkasdf');
|
||||
});
|
||||
|
||||
@@ -371,76 +355,95 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', 'W/"c-1525560792"', done)
|
||||
})
|
||||
|
||||
it('should send ETag for empty string response', function(done){
|
||||
var app = express()
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send('')
|
||||
});
|
||||
|
||||
app.enable('etag')
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', 'W/"0-0"', done)
|
||||
})
|
||||
|
||||
it('should send ETag for long response', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
var str = Array(1024 * 2).join('-');
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
app.enable('etag');
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', 'W/"7ff-2796319984"', done)
|
||||
.expect('ETag', 'W/"c-5aee35d8"')
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('should not override ETag when manually set', function(done){
|
||||
var app = express();
|
||||
methods.forEach(function (method) {
|
||||
if (method === 'connect') return;
|
||||
|
||||
app.use(function(req, res){
|
||||
res.set('etag', '"asdf"');
|
||||
res.send(200);
|
||||
});
|
||||
it('should send ETag in response to ' + method.toUpperCase() + ' request', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.enable('etag');
|
||||
app[method]('/', function (req, res) {
|
||||
res.send('kajdslfkasdf');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', '"asdf"', done)
|
||||
});
|
||||
|
||||
it('should not send ETag for res.send()', function(done){
|
||||
var app = express()
|
||||
|
||||
app.use(function(req, res){
|
||||
res.send()
|
||||
});
|
||||
|
||||
app.enable('etag')
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.headers.should.not.have.property('etag');
|
||||
done();
|
||||
request(app)
|
||||
[method]('/')
|
||||
.expect('ETag', 'W/"c-5aee35d8"')
|
||||
.expect(200, done);
|
||||
})
|
||||
});
|
||||
|
||||
it('should send ETag for empty string response', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send('');
|
||||
});
|
||||
|
||||
app.enable('etag');
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('ETag', 'W/"0-0"')
|
||||
.expect(200, done);
|
||||
})
|
||||
|
||||
it('should send ETag for long response', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1024 * 2).join('-');
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
app.enable('etag');
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('ETag', 'W/"fz/jGo0ONwzb+aKy/rWipg=="')
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('should not override ETag when manually set', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set('etag', '"asdf"');
|
||||
res.send(200);
|
||||
});
|
||||
|
||||
app.enable('etag');
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('ETag', '"asdf"')
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('should not send ETag for res.send()', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send();
|
||||
});
|
||||
|
||||
app.enable('etag');
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(shouldNotHaveHeader('ETag'))
|
||||
.expect(200, done);
|
||||
})
|
||||
});
|
||||
|
||||
describe('when disabled', function(){
|
||||
it('should send no ETag', function(done){
|
||||
describe('when disabled', function () {
|
||||
it('should send no ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1024 * 2).join('-');
|
||||
res.send(str);
|
||||
});
|
||||
@@ -449,97 +452,103 @@ describe('res', function(){
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.headers.should.not.have.property('etag');
|
||||
done();
|
||||
});
|
||||
.expect(shouldNotHaveHeader('ETag'))
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('should send ETag when manually set', function(done){
|
||||
it('should send ETag when manually set', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.disable('etag');
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
res.set('etag', '"asdf"');
|
||||
res.send(200);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', '"asdf"', done)
|
||||
.expect('ETag', '"asdf"')
|
||||
.expect(200, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when "strong"', function(){
|
||||
it('should send strong ETag', function(done){
|
||||
var app = express()
|
||||
describe('when "strong"', function () {
|
||||
it('should send strong ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('etag', 'strong');
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
res.send('hello, world!');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', '"Otu60XkfuuPskIiUxJY4cA=="', done)
|
||||
.expect('ETag', '"Otu60XkfuuPskIiUxJY4cA=="')
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when "weak"', function(){
|
||||
it('should send weak ETag', function(done){
|
||||
var app = express()
|
||||
describe('when "weak"', function () {
|
||||
it('should send weak ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('etag', 'weak');
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
res.send('hello, world!');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', 'W/"d-1486392595"', done)
|
||||
.expect('ETag', 'W/"d-58988d13"')
|
||||
.expect(200, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a function', function(){
|
||||
it('should send custom ETag', function(done){
|
||||
var app = express()
|
||||
describe('when a function', function () {
|
||||
it('should send custom ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('etag', function(body, encoding){
|
||||
body.should.equal('hello, world!')
|
||||
encoding.should.equal('utf8')
|
||||
return '"custom"'
|
||||
app.set('etag', function (body, encoding) {
|
||||
body.should.equal('hello, world!');
|
||||
encoding.should.equal('utf8');
|
||||
return '"custom"';
|
||||
});
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
res.send('hello, world!');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('etag', '"custom"', done)
|
||||
.expect('ETag', '"custom"')
|
||||
.expect(200, done);
|
||||
})
|
||||
|
||||
it('should not send falsy ETag', function(done){
|
||||
var app = express()
|
||||
it('should not send falsy ETag', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set('etag', function(body, encoding){
|
||||
return undefined
|
||||
app.set('etag', function (body, encoding) {
|
||||
return undefined;
|
||||
});
|
||||
|
||||
app.use(function(req, res){
|
||||
app.use(function (req, res) {
|
||||
res.send('hello, world!');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.end(function(err, res){
|
||||
res.headers.should.not.have.property('etag')
|
||||
done();
|
||||
})
|
||||
.expect(shouldNotHaveHeader('ETag'))
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function shouldNotHaveHeader(header) {
|
||||
return function (res) {
|
||||
assert.ok(!(header.toLowerCase() in res.headers), 'should not have header ' + header)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,30 @@ describe('res', function(){
|
||||
.expect(200, 'tobi', done);
|
||||
})
|
||||
|
||||
it('should transfer a file', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendfile('test/fixtures/name.txt');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, 'tobi', done);
|
||||
});
|
||||
|
||||
it('should transfer a directory index file', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendfile('test/fixtures/blog/');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(200, '<b>index</b>', done);
|
||||
});
|
||||
|
||||
describe('with an absolute path', function(){
|
||||
it('should transfer the file', function(done){
|
||||
var app = express();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
var express = require('../')
|
||||
, request = require('supertest')
|
||||
, res = express.response;
|
||||
var express = require('..');
|
||||
var request = require('supertest');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.set(field, value)', function(){
|
||||
@@ -18,10 +17,18 @@ describe('res', function(){
|
||||
.end(done);
|
||||
})
|
||||
|
||||
it('should coerce to a string', function(){
|
||||
res.headers = {};
|
||||
res.set('X-Number', 123);
|
||||
res.get('X-Number').should.equal('123');
|
||||
it('should coerce to a string', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set('X-Number', 123);
|
||||
res.end(typeof res.get('X-Number'));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('X-Number', '123')
|
||||
.expect(200, 'string', done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -39,11 +46,18 @@ describe('res', function(){
|
||||
.expect('["type=ninja","language=javascript"]', done);
|
||||
})
|
||||
|
||||
it('should coerce to an array of strings', function(){
|
||||
res.headers = {};
|
||||
res.set('X-Numbers', [123, 456]);
|
||||
JSON.stringify(res.get('X-Numbers'))
|
||||
.should.equal('["123","456"]');
|
||||
it('should coerce to an array of strings', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set('X-Numbers', [123, 456]);
|
||||
res.end(JSON.stringify(res.get('X-Numbers')));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('X-Numbers', '123, 456')
|
||||
.expect(200, '["123","456"]', done);
|
||||
})
|
||||
})
|
||||
|
||||
@@ -65,10 +79,18 @@ describe('res', function(){
|
||||
.end(done);
|
||||
})
|
||||
|
||||
it('should coerce to a string', function(){
|
||||
res.headers = {};
|
||||
res.set({ 'X-Number': 123 });
|
||||
res.get('X-Number').should.equal('123');
|
||||
it('should coerce to a string', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set({ 'X-Number': 123 });
|
||||
res.end(typeof res.get('X-Number'));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('X-Number', '123')
|
||||
.expect(200, 'string', done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
105
test/res.vary.js
105
test/res.vary.js
@@ -1,55 +1,96 @@
|
||||
|
||||
var express = require('../')
|
||||
, should = require('should');
|
||||
|
||||
function response() {
|
||||
var res = Object.create(express.response);
|
||||
res._headers = {};
|
||||
return res;
|
||||
}
|
||||
var assert = require('assert');
|
||||
var express = require('..');
|
||||
var request = require('supertest');
|
||||
|
||||
describe('res.vary()', function(){
|
||||
describe('with no arguments', function(){
|
||||
it('should not set Vary', function(){
|
||||
var res = response();
|
||||
res.vary();
|
||||
should.not.exist(res.get('Vary'));
|
||||
it('should not set Vary', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.vary();
|
||||
res.end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(shouldNotHaveHeader('Vary'))
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an empty array', function(){
|
||||
it('should not set Vary', function(){
|
||||
var res = response();
|
||||
res.vary([]);
|
||||
should.not.exist(res.get('Vary'));
|
||||
it('should not set Vary', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.vary([]);
|
||||
res.end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect(shouldNotHaveHeader('Vary'))
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('with an array', function(){
|
||||
it('should set the values', function(){
|
||||
var res = response();
|
||||
res.vary(['Accept', 'Accept-Language', 'Accept-Encoding']);
|
||||
res.get('Vary').should.equal('Accept, Accept-Language, Accept-Encoding');
|
||||
it('should set the values', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.vary(['Accept', 'Accept-Language', 'Accept-Encoding']);
|
||||
res.end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Vary', 'Accept, Accept-Language, Accept-Encoding')
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('with a string', function(){
|
||||
it('should set the value', function(){
|
||||
var res = response();
|
||||
res.vary('Accept');
|
||||
res.get('Vary').should.equal('Accept');
|
||||
it('should set the value', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.vary('Accept');
|
||||
res.end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Vary', 'Accept')
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the value is present', function(){
|
||||
it('should not add it again', function(){
|
||||
var res = response();
|
||||
res.vary('Accept');
|
||||
res.vary('Accept-Encoding');
|
||||
res.vary('Accept-Encoding');
|
||||
res.vary('Accept-Encoding');
|
||||
res.vary('Accept');
|
||||
res.get('Vary').should.equal('Accept, Accept-Encoding');
|
||||
it('should not add it again', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.vary('Accept');
|
||||
res.vary('Accept-Encoding');
|
||||
res.vary('Accept-Encoding');
|
||||
res.vary('Accept-Encoding');
|
||||
res.vary('Accept');
|
||||
res.end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Vary', 'Accept, Accept-Encoding')
|
||||
.expect(200, done);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function shouldNotHaveHeader(header) {
|
||||
return function (res) {
|
||||
assert.ok(!(header.toLowerCase() in res.headers), 'should not have header ' + header);
|
||||
};
|
||||
}
|
||||
|
||||
35
test/support/tmpl.js
Normal file
35
test/support/tmpl.js
Normal file
@@ -0,0 +1,35 @@
|
||||
var fs = require('fs');
|
||||
|
||||
var variableRegExp = /\$([0-9a-zA-Z\.]+)/g;
|
||||
|
||||
module.exports = function renderFile(fileName, options, callback) {
|
||||
function onReadFile(err, str) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
str = str.replace(variableRegExp, generateVariableLookup(options));
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
|
||||
callback(err, str);
|
||||
}
|
||||
|
||||
fs.readFile(fileName, 'utf8', onReadFile);
|
||||
};
|
||||
|
||||
function generateVariableLookup(data) {
|
||||
return function variableLookup(str, path) {
|
||||
var parts = path.split('.');
|
||||
var value = data;
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
value = value[parts[i]];
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
}
|
||||
@@ -28,18 +28,18 @@ describe('utils.etag(body, encoding)', function(){
|
||||
describe('utils.wetag(body, encoding)', function(){
|
||||
it('should support strings', function(){
|
||||
utils.wetag('express!')
|
||||
.should.eql('W/"8-3098196679"')
|
||||
.should.eql('W/"8-b8aabac7"')
|
||||
})
|
||||
|
||||
it('should support utf8 strings', function(){
|
||||
utils.wetag('express❤', 'utf8')
|
||||
.should.eql('W/"a-1751845617"')
|
||||
.should.eql('W/"a-686b0af1"')
|
||||
})
|
||||
|
||||
it('should support buffer', function(){
|
||||
var buf = new Buffer('express!')
|
||||
utils.wetag(buf)
|
||||
.should.eql('W/"8-3098196679"');
|
||||
.should.eql('W/"8-b8aabac7"');
|
||||
})
|
||||
|
||||
it('should support empty string', function(){
|
||||
|
||||
Reference in New Issue
Block a user