Compare commits

...

312 Commits

Author SHA1 Message Date
Douglas Christopher Wilson
dc538f6e81 4.16.4 2018-10-10 23:50:45 -04:00
Douglas Christopher Wilson
62a59b6ace build: update example dependencies 2018-09-27 18:09:27 -04:00
Douglas Christopher Wilson
451ee5d9c1 build: supertest@3.3.0 2018-09-24 23:40:21 -04:00
Douglas Christopher Wilson
f07f368fba build: mocha@5.2.0 2018-09-21 23:16:17 -04:00
Douglas Christopher Wilson
09d5654488 build: restructure CI build steps 2018-09-21 23:01:22 -04:00
Douglas Christopher Wilson
3d10279826 Fix issue where "Request aborted" may be logged in res.sendfile 2018-09-19 23:25:16 -04:00
Douglas Christopher Wilson
5e9de5dcb6 deps: safe-buffer@5.1.2 2018-09-19 14:47:48 -04:00
Douglas Christopher Wilson
5de1a08ebf build: supertest@2.0.0 2018-09-19 14:06:22 -04:00
Douglas Christopher Wilson
4480fb997e deps: proxy-addr@~2.0.4 2018-09-19 12:40:40 -04:00
Felix Bünemann
b8fb6a7fb1 deps: body-parser@1.18.3
closes #3655
closes #3706
2018-09-18 21:58:46 -04:00
Douglas Christopher Wilson
b4eb1f59d3 deps: qs@6.5.2 2018-09-18 21:56:31 -04:00
Linus Unnebäck
431f65305e lint: move removed middlewares list to a variable
closes #3558
closes #3677
closes #3678
2018-09-13 18:46:45 -04:00
Andreas Kohn
f3fa758af9 Fix JSDoc for Router constructor
fixes #3598
fixes #3599
fixes #3698
2018-09-13 18:44:47 -04:00
Logan Ripplinger
ede24da964 examples: fix typo in multi-router example
closes #3718
2018-09-13 18:15:48 -04:00
Douglas Christopher Wilson
d5b33cfad8 build: update example dependencies 2018-09-13 12:26:36 -04:00
Douglas Christopher Wilson
c39d7d9339 build: Node.js@8.12 2018-09-13 12:23:38 -04:00
Douglas Christopher Wilson
f95dbc28fd build: should@13.2.3 2018-07-31 17:09:27 -04:00
Douglas Christopher Wilson
ac89f6f121 build: Node.js@8.11 2018-06-07 00:12:07 -04:00
Douglas Christopher Wilson
3d8ca8ad4a build: Node.js@6.14 2018-06-07 00:04:28 -04:00
Douglas Christopher Wilson
02c753583e build: Node.js@4.9 2018-06-06 23:50:03 -04:00
Douglas Christopher Wilson
3ed5090ca9 4.16.3 2018-03-12 13:38:44 -04:00
Douglas Christopher Wilson
76bf96e9ce deps: finalhandler@1.1.1 2018-03-12 11:20:19 -04:00
Douglas Christopher Wilson
d3bdc3b663 build: marked@0.3.17 2018-03-12 11:17:26 -04:00
Douglas Christopher Wilson
0e88dceac2 deps: accepts@~1.3.5 2018-02-28 23:44:00 -05:00
Douglas Christopher Wilson
e69a29d9c2 deps: type-is@~1.6.16 2018-02-28 19:55:34 -05:00
Douglas Christopher Wilson
0083372bed deps: proxy-addr@~2.0.3 2018-02-26 23:18:07 -05:00
Douglas Christopher Wilson
f3c5f7ee29 build: test against Node.js 10.x nightly 2018-02-13 21:21:26 -05:00
Alejandro Estrada
40e04ec7a6 lint: remove usages of "=="
closes #3540
2018-02-13 19:30:57 -05:00
Douglas Christopher Wilson
972ada9079 tests: remove duplicate block in router test 2018-02-13 17:14:48 -05:00
Steven Anthony
80e64691e1 examples: add full urls to web-service example
closes #3519
2018-02-13 16:50:13 -05:00
Yuta Hiroto
98b0b66b6c build: use yaml eslint configuration
closes #3561
2018-02-13 16:45:40 -05:00
Douglas Christopher Wilson
cbaa04629a deps: serve-static@1.13.2 2018-02-09 13:20:09 -05:00
Douglas Christopher Wilson
276a80895c deps: send@0.16.2 2018-02-09 13:09:25 -05:00
Douglas Christopher Wilson
94a6cbfbfe tests: remove unnecessary functions for supertest 2018-01-17 00:28:25 -05:00
Douglas Christopher Wilson
f8fba68ec0 tests: use supertest expect to test body 2018-01-17 00:20:15 -05:00
Douglas Christopher Wilson
c6f12a8971 deps: statuses@~1.4.0 2018-01-17 00:00:22 -05:00
Douglas Christopher Wilson
323572610b deps: encodeurl@~1.0.2 2018-01-16 23:50:41 -05:00
Douglas Christopher Wilson
f448a96685 deps: depd@~1.1.2 2018-01-16 23:46:11 -05:00
Douglas Christopher Wilson
68e824cbff build: remove Node.js 8 nightly build 2018-01-16 19:19:03 -05:00
Douglas Christopher Wilson
086e56f1c4 build: marked@0.3.12 2018-01-16 19:12:34 -05:00
Douglas Christopher Wilson
b4020ec92b build: should@13.2.1 2018-01-16 19:09:25 -05:00
Douglas Christopher Wilson
fe0bc4082d build: Node.js@8.9 2018-01-02 22:38:09 -05:00
Douglas Christopher Wilson
1780ed1091 build: Node.js@6.12 2018-01-02 21:47:13 -05:00
Douglas Christopher Wilson
b49af6a674 build: should@13.2.0 2018-01-02 19:46:31 -05:00
Douglas Christopher Wilson
a743d5be4d build: marked@0.3.9 2018-01-02 19:45:25 -05:00
David Wu
187d1f57c9 docs: remove gratipay badges
closes #3524
2018-01-02 19:41:43 -05:00
chainhelen
950f4423f0 tests: separate res.send() chain test
closes #3448
2018-01-02 19:26:27 -05:00
Yaman Jain
53bee2506d examples: use https github url
closes #3465
2018-01-02 19:05:52 -05:00
Douglas Christopher Wilson
351396f971 4.16.2 2017-10-09 22:55:18 -04:00
Douglas Christopher Wilson
b97faff6e2 perf: skip parsing of entire "X-Forwarded-Proto" header 2017-10-09 22:43:23 -04:00
David Wood
b7817ab1b0 Fix TypeError in res.send when given Buffer and ETag header set
fixes #3445
2017-10-09 22:11:49 -04:00
Douglas Christopher Wilson
48aba21ea4 docs: add missing history for res.download change 2017-10-04 23:09:22 -04:00
Douglas Christopher Wilson
de129c289d tests: run mocha with --no-exit to detect hangs
closes #3439
2017-10-01 00:48:29 -04:00
Douglas Christopher Wilson
e3f7f51f5f 4.16.1 2017-09-29 16:23:23 -04:00
Douglas Christopher Wilson
6f823e409c deps: serve-static@1.13.1
closes #3436
2017-09-29 16:12:06 -04:00
Douglas Christopher Wilson
6d9b13cced deps: send@0.16.1 2017-09-29 15:56:55 -04:00
Douglas Christopher Wilson
f974d22c66 4.16.0 2017-09-28 13:57:23 -04:00
Douglas Christopher Wilson
8d4ceb623d docs: add more information to installation 2017-09-28 13:55:15 -04:00
Douglas Christopher Wilson
c0136d8b48 Add express.json and express.urlencoded to parse bodies
closes #2211
2017-09-28 13:22:36 -04:00
Douglas Christopher Wilson
86f5df00ed deps: serve-static@1.13.0
closes #3197
2017-09-28 13:08:38 -04:00
Daniel Tschinder
41964580a8 deps: send@0.16.0
closes #3431
closes #3435
2017-09-28 12:39:05 -04:00
Douglas Christopher Wilson
ddeb71301c tests: add maxAge option tests for res.sendFile 2017-09-28 12:32:27 -04:00
Greg Guthe
7154014785 Add "escape json" setting for res.json and res.jsonp
closes #3268
closes #3269
2017-09-28 12:03:42 -04:00
Douglas Christopher Wilson
628438d8d8 deps: update example dependencies 2017-09-28 11:36:20 -04:00
Aaron Clover
a24fd0ca6c Add options to res.download
closes #3327
closes #3370
2017-09-28 11:11:08 -04:00
Douglas Christopher Wilson
95fb5cc268 perf: remove dead .charset set in res.jsonp 2017-09-28 10:30:10 -04:00
chainhelen
44591fee23 deps: vary@~1.1.2
closes #3434
2017-09-28 10:08:23 -04:00
Hrvoje Šimić
2df1ad26a5 Improve error messages when non-function provided as middleware
closes #3426
2017-09-28 09:20:37 -04:00
Douglas Christopher Wilson
12c3712468 Use safe-buffer for improved Buffer API 2017-09-28 08:26:39 -04:00
Hrvoje Šimić
fa272edf84 docs: fix typo in jsdoc comment
closes #3430
2017-09-28 08:05:54 -04:00
Lawrence Page
d9d09b8b90 perf: re-use options object when generating ETags
closes #3313
closes #3314
2017-09-28 08:04:42 -04:00
Douglas Christopher Wilson
02a9d5fb28 deps: proxy-addr@~2.0.2
closes #3432
2017-09-28 01:18:04 -04:00
Douglas Christopher Wilson
c2f4fb5356 deps: finalhandler@1.1.0 2017-09-28 00:42:05 -04:00
Douglas Christopher Wilson
673d51f4f0 deps: utils-merge@1.0.1 2017-09-28 00:19:30 -04:00
Douglas Christopher Wilson
5cc761c865 deps: parseurl@~1.3.2 2017-09-28 00:04:47 -04:00
Douglas Christopher Wilson
ad7d96db47 deps: qs@6.5.1 2017-09-27 21:31:39 -04:00
Douglas Christopher Wilson
e62bb8bf9f deps: etag@~1.8.1 2017-09-27 21:30:43 -04:00
Douglas Christopher Wilson
70589c3aef deps: content-type@~1.0.4 2017-09-27 21:30:08 -04:00
Douglas Christopher Wilson
9a99c15270 deps: accepts@~1.3.4 2017-09-27 21:28:25 -04:00
Douglas Christopher Wilson
550043c217 deps: setprototypeof@1.1.0 2017-09-25 21:14:00 -04:00
Douglas Christopher Wilson
48940e6120 Skip Buffer encoding when not generating ETag for small response 2017-09-25 21:12:47 -04:00
Douglas Christopher Wilson
80f1ea9bec Improve error message when autoloading invalid view engine
fixes #3403
2017-09-25 21:11:33 -04:00
Douglas Christopher Wilson
c3fb7e5adc build: test against Node.js 9.x nightly 2017-09-25 21:06:00 -04:00
Douglas Christopher Wilson
94fdb674b1 build: support Node.js 8.x 2017-09-25 20:57:54 -04:00
Douglas Christopher Wilson
ea3d605652 4.15.5 2017-09-25 01:04:38 -04:00
Douglas Christopher Wilson
40435ec997 deps: serve-static@1.12.6 2017-09-22 20:28:52 -04:00
Douglas Christopher Wilson
7137bf567d deps: send@0.15.6 2017-09-22 20:27:37 -04:00
Douglas Christopher Wilson
bd1672f0a4 deps: finalhandler@~1.0.6 2017-09-22 20:26:30 -04:00
Douglas Christopher Wilson
9395db4c22 deps: debug@2.6.9 2017-09-22 20:25:18 -04:00
Kunal Pathak
19a2eeb476 tests: check render error without engine-specific message
closes #3251
2017-09-21 22:45:26 -04:00
Douglas Christopher Wilson
d7da22550d build: should@13.1.0 2017-09-21 20:49:14 -04:00
Douglas Christopher Wilson
961dbff904 deps: serve-static@1.12.5 2017-09-21 20:48:23 -04:00
Douglas Christopher Wilson
9e0fa7f1ca deps: send@0.15.5 2017-09-21 20:46:42 -04:00
Douglas Christopher Wilson
9e067ad2cb deps: fresh@0.5.2 2017-09-21 20:45:32 -04:00
Douglas Christopher Wilson
de5fb62b1a deps: update example dependencies 2017-09-17 20:13:05 -04:00
Douglas Christopher Wilson
b208b24f83 build: should@13.0.1 2017-09-13 20:09:33 -04:00
Douglas Christopher Wilson
78e55108e4 build: mocha@3.5.3 2017-09-13 20:03:42 -04:00
Douglas Christopher Wilson
48817a798f build: remove minor pin for nightly 2017-08-17 22:03:40 -04:00
Douglas Christopher Wilson
a4bd4373b2 4.15.4 2017-08-06 22:03:53 -04:00
Douglas Christopher Wilson
a50f1098d0 deps: serve-static@1.12.4 2017-08-06 02:38:02 -04:00
Douglas Christopher Wilson
e2d725e016 deps: send@0.15.4 2017-08-06 02:37:10 -04:00
Douglas Christopher Wilson
e0066227f7 lint: remove all unused varaibles 2017-08-06 00:19:32 -04:00
Douglas Christopher Wilson
44881fabe3 docs: update collaborator guide for lint script 2017-08-06 00:18:57 -04:00
Douglas Christopher Wilson
1dbaae51dd deps: update example dependencies 2017-08-05 23:54:31 -04:00
Douglas Christopher Wilson
56e90e3c72 lint: add eslint rules that cover editorconfig 2017-08-05 23:37:39 -04:00
Daniel Walasek
713d2aed93 tests: fix incorrect should usage
closes #3387
2017-08-05 20:10:35 -04:00
Douglas Christopher Wilson
e0aa8bf74e build: mocha@3.5.0 2017-08-04 00:26:50 -04:00
Douglas Christopher Wilson
85770a71fc deps: finalhandler@~1.0.4 2017-08-04 00:25:59 -04:00
Hung HOANG
daf66beda4 examples: fix path join in ejs example
fixes #3382
closes #3383
closes #3385
2017-08-03 21:20:55 -04:00
Douglas Christopher Wilson
b2af101821 build: ejs@2.5.7 2017-08-02 23:32:44 -04:00
Douglas Christopher Wilson
3eb16c233c deps: depd@~1.1.1 2017-08-02 23:30:47 -04:00
Douglas Christopher Wilson
582381bceb deps: proxy-addr@~1.1.5 2017-07-26 13:09:46 -04:00
Owen Luke
5e16f400f1 examples: use 1-based visitor count in cookie-sessions
closes #3312
2017-07-26 13:05:41 -04:00
Piper Chester
43dff4ceb3 docs: fix GitHub capitalization
closes #3353
2017-07-26 11:53:05 -04:00
Douglas Christopher Wilson
04beebb2c0 build: Node.js@6.11 2017-07-26 11:52:42 -04:00
Douglas Christopher Wilson
1adee79e63 deps: update example dependencies 2017-06-30 23:58:01 -04:00
Douglas Christopher Wilson
bd5951e603 deps: debug@2.6.8
closes #3286
closes #3337
2017-06-30 23:51:18 -04:00
Douglas Christopher Wilson
deffce5704 deps: qs@6.5.0 2017-06-30 23:47:12 -04:00
Douglas Christopher Wilson
48777dc377 build: mocha@3.4.2 2017-06-04 19:12:30 -04:00
Douglas Christopher Wilson
9467a392e3 build: Node.js@7.10 2017-06-04 19:09:25 -04:00
Owen Luke
9f019c8c69 examples: add comment about Redis install in examples
closes #3310
2017-05-17 21:18:35 -04:00
Owen Luke
cf37240e73 examples: fix reference error in view-constructor
closes #3310
2017-05-17 21:17:47 -04:00
Owen Luke
60f87f8074 examples: fix posts link in route-separation example
closes #3310
2017-05-17 21:17:16 -04:00
Owen Luke
fde8f647d3 examples: fix route in params example
closes #3310
2017-05-17 21:14:47 -04:00
Douglas Christopher Wilson
6da454c7fb 4.15.3 2017-05-17 02:14:11 -04:00
Douglas Christopher Wilson
5cf473dc5d deps: debug@2.6.7 2017-05-17 02:08:50 -04:00
Douglas Christopher Wilson
65494692c2 build: mocha@3.4.1 2017-05-17 01:57:31 -04:00
Douglas Christopher Wilson
bc2986fe59 deps: finalhandler@~1.0.3 2017-05-17 01:56:36 -04:00
Douglas Christopher Wilson
58cfc9911b deps: serve-static@1.12.3 2017-05-17 01:47:17 -04:00
Douglas Christopher Wilson
ad4456c491 deps: send@0.15.3 2017-05-17 01:46:34 -04:00
Douglas Christopher Wilson
1ba9a9ac23 deps: update example dependencies 2017-05-17 01:28:21 -04:00
Oz Michaeli
ae0b630ac7 Fix error when res.set cannot add charset to Content-Type
fixes #3303
closes #3305
closes #3307
2017-05-14 23:58:25 -04:00
Douglas Christopher Wilson
5ea2a8ff8e build: Node.js@7.9 2017-05-14 23:29:13 -04:00
Tony Anisimov
de41c0bfa4 Fix res.cookie jsdoc comment
closes #3304
2017-05-11 15:51:03 -04:00
Colin Richardson
a13938eed7 tests: add tests for res.location('back')
closes #3292
closes #3293
2017-05-07 19:26:33 -04:00
Douglas Christopher Wilson
1b6e7004b7 deps: send@0.15.2 2017-04-27 01:11:58 -04:00
Douglas Christopher Wilson
2d1dade36a deps: serve-static@1.12.2 2017-04-27 00:00:57 -04:00
Douglas Christopher Wilson
df4f2719db deps: type-is@~1.6.15 2017-04-26 23:49:41 -04:00
asaf david
c087a45b9c Fix typo in variable name setPrototypeOf
closes #3266
2017-03-31 22:27:00 -04:00
Douglas Christopher Wilson
347d4db3ca deps: proxy-addr@~1.1.4 2017-03-28 22:56:32 -04:00
Jamie Barton
aabf7802a9 docs: fix the security issues heading format
closes #3256
2017-03-24 17:07:06 -04:00
Jamie Barton
3763d73a1f examples: replace jade with hbs in mvc example
fixes #3181
closes #3185
closes #3243
closes #3245
closes #3249
2017-03-23 00:45:23 -04:00
Douglas Christopher Wilson
8acaa9a3ea deps: finalhandler@~1.0.1
fixes #3252
2017-03-22 02:12:06 -04:00
Douglas Christopher Wilson
dbf092d3ea deps: vary@~1.1.1 2017-03-22 02:10:43 -04:00
Wes Todd
efd7032f71 build: Add .editorconfig
closes #3221
2017-03-19 16:46:37 -04:00
Douglas Christopher Wilson
2189ff14a9 lint: remove trailing new lines from docs 2017-03-19 16:45:58 -04:00
Jamie Barton
245fa8942a examples: replace jade with ejs in route-separation
closes #3241
2017-03-17 00:09:50 -04:00
Douglas Christopher Wilson
1b6ad08095 deps: debug@2.6.3 2017-03-14 23:53:19 -04:00
Douglas Christopher Wilson
a1fffda3f2 build: should@11.2.1 2017-03-14 23:46:29 -04:00
Jamie Barton
f44368f8be examples: replace jade with ejs in view-locals
closes #3240
2017-03-09 23:41:15 -05:00
Jamie Barton
64dd446aa8 docs: remove dead link to translated readme
closes #3239
2017-03-09 23:37:06 -05:00
Douglas Christopher Wilson
d43b074f0b 4.15.2 2017-03-06 08:34:38 -05:00
Douglas Christopher Wilson
05fd1e4441 deps: update example dependencies 2017-03-06 08:33:37 -05:00
Douglas Christopher Wilson
85c96fd64e deps: qs@6.4.0 2017-03-06 08:32:13 -05:00
Douglas Christopher Wilson
d32ed68b29 4.15.1 2017-03-05 23:19:32 -05:00
Jamie Barton
57d3dfd9f8 examples: merge the jade example into ejs
closes #3223
2017-03-05 23:13:53 -05:00
chainhelen
eece3850bc tests: use path.join instead of concatenation
closes #3236
2017-03-05 23:08:47 -05:00
chainhelen
8eb95ae579 examples: use path.join instead of concatenation
closes #3236
2017-03-05 23:07:24 -05:00
Douglas Christopher Wilson
67168fe231 deps: serve-static@1.12.1
fixes #3233
2017-03-05 00:08:16 -05:00
Douglas Christopher Wilson
c0089d971b deps: send@0.15.1 2017-03-05 00:06:59 -05:00
Douglas Christopher Wilson
dc8acc8676 tests: use supertest expect for simple assertions 2017-03-05 00:04:47 -05:00
Jianru Lin
7027b37764 lint: remove unused err argument
closes #3228
2017-03-04 23:22:08 -05:00
Jamie Barton
b4550fbe7a Use ejs instead of jade within engine jsdoc
closes #3222
2017-03-01 19:34:30 -05:00
Jamie Barton
4012846d25 examples: use static assets in search example
closes #3224
2017-03-01 18:22:36 -05:00
Douglas Christopher Wilson
6d9b127989 build: Node.js@7.6 2017-03-01 17:44:13 -05:00
Douglas Christopher Wilson
504a51c040 4.15.0 2017-03-01 17:22:18 -05:00
Douglas Christopher Wilson
7f96896f67 deps: update example dependencies 2017-03-01 17:17:50 -05:00
Douglas Christopher Wilson
f59de6ae3d build: Node.js@7.7 2017-03-01 17:16:21 -05:00
Douglas Christopher Wilson
72475543bc build: Node.js@6.10 2017-03-01 17:16:09 -05:00
Douglas Christopher Wilson
146a13ede7 build: Node.js@4.8 2017-03-01 17:15:57 -05:00
Blake Embrey
9722202df9 Add next("router") to exit from router
closes #2241
closes #2371
2017-02-26 14:38:05 -05:00
Douglas Christopher Wilson
51f52901eb Fix case where router.use skipped requests routes did not
fixes #3037
2017-02-26 13:59:47 -05:00
Douglas Christopher Wilson
8b6dc6ceec Use "%o" in path debug to tell types apart 2017-02-26 13:45:35 -05:00
Douglas Christopher Wilson
081b811b10 perf: add fast match path for "*" route 2017-02-26 13:32:21 -05:00
Douglas Christopher Wilson
1f71fae23b tests: add lone "*" route tests 2017-02-26 13:21:18 -05:00
Douglas Christopher Wilson
acc4a619d9 deps: serve-static@1.12.0 2017-02-25 19:31:39 -05:00
Douglas Christopher Wilson
1b43166fca deps: send@0.15.0 2017-02-25 17:53:34 -05:00
Douglas Christopher Wilson
6022567c75 Use setprototypeof module to replace __proto__ setting
closes #1967
closes #2613
closes #3103
closes #3164
2017-02-23 01:56:58 -05:00
Douglas Christopher Wilson
12ff56e1e4 Use Object.create to setup request & response prototypes 2017-02-23 01:52:49 -05:00
Douglas Christopher Wilson
668f545fd4 Skip routing when req.url is not set 2017-02-22 23:42:57 -05:00
Douglas Christopher Wilson
7bc5f1af96 lint: consolidate layer match failure path 2017-02-22 23:09:36 -05:00
Douglas Christopher Wilson
8de1230d03 lint: remove unreachable code 2017-02-22 23:03:20 -05:00
Wes
034165caeb Use statuses instead of http module for status messages
closes #3215
2017-02-22 02:16:52 -05:00
Douglas Christopher Wilson
a9f15aaefc deps: fresh@0.5.0 2017-02-22 02:11:06 -05:00
Douglas Christopher Wilson
f87abb3493 Remove usage of res._headers private field
closes #3174
2017-02-20 22:08:33 -05:00
Douglas Christopher Wilson
cd7d241a5d build: test against Node.js 8.x nightly 2017-02-20 21:29:19 -05:00
Douglas Christopher Wilson
9f4dbae083 deps: etag@~1.8.0 2017-02-20 21:25:26 -05:00
Douglas Christopher Wilson
f2bbd10ae7 deps: update example dependencies 2017-02-20 21:24:55 -05:00
Douglas Christopher Wilson
92c859dd05 deps: finalhandler@~1.0.0 2017-02-20 21:24:54 -05:00
Ángel Sanz
485b6f86ac perf: improve req.ips performance
closes #2723
2017-02-20 21:24:54 -05:00
Douglas Christopher Wilson
906164b204 deps: qs@6.3.1 2017-02-20 21:24:54 -05:00
Douglas Christopher Wilson
c63424a0a1 deps: debug@2.6.1 2017-02-20 21:24:54 -05:00
Douglas Christopher Wilson
bbed8021c6 build: support Node.js 7.x 2017-02-20 21:24:54 -05:00
Pravdomil
fefd729037 Add debug message when loading view engine
closes #3158
2017-02-20 21:24:34 -05:00
Mike Tunnicliffe
1a99bb0519 docs: add release guide
closes #2857
closes #2890
2017-02-20 20:05:54 -05:00
Douglas Christopher Wilson
4420a7bd94 docs: update link to expressjs.com website repo 2017-02-20 18:25:42 -05:00
Rand McKinney
1678613db1 docs: add guide for writing readmes
closes #3209
2017-02-20 18:21:38 -05:00
Rand McKinney
f3a47e39a4 docs: update collaborator guide 2017-02-20 17:57:14 -05:00
Douglas Christopher Wilson
3e3d35777d tests: update req.range tests to run through express 2017-02-20 17:09:21 -05:00
Douglas Christopher Wilson
eb326d7ecb tests: update req.is tests to run through express 2017-02-20 16:55:15 -05:00
Douglas Christopher Wilson
7ef92f8a17 examples: remove semi-broken expose-data-to-client example 2017-02-16 00:42:57 -05:00
Rand McKinney
c48014fde8 docs: minor fixes to contributing guide 2017-02-16 00:22:31 -05:00
Douglas Christopher Wilson
034f261fea examples: use pbkdf2-password module in auth example
closes #3207
2017-02-15 23:36:17 -05:00
Sebastian Van Sande
abd1de73c1 tests: fix misnamed app.router test section
fixes #3194
closes #3199
2017-02-07 19:42:35 -05:00
Douglas Christopher Wilson
fb3946f454 lint: fix broken indentation in tests 2017-02-04 20:54:47 -05:00
Tom Hosford
4f291e7d55 examples: use res.format in error-pages
closes #3195
2017-02-04 20:48:12 -05:00
Takuma Hanatani
94377f681d lint: remove unnecessary semicolon
closes #3191
2017-02-04 20:43:50 -05:00
Douglas Christopher Wilson
0437c513f2 4.14.1 2017-01-28 17:21:24 -05:00
Douglas Christopher Wilson
1f70b76c45 build: Node.js@4.7 2017-01-28 16:56:34 -05:00
Douglas Christopher Wilson
0b39fa2f7c build: should@11.2.0 2017-01-28 16:40:40 -05:00
Douglas Christopher Wilson
0d6c64fdfd deps: type-is@~1.6.14 2017-01-26 22:54:05 -05:00
Douglas Christopher Wilson
c238aca438 examples: remove big-view example 2017-01-26 22:48:08 -05:00
Douglas Christopher Wilson
6b506d801a examples: fix mvc example to ignore files in controllers dir
fixes #3182
2017-01-26 22:33:52 -05:00
Douglas Christopher Wilson
dc48f27f60 deps: update example dependencies 2017-01-26 22:25:39 -05:00
Douglas Christopher Wilson
8e14e06ebf deps: serve-static@~1.11.2 2017-01-24 07:40:20 -08:00
Douglas Christopher Wilson
572657ee4a deps: send@0.14.2 2017-01-23 10:43:11 -05:00
Douglas Christopher Wilson
cfae537d3b deps: finalhandler@0.5.1 2017-01-21 01:05:17 -05:00
Douglas Christopher Wilson
a3d635309c deps: proxy-addr@~1.1.3 2017-01-21 01:00:52 -05:00
Douglas Christopher Wilson
a2e323a012 build: should@11.1.2 2017-01-21 00:59:29 -05:00
Douglas Christopher Wilson
e73913b583 build: mocha@3.2.0 2017-01-21 00:46:28 -05:00
Douglas Christopher Wilson
ddc93aa0e2 deps: content-disposition@0.5.2 2017-01-21 00:39:46 -05:00
Zachary Lester
6723b4419a tests: add test for res.sendFile "cacheContol" option
closes #3061
2017-01-21 00:33:29 -05:00
SeongHeon Kim
d1d9631b97 docs: remove link to missing section
closes #3179
2017-01-21 00:26:49 -05:00
Deniz Tetik
1a17888073 docs: fix minor grammatical error
closes #3178
2017-01-21 00:25:47 -05:00
Douglas Christopher Wilson
f6dca56e72 build: istanbul@0.4.5 2016-12-03 00:08:46 -05:00
Douglas Christopher Wilson
6210e47cb6 build: after@0.8.2 2016-12-03 00:04:47 -05:00
Douglas Christopher Wilson
1bcc9b1236 build: Node.js@6.9 2016-12-02 22:19:04 -05:00
Douglas Christopher Wilson
421ad5aaaa build: Node.js@5.12 2016-12-02 22:12:33 -05:00
Douglas Christopher Wilson
505f8482f2 build: Node.js@4.6 2016-12-02 22:09:46 -05:00
Vishvajit Pathak
bd47aeb88d tests: fix typos in test descriptions
closes #3129
closes #3130
2016-11-18 13:47:28 -05:00
Hamza
305f982bd7 exapmples: use path.join to concat paths
closes #3046
2016-07-31 22:14:05 +10:00
Douglas Christopher Wilson
9375a9afa9 4.14.0 2016-06-16 11:03:44 -04:00
Douglas Christopher Wilson
14cf9c5636 deps: update example dependencies 2016-06-15 18:16:08 -04:00
Douglas Christopher Wilson
605983fd0e build: should@9.0.2 2016-06-15 18:13:30 -04:00
Douglas Christopher Wilson
e06766c573 deps: finalhandler@0.5.0 2016-06-15 18:12:19 -04:00
Douglas Christopher Wilson
76eaa326ee Encode URL in res.location/res.redirect if not already encoded
fixes #2897
fixes #3003
2016-06-13 23:23:29 -04:00
Douglas Christopher Wilson
c12cc88392 build: support Node.js 6.x 2016-06-13 22:51:07 -04:00
Douglas Christopher Wilson
23c22ce3fe build: support Node.js 5.x 2016-06-13 22:50:18 -04:00
Douglas Christopher Wilson
791cabf939 deps: serve-static@~1.11.1 2016-06-12 22:38:20 -04:00
Douglas Christopher Wilson
fc40702cb7 deps: send@0.14.1 2016-06-12 22:33:44 -04:00
Douglas Christopher Wilson
c762b16f62 Improve error with invalid arguments to req.get()
fixes #2993
2016-06-03 00:07:34 -04:00
Douglas Christopher Wilson
5d642af8c3 Add "options" argument to req.range 2016-06-01 19:13:36 -04:00
Douglas Christopher Wilson
7fcf1d7d5b docs: update the req.range jsdoc comment 2016-06-01 19:04:02 -04:00
Douglas Christopher Wilson
7ee41cc23f deps: range-parser@~1.2.0 2016-06-01 18:54:11 -04:00
Douglas Christopher Wilson
8ddab697cc build: supertest@1.2.0 2016-06-01 17:31:10 -04:00
Douglas Christopher Wilson
d038689658 build: should@9.0.0 2016-06-01 17:27:06 -04:00
Douglas Christopher Wilson
c9531ac1f1 build: mocha@2.5.3 2016-06-01 17:24:08 -04:00
Douglas Christopher Wilson
98224d2c4f build: ejs@2.4.2 2016-06-01 17:22:15 -04:00
huaoguo
2e1284beb6 Fix Windows absolute path check using forward slashes
closes #3017
2016-06-01 16:47:03 -04:00
Douglas Christopher Wilson
999546dfde deps: qs@6.2.0 2016-05-31 14:28:20 -04:00
Douglas Christopher Wilson
cc25a04d10 deps: type-is@~1.6.13 2016-05-31 14:25:41 -04:00
Benjamin Tan
f90f9dde3f Improve performance for res.json/res.jsonp in most cases
closes #2900
2016-05-31 00:32:48 -04:00
Ángel Sanz
b69b7605b0 perf: use strict equality when possible
closes #2722
2016-05-31 00:25:34 -04:00
Douglas Christopher Wilson
c6039af39d deps: proxy-addr@~1.1.2 2016-05-31 00:12:54 -04:00
Douglas Christopher Wilson
bdf604a77e deps: cookie@0.3.1 2016-05-31 00:08:16 -04:00
Douglas Christopher Wilson
76c56d1ab8 deps: vary@~1.1.0 2016-05-29 14:25:27 -04:00
Douglas Christopher Wilson
2cf830b29e deps: content-type@~1.0.2 2016-05-23 23:18:41 -04:00
Douglas Christopher Wilson
e5502690d2 deps: accepts@~1.3.3 2016-05-23 23:15:52 -04:00
Douglas Christopher Wilson
31dd549f35 tests: add test for dispatching to empty route 2016-05-23 23:03:13 -04:00
Douglas Christopher Wilson
e3dd191d54 examples: escape HTML in markdown example 2016-05-23 23:00:43 -04:00
Douglas Christopher Wilson
fd48bfe8fe build: should@8.4.0 2016-05-23 22:47:25 -04:00
Douglas Christopher Wilson
d7ae24228d build: mocha@2.5.1 2016-05-23 22:44:48 -04:00
Douglas Christopher Wilson
992cd085fb build: istanbul@0.4.3 2016-05-23 22:41:26 -04:00
Douglas Christopher Wilson
20a25489de build: ejs@2.4.1 2016-05-23 22:39:59 -04:00
Douglas Christopher Wilson
741a5aac9c build: cache node_modules on CI 2016-05-23 22:12:31 -04:00
Rand McKinney
3d56e7374d docs: update location of expressjs.com repo
closes #2995
2016-05-12 20:23:54 -04:00
Douglas Christopher Wilson
12bc16e72f tests: use supertest to check response header values
closes #2983
closes #2992
2016-05-11 08:50:38 +02:00
Douglas Christopher Wilson
8931b2311a build: Node.js@4.4 2016-05-10 12:42:16 -04:00
Linus Unnebäck
bb84cf955f tests: add test for signed cookie without secret
closes #2986
2016-05-10 11:54:52 -04:00
Mikeal Rogers
f3d99a4fdb docs: add base contributing guide
closes #2918
2016-03-01 18:55:01 -05:00
Muhammad Saqib
dd2b897774 examples: comment the usage of process.nextTick
closes #2903
closes #2908
2016-02-24 21:58:50 -05:00
Sian January
4bcbf67482 docs: add branch & fork steps to contributing documentation
closes #2881
2016-02-10 18:35:54 -05:00
Andy Fleming
b5a280111f Fix jsdoc comment for res.get
closes #2882
2016-02-10 18:32:51 -05:00
Douglas Christopher Wilson
05136550c7 docs: fix some links messed up from repository move commit
closes #2861
closes #2867
2016-02-10 18:21:46 -05:00
Douglas Christopher Wilson
193bed2649 4.13.4 2016-01-21 21:10:45 -05:00
Douglas Christopher Wilson
e7a02f6a25 build: move repository to expressjs 2016-01-21 20:59:53 -05:00
Douglas Christopher Wilson
6847405974 deps: parseurl@~1.3.1 2016-01-20 00:58:09 -05:00
Douglas Christopher Wilson
f627ca8d0b deps: serve-static@~1.10.2 2016-01-20 00:56:56 -05:00
Douglas Christopher Wilson
e83eab85e4 deps: methods@~1.1.2 2016-01-17 22:17:13 -05:00
Douglas Christopher Wilson
1589ce2153 deps: merge-descriptors@1.0.1 2016-01-17 18:51:24 -05:00
Douglas Christopher Wilson
547ea368c2 deps: content-disposition@0.5.1 2016-01-17 18:00:59 -05:00
Douglas Christopher Wilson
8eee818e0b build: istanbul@0.4.2 2016-01-16 23:58:27 -05:00
Douglas Christopher Wilson
7c8456fcde deps: depd@~1.1.0 2016-01-16 23:57:07 -05:00
Douglas Christopher Wilson
53ee474c44 deps: send@0.13.1 2016-01-16 23:56:09 -05:00
Douglas Christopher Wilson
bd118c47df deps: serve-static@~1.10.1 2016-01-16 23:54:41 -05:00
Jordan Larson
f2cf28c2f3 docs: add link to Gitter 2016-01-13 13:44:41 -08:00
Douglas Christopher Wilson
e44f024dab deps: update example dependencies 2015-12-18 15:10:33 -05:00
Douglas Christopher Wilson
2493239192 build: mocha@2.3.4 2015-12-18 15:09:34 -05:00
Douglas Christopher Wilson
c73b1bee51 build: istanbul@0.4.1 2015-12-17 21:02:22 -05:00
Douglas Christopher Wilson
4f8167f23f deps: range-parser@~1.0.3 2015-12-17 20:59:12 -05:00
Douglas Christopher Wilson
c95a1077d2 deps: proxy-addr@~1.0.10 2015-12-17 20:58:41 -05:00
Douglas Christopher Wilson
7d93503914 deps: finalhandler@0.4.1 2015-12-17 20:56:04 -05:00
Douglas Christopher Wilson
2b2a1b28f3 deps: escape-html@~1.0.3 2015-12-17 20:51:32 -05:00
Rand McKinney
4416fb2746 docs: fix link to Security.md in Readme.md
closes #2829
2015-12-15 15:28:59 -05:00
ChALkeR
60f8e77d66 deps: cookie@0.1.5
closes #2799
closes #2800
closes #2801
2015-12-14 23:18:28 -05:00
Douglas Christopher Wilson
23f021a3e1 build: support Node.js 4.x
closes #2751
closes #2754
closes #2757
2015-12-14 23:10:31 -05:00
Young Jae Sim
67116cc5e6 docs: remove link to Korean translation
closes #2820
2015-12-14 23:08:54 -05:00
Rand McKinney
42b944295a Add Security document
closes #2733
closes #2804
2015-12-14 23:06:17 -05:00
Ricardo Bin
7a3b5aea11 tests: add test for res.send() without arguments
closes #2778
closes #2783
2015-11-07 00:25:06 -05:00
Alexander Shemetovsky
e5ec966b2f Fix param definition is jsdoc for app.render
fixes #2741
2015-11-07 00:18:32 -05:00
Douglas Christopher Wilson
5699d64b99 build: ejs@2.3.4 2015-11-07 00:15:39 -05:00
Douglas Christopher Wilson
747fccfb44 build: should@7.1.1 2015-11-06 22:59:46 -05:00
Douglas Christopher Wilson
9665aa2153 build: supertest@1.1.0 2015-11-06 22:57:04 -05:00
Douglas Christopher Wilson
2f37f4b28d build: istanbul@0.4.0 2015-11-06 22:51:09 -05:00
Douglas Christopher Wilson
1a59246746 build: mocha@2.3.3 2015-11-06 22:49:44 -05:00
Douglas Christopher Wilson
963d795d24 build: support io.js 3.x 2015-11-06 22:47:15 -05:00
Douglas Christopher Wilson
2f96412636 build: io.js@2.5 2015-11-06 22:16:06 -05:00
Douglas Christopher Wilson
5a4310e9da build: reduce runtime versions to one per major 2015-11-06 22:09:47 -05:00
Brendan Ashworth
2f8ac6726f tests: fix redirect tests for change in 302 status message
closes #2690
2015-08-03 15:54:03 -04:00
Douglas Christopher Wilson
ef7ad681b2 4.13.3 2015-08-03 01:02:22 -04:00
Douglas Christopher Wilson
11a77a3fff Fix inner numeric indices incorrectly altering parent req.params 2015-08-03 01:01:16 -04:00
Douglas Christopher Wilson
ee90042d0c Fix infinite loop condition using mergeParams: true 2015-08-03 00:50:48 -04:00
159 changed files with 3040 additions and 1301 deletions

11
.editorconfig Normal file
View File

@@ -0,0 +1,11 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true
[{*.js,*.json,*.yml}]
indent_size = 2
indent_style = space

2
.eslintignore Normal file
View File

@@ -0,0 +1,2 @@
coverage
node_modules

8
.eslintrc.yml Normal file
View File

@@ -0,0 +1,8 @@
root: true
rules:
eol-last: error
eqeqeq: [error, allow-null]
indent: [error, 2, { SwitchCase: 1 }]
no-trailing-spaces: error
no-unused-vars: [error, { vars: all, args: none, ignoreRestSiblings: true }]

1
.gitignore vendored
View File

@@ -15,6 +15,7 @@ Desktop.ini
# npm
node_modules
package-lock.json
*.log
*.gz

View File

@@ -2,11 +2,63 @@ language: node_js
node_js:
- "0.10"
- "0.12"
- "1.0"
- "1.8"
- "2.0"
- "2.3"
- "2.5"
- "3.3"
- "4.9"
- "5.12"
- "6.14"
- "7.10"
- "8.12"
matrix:
include:
- node_js: "9"
env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly"
- node_js: "10"
env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly"
allow_failures:
# Allow the nightly installs to fail
- env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly"
sudo: false
before_install: "npm rm --save-dev connect-redis"
script: "npm run-script test-ci"
after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls"
cache:
directories:
- node_modules
before_install:
# Configure npm
- |
# Skip updating shrinkwrap / lock
npm config set shrinkwrap false
# Remove all non-test dependencies
- |
# Remove example dependencies
npm rm --silent --save-dev connect-redis
# Setup Node.js version-specific dependencies
- |
# mocha for testing
# - use 3.x for Node.js < 6
if [[ "$(cut -d. -f1 <<< "$TRAVIS_NODE_VERSION")" -lt 6 ]]; then
npm install --silent --save-dev mocha@3.5.3
fi
- |
# supertest for http calls
# - use 2.0.0 for Node.js < 4
if [[ "$(cut -d. -f1 <<< "$TRAVIS_NODE_VERSION")" -lt 4 ]]; then
npm install --silent --save-dev supertest@2.0.0
fi
# Update Node.js modules
- |
# Prune and rebuild node_modules
if [[ -d node_modules ]]; then
npm prune
npm rebuild
fi
script:
# Run test script
- npm run test-ci
# Run linting
- npm run lint
after_script:
- |
# Upload coverage to coveralls
npm install --save-dev coveralls@2.10.0
coveralls < ./coverage/lcov.info

50
Collaborator-Guide.md Normal file
View File

@@ -0,0 +1,50 @@
## Website Issues
Open issues for the expressjs.com website in https://github.com/expressjs/expressjs.com.
## PRs and Code contributions
* Tests must pass.
* Follow the [JavaScript Standard Style](http://standardjs.com/) and `npm run lint`.
* If you fix a bug, add a test.
## Branches
Use the `master` branch for bug fixes or minor work that is intended for the
current release stream.
Use the correspondingly named branch, e.g. `5.0`, for anything intended for
a future release of Express.
## Steps for contributing
1. [Create an issue](https://github.com/expressjs/express/issues/new) for the
bug you want to fix or the feature that you want to add.
2. Create your own [fork](https://github.com/expressjs/express) on github, then
checkout your fork.
3. Write your code in your local copy. It's good practice to create a branch for
each new issue you work on, although not compulsory.
4. To run the test suite, first install the dependencies by running `npm install`,
then run `npm test`.
5. Ensure your code is linted by running `npm run lint` -- fix any issue you
see listed.
6. If the tests pass, you can commit your changes to your fork and then create
a pull request from there. Make sure to reference your issue from the pull
request comments by including the issue number e.g. `#123`.
## Issues which are questions
We will typically close any vague issues or questions that are specific to some
app you are writing. Please double check the docs and other references before
being trigger happy with posting a question issue.
Things that will help get your question issue looked at:
* Full and runnable JS code.
* Clear description of the problem or unexpected behavior.
* Clear description of the expected result.
* Steps you have taken to debug it yourself.
If you post a question and do not outline the above items or make it easy for
us to understand and reproduce your issue, it will be closed.

View File

@@ -1,25 +1,85 @@
# Express.js Community Contributing Guide 1.0
## Website Issues
The goal of this document is to create a contribution process that:
Issues for the expressjs.com website go here https://github.com/strongloop/expressjs.com
* Encourages new contributions.
* Encourages contributors to remain involved.
* Avoids unnecessary processes and bureaucracy whenever possible.
* Creates a transparent decision making process that makes it clear how
contributors can be involved in decision making.
## PRs and Code contributions
## Vocabulary
* Tests must pass.
* Follow existing coding style.
* If you fix a bug, add a test.
* A **Contributor** is any individual creating or commenting on an issue or pull request.
* A **Committer** is a subset of contributors who have been given write access to the repository.
* A **TC (Technical Committee)** is a group of committers representing the required technical
expertise to resolve rare disputes.
# Logging Issues
Log an issue for any question or problem you might have. When in doubt, log an issue, and
any additional policies about what to include will be provided in the responses. The only
exception is security dislosures which should be sent privately.
Committers may direct you to another repository, ask for additional clarifications, and
add appropriate metadata before the issue is addressed.
Please be courteous and respectful. Every participant is expected to follow the
project's Code of Conduct.
# Contributions
Any change to resources in this repository must be through pull requests. This applies to all changes
to documentation, code, binary files, etc. Even long term committers and TC members must use
pull requests.
No pull request can be merged without being reviewed.
For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that
contributors in other timezones have time to review. Consideration should also be given to
weekends and other holiday periods to ensure active committers all have reasonable time to
become involved in the discussion and review process if they wish.
The default for each contribution is that it is accepted once no committer has an objection.
During review committers may also request that a specific contributor who is most versed in a
particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off"
process for contributions to land. Once all issues brought by committers are addressed it can
be landed by any committer.
In the case of an objection being raised in a pull request by another committer, all involved
committers should seek to arrive at a consensus by way of addressing concerns being expressed
by discussion, compromise on the proposed change, or withdrawal of the proposed change.
If a contribution is controversial and committers cannot agree about how to get it to land
or if it should land then it should be escalated to the TC. TC members should regularly
discuss pending contributions in order to find a resolution. It is expected that only a
small minority of issues be brought to the TC for resolution and that discussion and
compromise among committers be the default resolution mechanism.
# Becoming a Committer
All contributors who land a non-trivial contribution should be on-boarded in a timely manner,
and added as a committer, and be given write access to the repository.
Committers are expected to follow this policy and continue to send pull requests, go through
proper review, and have other committers merge their pull requests.
# TC Process
The TC uses a "consensus seeking" process for issues that are escalated to the TC.
The group tries to find a resolution that has no open objections among TC members.
If a consensus cannot be reached that has no objections then a majority wins vote
is called. It is also expected that the majority of decisions made by the TC are via
a consensus seeking process and that voting is only used as a last-resort.
Resolution may involve returning the issue to committers with suggestions on how to
move forward towards a consensus. It is not expected that a meeting of the TC
will resolve all issues on its agenda during that meeting and may prefer to continue
the discussion happening among the committers.
Members can be added to the TC at any time. Any committer can nominate another committer
to the TC and the TC uses its standard consensus seeking process to evaluate whether or
not to add this new member. Members who do not participate consistently at the level of
a majority of the other members are expected to resign.
## Issues which are questions
We will typically close any vague issues or questions that are specific to some app you are writing. Please double check the docs and other references before being trigger happy with posting a question issue.
Things that will help get your question issue looked at:
* Full and runnable JS code.
* Clear description of the problem or unexpected behavior.
* Clear description of the expected result.
* Steps you have taken to debug it yourself.
If you post a question and do not outline the above items or make it easy for us to understand and reproduce your issue, it will be closed.

View File

@@ -1,3 +1,405 @@
4.16.4 / 2018-10-10
===================
* Fix issue where `"Request aborted"` may be logged in `res.sendfile`
* Fix JSDoc for `Router` constructor
* deps: body-parser@1.18.3
- Fix deprecation warnings on Node.js 10+
- Fix stack trace for strict json parse error
- deps: depd@~1.1.2
- deps: http-errors@~1.6.3
- deps: iconv-lite@0.4.23
- deps: qs@6.5.2
- deps: raw-body@2.3.3
- deps: type-is@~1.6.16
* deps: proxy-addr@~2.0.4
- deps: ipaddr.js@1.8.0
* deps: qs@6.5.2
* deps: safe-buffer@5.1.2
4.16.3 / 2018-03-12
===================
* deps: accepts@~1.3.5
- deps: mime-types@~2.1.18
* deps: depd@~1.1.2
- perf: remove argument reassignment
* deps: encodeurl@~1.0.2
- Fix encoding `%` as last character
* deps: finalhandler@1.1.1
- Fix 404 output for bad / missing pathnames
- deps: encodeurl@~1.0.2
- deps: statuses@~1.4.0
* deps: proxy-addr@~2.0.3
- deps: ipaddr.js@1.6.0
* deps: send@0.16.2
- Fix incorrect end tag in default error & redirects
- deps: depd@~1.1.2
- deps: encodeurl@~1.0.2
- deps: statuses@~1.4.0
* deps: serve-static@1.13.2
- Fix incorrect end tag in redirects
- deps: encodeurl@~1.0.2
- deps: send@0.16.2
* deps: statuses@~1.4.0
* deps: type-is@~1.6.16
- deps: mime-types@~2.1.18
4.16.2 / 2017-10-09
===================
* Fix `TypeError` in `res.send` when given `Buffer` and `ETag` header set
* perf: skip parsing of entire `X-Forwarded-Proto` header
4.16.1 / 2017-09-29
===================
* deps: send@0.16.1
* deps: serve-static@1.13.1
- Fix regression when `root` is incorrectly set to a file
- deps: send@0.16.1
4.16.0 / 2017-09-28
===================
* Add `"json escape"` setting for `res.json` and `res.jsonp`
* Add `express.json` and `express.urlencoded` to parse bodies
* Add `options` argument to `res.download`
* Improve error message when autoloading invalid view engine
* Improve error messages when non-function provided as middleware
* Skip `Buffer` encoding when not generating ETag for small response
* Use `safe-buffer` for improved Buffer API
* deps: accepts@~1.3.4
- deps: mime-types@~2.1.16
* deps: content-type@~1.0.4
- perf: remove argument reassignment
- perf: skip parameter parsing when no parameters
* deps: etag@~1.8.1
- perf: replace regular expression with substring
* deps: finalhandler@1.1.0
- Use `res.headersSent` when available
* deps: parseurl@~1.3.2
- perf: reduce overhead for full URLs
- perf: unroll the "fast-path" `RegExp`
* deps: proxy-addr@~2.0.2
- Fix trimming leading / trailing OWS in `X-Forwarded-For`
- deps: forwarded@~0.1.2
- deps: ipaddr.js@1.5.2
- perf: reduce overhead when no `X-Forwarded-For` header
* deps: qs@6.5.1
- Fix parsing & compacting very deep objects
* deps: send@0.16.0
- Add 70 new types for file extensions
- Add `immutable` option
- Fix missing `</html>` in default error & redirects
- Set charset as "UTF-8" for .js and .json
- Use instance methods on steam to check for listeners
- deps: mime@1.4.1
- perf: improve path validation speed
* deps: serve-static@1.13.0
- Add 70 new types for file extensions
- Add `immutable` option
- Set charset as "UTF-8" for .js and .json
- deps: send@0.16.0
* deps: setprototypeof@1.1.0
* deps: utils-merge@1.0.1
* deps: vary@~1.1.2
- perf: improve header token parsing speed
* perf: re-use options object when generating ETags
* perf: remove dead `.charset` set in `res.jsonp`
4.15.5 / 2017-09-24
===================
* deps: debug@2.6.9
* deps: finalhandler@~1.0.6
- deps: debug@2.6.9
- deps: parseurl@~1.3.2
* deps: fresh@0.5.2
- Fix handling of modified headers with invalid dates
- perf: improve ETag match loop
- perf: improve `If-None-Match` token parsing
* deps: send@0.15.6
- Fix handling of modified headers with invalid dates
- deps: debug@2.6.9
- deps: etag@~1.8.1
- deps: fresh@0.5.2
- perf: improve `If-Match` token parsing
* deps: serve-static@1.12.6
- deps: parseurl@~1.3.2
- deps: send@0.15.6
- perf: improve slash collapsing
4.15.4 / 2017-08-06
===================
* deps: debug@2.6.8
* deps: depd@~1.1.1
- Remove unnecessary `Buffer` loading
* deps: finalhandler@~1.0.4
- deps: debug@2.6.8
* deps: proxy-addr@~1.1.5
- Fix array argument being altered
- deps: ipaddr.js@1.4.0
* deps: qs@6.5.0
* deps: send@0.15.4
- deps: debug@2.6.8
- deps: depd@~1.1.1
- deps: http-errors@~1.6.2
* deps: serve-static@1.12.4
- deps: send@0.15.4
4.15.3 / 2017-05-16
===================
* Fix error when `res.set` cannot add charset to `Content-Type`
* deps: debug@2.6.7
- Fix `DEBUG_MAX_ARRAY_LENGTH`
- deps: ms@2.0.0
* deps: finalhandler@~1.0.3
- Fix missing `</html>` in HTML document
- deps: debug@2.6.7
* deps: proxy-addr@~1.1.4
- deps: ipaddr.js@1.3.0
* deps: send@0.15.3
- deps: debug@2.6.7
- deps: ms@2.0.0
* deps: serve-static@1.12.3
- deps: send@0.15.3
* deps: type-is@~1.6.15
- deps: mime-types@~2.1.15
* deps: vary@~1.1.1
- perf: hoist regular expression
4.15.2 / 2017-03-06
===================
* deps: qs@6.4.0
- Fix regression parsing keys starting with `[`
4.15.1 / 2017-03-05
===================
* deps: send@0.15.1
- Fix issue when `Date.parse` does not return `NaN` on invalid date
- Fix strict violation in broken environments
* deps: serve-static@1.12.1
- Fix issue when `Date.parse` does not return `NaN` on invalid date
- deps: send@0.15.1
4.15.0 / 2017-03-01
===================
* Add debug message when loading view engine
* Add `next("router")` to exit from router
* Fix case where `router.use` skipped requests routes did not
* Remove usage of `res._headers` private field
- Improves compatibility with Node.js 8 nightly
* Skip routing when `req.url` is not set
* Use `%o` in path debug to tell types apart
* Use `Object.create` to setup request & response prototypes
* Use `setprototypeof` module to replace `__proto__` setting
* Use `statuses` instead of `http` module for status messages
* deps: debug@2.6.1
- Allow colors in workers
- Deprecated `DEBUG_FD` environment variable set to `3` or higher
- Fix error when running under React Native
- Use same color for same namespace
- deps: ms@0.7.2
* deps: etag@~1.8.0
- Use SHA1 instead of MD5 for ETag hashing
- Works with FIPS 140-2 OpenSSL configuration
* deps: finalhandler@~1.0.0
- Fix exception when `err` cannot be converted to a string
- Fully URL-encode the pathname in the 404
- Only include the pathname in the 404 message
- Send complete HTML document
- Set `Content-Security-Policy: default-src 'self'` header
- deps: debug@2.6.1
* deps: fresh@0.5.0
- Fix false detection of `no-cache` request directive
- Fix incorrect result when `If-None-Match` has both `*` and ETags
- Fix weak `ETag` matching to match spec
- perf: delay reading header values until needed
- perf: enable strict mode
- perf: hoist regular expressions
- perf: remove duplicate conditional
- perf: remove unnecessary boolean coercions
- perf: skip checking modified time if ETag check failed
- perf: skip parsing `If-None-Match` when no `ETag` header
- perf: use `Date.parse` instead of `new Date`
* deps: qs@6.3.1
- Fix array parsing from skipping empty values
- Fix compacting nested arrays
* deps: send@0.15.0
- Fix false detection of `no-cache` request directive
- Fix incorrect result when `If-None-Match` has both `*` and ETags
- Fix weak `ETag` matching to match spec
- Remove usage of `res._headers` private field
- Support `If-Match` and `If-Unmodified-Since` headers
- Use `res.getHeaderNames()` when available
- Use `res.headersSent` when available
- deps: debug@2.6.1
- deps: etag@~1.8.0
- deps: fresh@0.5.0
- deps: http-errors@~1.6.1
* deps: serve-static@1.12.0
- Fix false detection of `no-cache` request directive
- Fix incorrect result when `If-None-Match` has both `*` and ETags
- Fix weak `ETag` matching to match spec
- Remove usage of `res._headers` private field
- Send complete HTML document in redirect response
- Set default CSP header in redirect response
- Support `If-Match` and `If-Unmodified-Since` headers
- Use `res.getHeaderNames()` when available
- Use `res.headersSent` when available
- deps: send@0.15.0
* perf: add fast match path for `*` route
* perf: improve `req.ips` performance
4.14.1 / 2017-01-28
===================
* deps: content-disposition@0.5.2
* deps: finalhandler@0.5.1
- Fix exception when `err.headers` is not an object
- deps: statuses@~1.3.1
- perf: hoist regular expressions
- perf: remove duplicate validation path
* deps: proxy-addr@~1.1.3
- deps: ipaddr.js@1.2.0
* deps: send@0.14.2
- deps: http-errors@~1.5.1
- deps: ms@0.7.2
- deps: statuses@~1.3.1
* deps: serve-static@~1.11.2
- deps: send@0.14.2
* deps: type-is@~1.6.14
- deps: mime-types@~2.1.13
4.14.0 / 2016-06-16
===================
* Add `acceptRanges` option to `res.sendFile`/`res.sendfile`
* Add `cacheControl` option to `res.sendFile`/`res.sendfile`
* Add `options` argument to `req.range`
- Includes the `combine` option
* Encode URL in `res.location`/`res.redirect` if not already encoded
* Fix some redirect handling in `res.sendFile`/`res.sendfile`
* Fix Windows absolute path check using forward slashes
* Improve error with invalid arguments to `req.get()`
* Improve performance for `res.json`/`res.jsonp` in most cases
* Improve `Range` header handling in `res.sendFile`/`res.sendfile`
* deps: accepts@~1.3.3
- Fix including type extensions in parameters in `Accept` parsing
- Fix parsing `Accept` parameters with quoted equals
- Fix parsing `Accept` parameters with quoted semicolons
- Many performance improvments
- deps: mime-types@~2.1.11
- deps: negotiator@0.6.1
* deps: content-type@~1.0.2
- perf: enable strict mode
* deps: cookie@0.3.1
- Add `sameSite` option
- Fix cookie `Max-Age` to never be a floating point number
- Improve error message when `encode` is not a function
- Improve error message when `expires` is not a `Date`
- Throw better error for invalid argument to parse
- Throw on invalid values provided to `serialize`
- perf: enable strict mode
- perf: hoist regular expression
- perf: use for loop in parse
- perf: use string concatination for serialization
* deps: finalhandler@0.5.0
- Change invalid or non-numeric status code to 500
- Overwrite status message to match set status code
- Prefer `err.statusCode` if `err.status` is invalid
- Set response headers from `err.headers` object
- Use `statuses` instead of `http` module for status messages
* deps: proxy-addr@~1.1.2
- Fix accepting various invalid netmasks
- Fix IPv6-mapped IPv4 validation edge cases
- IPv4 netmasks must be contingous
- IPv6 addresses cannot be used as a netmask
- deps: ipaddr.js@1.1.1
* deps: qs@6.2.0
- Add `decoder` option in `parse` function
* deps: range-parser@~1.2.0
- Add `combine` option to combine overlapping ranges
- Fix incorrectly returning -1 when there is at least one valid range
- perf: remove internal function
* deps: send@0.14.1
- Add `acceptRanges` option
- Add `cacheControl` option
- Attempt to combine multiple ranges into single range
- Correctly inherit from `Stream` class
- Fix `Content-Range` header in 416 responses when using `start`/`end` options
- Fix `Content-Range` header missing from default 416 responses
- Fix redirect error when `path` contains raw non-URL characters
- Fix redirect when `path` starts with multiple forward slashes
- Ignore non-byte `Range` headers
- deps: http-errors@~1.5.0
- deps: range-parser@~1.2.0
- deps: statuses@~1.3.0
- perf: remove argument reassignment
* deps: serve-static@~1.11.1
- Add `acceptRanges` option
- Add `cacheControl` option
- Attempt to combine multiple ranges into single range
- Fix redirect error when `req.url` contains raw non-URL characters
- Ignore non-byte `Range` headers
- Use status code 301 for redirects
- deps: send@0.14.1
* deps: type-is@~1.6.13
- Fix type error when given invalid type to match against
- deps: mime-types@~2.1.11
* deps: vary@~1.1.0
- Only accept valid field names in the `field` argument
* perf: use strict equality when possible
4.13.4 / 2016-01-21
===================
* deps: content-disposition@0.5.1
- perf: enable strict mode
* deps: cookie@0.1.5
- Throw on invalid values provided to `serialize`
* deps: depd@~1.1.0
- Support web browser loading
- perf: enable strict mode
* deps: escape-html@~1.0.3
- perf: enable strict mode
- perf: optimize string replacement
- perf: use faster string coercion
* deps: finalhandler@0.4.1
- deps: escape-html@~1.0.3
* deps: merge-descriptors@1.0.1
- perf: enable strict mode
* deps: methods@~1.1.2
- perf: enable strict mode
* deps: parseurl@~1.3.1
- perf: enable strict mode
* deps: proxy-addr@~1.0.10
- deps: ipaddr.js@1.0.5
- perf: enable strict mode
* deps: range-parser@~1.0.3
- perf: enable strict mode
* deps: send@0.13.1
- deps: depd@~1.1.0
- deps: destroy@~1.0.4
- deps: escape-html@~1.0.3
- deps: range-parser@~1.0.3
* deps: serve-static@~1.10.2
- deps: escape-html@~1.0.3
- deps: parseurl@~1.3.0
- deps: send@0.13.1
4.13.3 / 2015-08-02
===================
* Fix infinite loop condition using `mergeParams: true`
* Fix inner numeric indices incorrectly altering parent `req.params`
4.13.2 / 2015-07-31
===================

125
Readme-Guide.md Normal file
View File

@@ -0,0 +1,125 @@
# README guidelines
Every module in the expressjs, pillarjs, and jshttp organizations should have
a README file named `README.md`. The purpose of the README is to:
- Explain the purpose of the module and how to use it.
- Act as a landing page (both on GitHub and npmjs.com) for the module to help
people find it via search. Middleware module READMEs are also incorporated
into https://expressjs.com/en/resources/middleware.html.
- Encourage community contributions and participation.
Use the [README template](https://github.com/expressjs/express/wiki/README-template)
to quickly create a new README file.
## Top-level items
**Badges** (optional): At the very top (with no subheading), include any
applicable badges, such as npm version/downloads, build status, test coverage,
and so on. Badges should resolve properly (not display a broken image).
Possible badges include:
- npm version: `[![NPM Version][npm-image]][npm-url]`
- npm downloads: `[![NPM Downloads][downloads-image]][downloads-url]`
- Build status: `[![Build Status][travis-image]][travis-url]`
- Test coverage: `[![Test Coverage][coveralls-image]][coveralls-url]`
- Tips: `[![Gratipay][gratipay-image]][gratipay-url]`
**Summary**: Following badges, provide a one- or two-sentence description of
what the module does. This should be the same as the npmjs.org blurb (which
comes from the description property of `package.json`). Since npm doesn't
handle markdown for the blurb, avoid using markdown in the summary sentence.
**TOC** (Optional): For longer READMEs, provide a table of contents that has
a relative link to each section. A tool such as
[doctoc](https://www.npmjs.com/package/doctoc) makes it very easy to generate
a TOC.
## Overview
Optionally, include a section of one or two paragraphs with more high-level
information on what the module does, what problems it solves, why one would
use it and how. Don't just repeat what's in the summary.
## Installation
Required. This section is typically just:
```sh
$ npm install module-name
```
But include any other steps or requirements.
NOTE: Use the `sh` code block to make the shell command display properly on
the website.
## Basic use
- Provide a general description of how to use the module with code sample.
Include any important caveats or restrictions.
- Explain the most common use cases.
- Optional: a simple "hello world" type example (where applicable). This
example is in addition to the more comprehensive [example section](#examples)
later.
## API
Provide complete API documentation.
Formatting conventions: Each function is listed in a 3rd-level heading (`###`),
like this:
```
### Function_name(arg, options [, optional_arg] ... )
```
**Options objects**
For arguments that are objects (for example, options object), describe the
properties in a table, as follows. This matches the formatting used in the
[Express API docs](https://expressjs.com/en/4x/api.html).
|Property | Description | Type | Default|
|----------|-----------|------------|-------------|
|Name of the property in `monospace`. | Brief description | String, Number, Boolean, etc. | If applicable.|
If all the properties are required (i.e. there are no defaults), then you
can omit the default column.
Instead of very lengthy descriptions, link out to subsequent paragraphs for
more detailed explanation of specific cases (e.g. "When this property is set
to 'foobar', xyz happens; see &lt;link to following section &gt;.)
If there are options properties that are themselves options, use additional
tables. See [`trust proxy` and `etag` properties](https://expressjs.com/en/4x/api.html#app.settings.table).
## Examples
Every README should have at least one example; ideally more. For code samples,
be sure to use the `js` code block, for proper display in the website, e.g.:
```js
var csurf = require('csurf')
...
```
## Tests
What tests are included.
How to run them.
The convention for running tests is `npm test`. All our projects should follow
this convention.
## Contributors
Names of module "owners" (lead developers) and other developers who have
contributed.
## License
Link to the license, with a short description of what it is, e.g. "MIT" or
whatever. Ideally, avoid putting the license text directly in the README; link
to it instead.

View File

@@ -21,10 +21,22 @@ app.listen(3000)
## Installation
This is a [Node.js](https://nodejs.org/en/) module available through the
[npm registry](https://www.npmjs.com/).
Before installing, [download and install Node.js](https://nodejs.org/en/download/).
Node.js 0.10 or higher is required.
Installation is done using the
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
```bash
$ npm install express
```
Follow [our installing guide](http://expressjs.com/en/starter/installing.html)
for more information.
## Features
* Robust routing
@@ -37,15 +49,18 @@ $ npm install express
## Docs & Community
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/strongloop/expressjs.com)]
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
* [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
* [Github Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/strongloop/express/wiki)
* [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/expressjs/express/wiki)
* [Google Group](https://groups.google.com/group/express-js) for discussion
* [Русскоязычная документация](http://jsman.ru/express/)
* [한국어 문서](http://expressjs.kr) - [[website repo](https://github.com/Hanul/expressjs.kr)]
* [Gitter](https://gitter.im/expressjs/express) for support and discussion
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/strongloop/express/wiki/New-features-in-4.x).
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x).
### Security Issues
If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
## Quick Start
@@ -90,7 +105,7 @@ $ npm start
To view the examples, clone the Express repo and install the dependencies:
```bash
$ git clone git://github.com/strongloop/express.git --depth 1
$ git clone git://github.com/expressjs/express.git --depth 1
$ cd express
$ npm install
```
@@ -112,11 +127,11 @@ $ npm test
## People
The original author of Express is [TJ Holowaychuk](https://github.com/tj) [![TJ's Gratipay][gratipay-image-visionmedia]][gratipay-url-visionmedia]
The original author of Express is [TJ Holowaychuk](https://github.com/tj)
The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) [![Doug's Gratipay][gratipay-image-dougwilson]][gratipay-url-dougwilson]
The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson)
[List of all contributors](https://github.com/strongloop/express/graphs/contributors)
[List of all contributors](https://github.com/expressjs/express/graphs/contributors)
## License
@@ -126,12 +141,12 @@ The current lead maintainer is [Douglas Christopher Wilson](https://github.com/d
[npm-url]: https://npmjs.org/package/express
[downloads-image]: https://img.shields.io/npm/dm/express.svg
[downloads-url]: https://npmjs.org/package/express
[travis-image]: https://img.shields.io/travis/strongloop/express/master.svg?label=linux
[travis-url]: https://travis-ci.org/strongloop/express
[travis-image]: https://img.shields.io/travis/expressjs/express/master.svg?label=linux
[travis-url]: https://travis-ci.org/expressjs/express
[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/express/master.svg?label=windows
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express
[coveralls-image]: https://img.shields.io/coveralls/strongloop/express/master.svg
[coveralls-url]: https://coveralls.io/r/strongloop/express?branch=master
[coveralls-image]: https://img.shields.io/coveralls/expressjs/express/master.svg
[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
[gratipay-image-visionmedia]: https://img.shields.io/gratipay/visionmedia.svg
[gratipay-url-visionmedia]: https://gratipay.com/visionmedia/
[gratipay-image-dougwilson]: https://img.shields.io/gratipay/dougwilson.svg

186
Release-Process.md Normal file
View File

@@ -0,0 +1,186 @@
# Express Release Process
This document contains the technical aspects of the Express release process. The
intended audience is those who have been authorized by the Express Technical
Committee (TC) to create, promote and sign official release builds for Express,
as npm packages hosted on https://npmjs.com/package/express.
## Who can make releases?
Release authorization is given by the Express TC. Once authorized, an individual
must have the following access permissions:
### 1. Github release access
The individual making the release will need to be a member of the
expressjs/express team with Write permission level so they are able to tag the
release commit and push changes to the expressjs/express repository
(see Steps 4 and 5).
### 2. npmjs.com release access
The individual making the release will need to be made an owner on the
`express` package on npmjs.com so they are able to publish the release
(see Step 6).
## How to publish a release
Before publishing, the following preconditions should be met:
- A release proposal issue or tracking pull request (see "Proposal branch"
below) will exist documenting:
- the proposed changes
- the type of release: patch, minor or major
- the version number (according to semantic versioning - http://semver.org)
- The proposed changes should be complete.
There are two main release flows: patch and non-patch.
The patch flow is for making **patch releases**. As per semantic versioning,
patch releases are for simple changes, eg: typo fixes, patch dependency updates,
and simple/low-risk bug fixes. Every other type of change is made via the
non-patch flow.
### Branch terminology
"Master branch"
- There is a branch in git used for the current major version of Express, named
`master`.
- This branch contains the completed commits for the next patch release of the
current major version.
- Releases for the current major version are published from this branch.
"Version branch"
- For any given major version of Express (current, previous or next) there is
a branch in git for that release named `<major-version>.x` (eg: `4.x`).
- This branch points to the commit of the latest tag for the given major version.
"Release branch"
- For any given major version of Express, there is a branch used for publishing
releases.
- For the current major version of Express, the release branch is the
"Master branch" named `master`.
- For all other major versions of Express, the release branch is the
"Version branch" named `<major-version>.x`.
"Proposal branch"
- A branch in git representing a proposed new release of Express. This can be a
minor or major release, named `<major-version>.0` for a major release,
`<major-version>.<minor-version>` for a minor release.
- A tracking pull request should exist to document the proposed release,
targeted at the appropriate release branch. Prior to opening the tracking
pull request the content of the release may have be discussed in an issue.
- This branch contains the commits accepted so far that implement the proposal
in the tracking pull request.
### Patch flow
In the patch flow, simple changes are committed to the release branch which
acts as an ever-present branch for the next patch release of the associated
major version of Express.
The release branch is usually kept in a state where it is ready to release.
Releases are made when sufficient time or change has been made to warrant it.
This is usually proposed and decided using a github issue.
### Non-patch flow
In the non-patch flow, changes are committed to a temporary proposal branch
created specifically for that release proposal. The branch is based on the
most recent release of the major version of Express that the release targets.
Releases are made when all the changes on a proposal branch are complete and
approved. This is done by merging the proposal branch into the release branch
(using a fast-forward merge), tagging it with the new version number and
publishing the release package to npmjs.com.
### Flow
Below is a detailed description of the steps to publish a release.
#### Step 1. Check the release is ready to publish
Check any relevant information to ensure the release is ready, eg: any
milestone, label, issue or tracking pull request for the release. The release
is ready when all proposed code, tests and documentation updates are complete
(either merged, closed or re-targeted to another release).
#### Step 2. (Non-patch flow only) Merge the proposal branch into the release branch
In the patch flow: skip this step.
In the non-patch flow:
```sh
$ git checkout <release-branch>
$ git merge --ff-only <proposal-branch>
```
<release-branch> - see "Release branch" of "Branches" above.
<proposal-branch> - see "Proposal branch" of "Non-patch flow" above.
**NOTE:** You may need to rebase the proposal branch to allow a fast-forward
merge. Using a fast-forward merge keeps the history clean as it does
not introduce merge commits.
### Step 3. Update the History.md and package.json to the new version number
The changes so far for the release should already be documented under the
"unreleased" section at the top of the History.md file, as per the usual
development practice. Change "unreleased" to the new release version / date.
Example diff fragment:
```diff
-unreleased
-==========
+4.13.3 / 2015-08-02
+===================
```
The version property in the package.json should already contain the version of
the previous release. Change it to the new release version.
Commit these changes together under a single commit with the message set to
the new release version (eg: `4.13.3`):
```sh
$ git checkout <release-branch>
<..edit files..>
$ git add History.md package.json
$ git commit -m '<version-number>'
```
### Step 4. Identify and tag the release commit with the new release version
Create a lightweight tag (rather than an annotated tag) named after the new
release version (eg: `4.13.3`).
```sh
$ git tag <version-number>
```
### Step 5. Push the release branch changes and tag to github
The branch and tag should be pushed directly to the main repository
(https://github.com/expressjs/express).
```sh
$ git push origin <release-branch>
$ git push origin <version-number>
```
### Step 6. Publish to npmjs.com
Ensure your local working copy is completely clean (no extra or changed files).
You can use `git status` for this purpose.
```sh
$ npm login <npm-username>
$ npm publish
```
**NOTE:** The version number to publish will be picked up automatically from
package.json.

43
Security.md Normal file
View File

@@ -0,0 +1,43 @@
# Security Policies and Procedures
This document outlines security procedures and general policies for the Express
project.
* [Reporting a Bug](#reporting-a-bug)
* [Disclosure Policy](#disclosure-policy)
* [Comments on this Policy](#comments-on-this-policy)
## Reporting a Bug
The Express team and community take all security bugs in Express seriously.
Thank you for improving the security of Express. We appreciate your efforts and
responsible disclosure and will make every effort to acknowledge your
contributions.
Report security bugs by emailing the lead maintainer in the Readme.md file.
The lead maintainer will acknowledge your email within 48 hours, and will send a
more detailed response within 48 hours indicating the next steps in handling
your report. After the initial reply to your report, the security team will
endeavor to keep you informed of the progress towards a fix and full
announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining
the module. You can also report a vulnerability through the
[Node Security Project](https://nodesecurity.io/report).
## Disclosure Policy
When the security team receives a security bug report, they will assign it to a
primary handler. This person will coordinate the fix and release process,
involving the following steps:
* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* Prepare fixes for all releases still under maintenance. These fixes will be
released as fast as possible to npm.
## Comments on this Policy
If you have suggestions on how this process could be improved please submit a
pull request.

View File

@@ -2,17 +2,59 @@ environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "1.0"
- nodejs_version: "1.8"
- nodejs_version: "2.0"
- nodejs_version: "2.3"
- nodejs_version: "2.5"
- nodejs_version: "3.3"
- nodejs_version: "4.9"
- nodejs_version: "5.12"
- nodejs_version: "6.14"
- nodejs_version: "7.10"
- nodejs_version: "8.12"
cache:
- node_modules
install:
- ps: Install-Product node $env:nodejs_version
- npm rm --save-dev connect-redis
# Install Node.js
- ps: >-
try { Install-Product node $env:nodejs_version -ErrorAction Stop }
catch { Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) }
# Configure npm
- ps: |
# Skip updating shrinkwrap / lock
npm config set shrinkwrap false
# Remove all non-test dependencies
- ps: |
# Remove example dependencies
npm rm --silent --save-dev connect-redis
# Setup Node.js version-specific dependencies
- ps: |
# mocha for testing
# - use 3.x for Node.js < 6
if ($env:nodejs_version.split(".")[0] -lt 6) {
npm install --silent --save-dev mocha@3.5.3
}
- ps: |
# supertest for http calls
# - use 2.0.0 for Node.js < 4
if ($env:nodejs_version.split(".")[0] -lt 4) {
npm install --silent --save-dev supertest@2.0.0
}
# Update Node.js modules
- ps: |
# Prune & rebuild node_modules
if (Test-Path -Path node_modules) {
npm prune
npm rebuild
}
# Install Node.js modules
- npm install
build: off
test_script:
- node --version
- npm --version
# Output version data
- ps: |
node --version
npm --version
# Run test script
- npm run test-ci
# Run linting
- npm run lint
version: "{build}"

View File

@@ -1,5 +1,4 @@
var http = require('http');
var express = require('..');
var app = express();
@@ -14,10 +13,8 @@ while (n--) {
});
}
var body = new Buffer('Hello World');
app.use(function(req, res, next){
res.send(body);
res.send('Hello World')
});
app.listen(3333);

View File

@@ -3,8 +3,8 @@
*/
var express = require('../..');
var hash = require('./pass').hash;
var bodyParser = require('body-parser');
var hash = require('pbkdf2-password')()
var path = require('path');
var session = require('express-session');
var app = module.exports = express();
@@ -12,11 +12,11 @@ var app = module.exports = express();
// config
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));
// middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: false }))
app.use(session({
resave: false, // don't save session if unmodified
saveUninitialized: false, // don't create session until something stored
@@ -45,7 +45,7 @@ var users = {
// when you create a user, generate a salt
// and hash the password ('foobar' is the pass here)
hash('foobar', function(err, salt, hash){
hash({ password: 'foobar' }, function (err, pass, salt, hash) {
if (err) throw err;
// store the salt & hash in the "db"
users.tj.salt = salt;
@@ -63,9 +63,9 @@ function authenticate(name, pass, fn) {
// apply the same algorithm to the POSTed password, applying
// the hash against the pass / salt, if there is a match we
// found the user
hash(pass, user.salt, function(err, hash){
hash({ password: pass, salt: user.salt }, function (err, pass, salt, hash) {
if (err) return fn(err);
if (hash == user.hash) return fn(null, user);
if (hash === user.hash) return fn(null, user)
fn(new Error('invalid password'));
});
}

View File

@@ -1,48 +0,0 @@
// check out https://github.com/tj/node-pwd
/**
* Module dependencies.
*/
var crypto = require('crypto');
/**
* Bytesize.
*/
var len = 128;
/**
* Iterations. ~300ms
*/
var iterations = 12000;
/**
* Hashes a password with optional `salt`, otherwise
* generate a salt for `pass` and invoke `fn(err, salt, hash)`.
*
* @param {String} password to hash
* @param {String} optional salt
* @param {Function} callback
* @api public
*/
exports.hash = function (pwd, salt, fn) {
if (3 == arguments.length) {
crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){
fn(err, hash.toString('base64'));
});
} else {
fn = salt;
crypto.randomBytes(len, function(err, salt){
if (err) return fn(err);
salt = salt.toString('base64');
crypto.pbkdf2(pwd, salt, iterations, len, function(err, hash){
if (err) return fn(err);
fn(null, salt, hash.toString('base64'));
});
});
}
};

View File

@@ -1,31 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../..');
var logger = require('morgan');
var app = express();
app.set('views', __dirname);
app.set('view engine', 'jade');
var pets = [];
var n = 1000;
while (n--) {
pets.push({ name: 'Tobi', age: 2, species: 'ferret' });
pets.push({ name: 'Loki', age: 1, species: 'ferret' });
pets.push({ name: 'Jane', age: 6, species: 'ferret' });
}
app.use(logger('dev'));
app.get('/', function(req, res){
res.render('pets', { pets: pets });
});
/* istanbul ignore next */
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}

View File

@@ -1,12 +0,0 @@
style.
body {
padding: 50px;
font: 16px "Helvetica Neue", Helvetica;
}
table
for pet in pets
tr
td= pet.name
td= pet.age
td= pet.species

View File

@@ -4,4 +4,4 @@ users.push({ name: 'Tobi' });
users.push({ name: 'Loki' });
users.push({ name: 'Jane' });
module.exports = users;
module.exports = users;

View File

@@ -15,9 +15,8 @@ app.use(count);
// custom middleware
function count(req, res) {
req.session.count = req.session.count || 0;
var n = req.session.count++;
res.send('viewed ' + n + ' times\n');
req.session.count = (req.session.count || 0) + 1
res.send('viewed ' + req.session.count + ' times\n')
}
/* istanbul ignore next */

View File

@@ -6,10 +6,9 @@ var express = require('../../');
var app = module.exports = express();
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
// custom log format
if ('test' != process.env.NODE_ENV) app.use(logger(':method :url'));
if (process.env.NODE_ENV !== 'test') app.use(logger(':method :url'))
// parses request cookies, populating
// req.cookies and req.signedCookies
@@ -18,7 +17,7 @@ if ('test' != process.env.NODE_ENV) app.use(logger(':method :url'));
app.use(cookieParser('my secret here'));
// parses x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: false }))
app.get('/', function(req, res){
if (req.cookies.remember) {

View File

@@ -3,6 +3,7 @@
*/
var express = require('../../');
var path = require('path');
var app = module.exports = express();
app.get('/', function(req, res){
@@ -16,10 +17,9 @@ app.get('/', function(req, res){
// /files/* is accessed via req.params[0]
// but here we name it :file
app.get('/files/:file(*)', function(req, res, next){
var file = req.params.file;
var path = __dirname + '/files/' + file;
var filePath = path.join(__dirname, 'files', req.params.file);
res.download(path, function(err){
res.download(filePath, function (err) {
if (!err) return; // file sent
if (err && err.status !== 404) return next(err); // non-404 error
// file for download not found

View File

@@ -3,6 +3,7 @@
*/
var express = require('../../');
var path = require('path');
var app = module.exports = express();
@@ -21,7 +22,11 @@ app.engine('.html', require('ejs').__express);
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));
// Path to our public directory
app.use(express.static(path.join(__dirname, 'public')));
// Without this you would need to
// supply the extension to res.render()

View File

@@ -2,12 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title> <%= title %> </title>
<style type="text/css">
body {
padding: 50px;
font: 13px Helvetica, Arial, sans-serif;
}
</style>
<title><%= title %></title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>

View File

@@ -3,12 +3,13 @@
*/
var express = require('../../');
var path = require('path');
var app = module.exports = express();
var logger = require('morgan');
var silent = 'test' == process.env.NODE_ENV;
var silent = process.env.NODE_ENV === 'test'
// general config
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// our custom "verbose errors" setting
@@ -18,7 +19,7 @@ app.enable('verbose errors');
// disable them in production
// use $ NODE_ENV=production node examples/error-pages
if ('production' == app.settings.env) app.disable('verbose errors');
if (app.settings.env === 'production') app.disable('verbose errors')
silent || app.use(logger('dev'));
@@ -60,20 +61,17 @@ app.get('/500', function(req, res, next){
app.use(function(req, res, next){
res.status(404);
// respond with html page
if (req.accepts('html')) {
res.render('404', { url: req.url });
return;
}
// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}
// default to plain-text. send()
res.type('txt').send('Not found');
res.format({
html: function () {
res.render('404', { url: req.url })
},
json: function () {
res.json({ error: 'Not found' })
},
default: function () {
res.type('txt').send('Not found')
}
})
});
// error-handling middleware, take the same form

View File

@@ -5,7 +5,7 @@
var express = require('../../');
var logger = require('morgan');
var app = module.exports = express();
var test = app.get('env') == 'test';
var test = app.get('env') === 'test'
if (!test) app.use(logger('dev'));
@@ -31,6 +31,9 @@ app.get('/', function(req, res){
app.get('/next', function(req, res, next){
// We can also pass exceptions to next()
// The reason for process.nextTick() is to show that
// next() can be called inside an async operation,
// in real life it can be a DB read or HTTP request.
process.nextTick(function(){
next(new Error('oh no!'));
});

View File

@@ -1,64 +0,0 @@
var express = require('../..');
var logger = require('morgan');
var app = express();
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
function User(name) {
this.private = 'heyyyy';
this.secret = 'something';
this.name = name;
this.id = 123;
}
// You'll probably want to do
// something like this so you
// dont expose "secret" data.
User.prototype.toJSON = function(){
return {
id: this.id,
name: this.name
};
};
app.use(logger('dev'));
// earlier on expose an object
// that we can tack properties on.
// all res.locals props are exposed
// to the templates, so "expose" will
// be present.
app.use(function(req, res, next){
res.locals.expose = {};
// you could alias this as req or res.expose
// to make it shorter and less annoying
next();
});
// pretend we loaded a user
app.use(function(req, res, next){
req.user = new User('Tobi');
next();
});
app.get('/', function(req, res){
res.redirect('/user');
});
app.get('/user', function(req, res){
// we only want to expose the user
// to the client for this route:
res.locals.expose.user = req.user;
res.render('page');
});
/* istanbul ignore next */
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}

View File

@@ -1,14 +0,0 @@
html
head
title Express
script.
// call this whatever you like,
// or dump them into individual
// props like "var user ="
var data = !{JSON.stringify(expose)}
body
h1 Expose client data
p The following was exposed to the client:
pre
script.
document.write(JSON.stringify(data, null, 2))

View File

@@ -1,51 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../../lib/express');
// Path to our public directory
var pub = __dirname + '/public';
// setup middleware
var app = express();
app.use(express.static(pub));
// Optional since express defaults to CWD/views
app.set('views', __dirname + '/views');
// Set our default template engine to "jade"
// which prevents the need for extensions
// (although you can still mix and match)
app.set('view engine', 'jade');
function User(name, email) {
this.name = name;
this.email = email;
}
// Dummy users
var users = [
new User('tj', 'tj@vision-media.ca')
, new User('ciaran', 'ciaranj@gmail.com')
, new User('aaron', 'aaron.heckmann+github@gmail.com')
];
app.get('/', function(req, res){
res.render('users', { users: users });
});
// change this to a better error handler in your code
// sending stacktrace to users in production is not good
app.use(function(err, req, res, next) {
res.send(err.stack);
});
/* istanbul ignore next */
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}

View File

@@ -1,3 +0,0 @@
head
title Jade Example
link(rel="stylesheet", href="/stylesheets/style.css")

View File

@@ -1,5 +0,0 @@
doctype html
html
include header
body
block content

View File

@@ -1,8 +0,0 @@
extends ../layout
block content
h1 Users
#users
for user in users
include user

View File

@@ -1,3 +0,0 @@
.user
h2= user.name
.email= user.email

View File

@@ -2,9 +2,11 @@
* Module dependencies.
*/
var escapeHtml = require('escape-html');
var express = require('../..');
var fs = require('fs');
var md = require('marked').parse;
var marked = require('marked');
var path = require('path');
var app = module.exports = express();
@@ -13,19 +15,14 @@ var app = module.exports = express();
app.engine('md', function(path, options, fn){
fs.readFile(path, 'utf8', function(err, str){
if (err) return fn(err);
try {
var html = md(str);
html = html.replace(/\{([^}]+)\}/g, function(_, name){
return options[name] || '';
});
fn(null, html);
} catch(err) {
fn(err);
}
var html = marked.parse(str).replace(/\{([^}]+)\}/g, function(_, name){
return escapeHtml(options[name] || '');
});
fn(null, html);
});
});
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));
// make it the default so we dont need .md
app.set('view engine', 'md');

View File

@@ -6,7 +6,7 @@ app.use('/api/v1', require('./controllers/api_v1'));
app.use('/api/v2', require('./controllers/api_v2'));
app.get('/', function(req, res) {
res.send('Hello form root route.');
res.send('Hello from root route.')
});
/* istanbul ignore next */

View File

@@ -1,3 +1,3 @@
exports.index = function(req, res){
res.redirect('/users');
};
};

View File

@@ -4,6 +4,8 @@
var db = require('../../db');
exports.engine = 'hbs';
exports.before = function(req, res, next){
var id = req.params.user_id;
if (!id) return next();

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/style.css">
<title>Edit {{user.name}}</title>
</head>
<body>
<h1>{{user.name}}</h1>
<form action="/user/{{user.id}}?_method=put" method="post">
<label for="user[name]">Name:
<input type="text" name="user[name]" value="{{user.name}}">
</label>
<input type="submit" name="submit" value="Update">
</form>
<form action="/user/{{user.id}}/pet" method="post">
<label for="pet[name]">Pet:
<input type="text" name="pet[name]" placeholder="Pet Name">
</label>
<input type="submit" name="submit" value="Add">
</form>
</body>
</html>

View File

@@ -1,11 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1= user.name
form(action='/user/#{user.id}?_method=put', method='post')
label= 'Name: '
input(type='text', name='user[name]', value='#{user.name}')
input(type='submit', value='Update')
form(action='/user/#{user.id}/pet', method='post')
label= 'Pet: '
input(type='text', name='pet[name]', placeholder='Name')
input(type='submit', value='Add')

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/style.css">
<title>Users</title>
</head>
<body>
<h1>Users</h1>
<p>Click a user below to view their pets.</p>
<ul>
{{#each users}}
<li><a href="/user/{{id}}">{{name}}</a></li>
{{/each}}
</ul>
</body>
</html>

View File

@@ -1,7 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1 Users
p Click a user below to view their pets.
ul
each user in users
li
a(href='/user/#{user.id}')= user.name

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/style.css">
<title>{{user.name}}</title>
</head>
<body>
<h1>{{user.name}} <a href="/user/{{user.id}}/edit">edit</a></h1>
{{#if hasMessages}}
<ul>
{{#each messages}}
<li>{{this}}</li>
{{/each}}
</ul>
{{/if}}
{{#if user.pets.length}}
<p>View {{user.name}}'s pets:</p>
<ul>
{{#each user.pets}}
<li><a href="/pet/{{id}}">{{name}}</a></li>
{{/each}}
</ul>
{{else}}
<p>No pets!</p>
{{/if}}
</body>
</html>

View File

@@ -1,17 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1= user.name + ' '
a(href='/user/#{user.id}/edit') edit
if (hasMessages)
ul#messages
each msg in messages
li= msg
if (user.pets.length)
p View #{user.name}'s pets:
ul
each pet in user.pets
li
a(href='/pet/#{pet.id}')= pet.name
else
p No pets!

View File

@@ -11,4 +11,4 @@ var users = exports.users = [];
users.push({ name: 'TJ', pets: [pets[0], pets[1], pets[2]], id: 0 });
users.push({ name: 'Guillermo', pets: [pets[3]], id: 1 });
users.push({ name: 'Nathan', pets: [], id: 2 });
users.push({ name: 'Nathan', pets: [], id: 2 });

View File

@@ -4,20 +4,18 @@
var express = require('../..');
var logger = require('morgan');
var path = require('path');
var session = require('express-session');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var app = module.exports = express();
// settings
// set our default template engine to "jade"
// which prevents the need for extensions
app.set('view engine', 'jade');
// set our default template engine to "ejs"
// which prevents the need for using file extensions
app.set('view engine', 'ejs');
// set views for error and 404 pages
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));
// define a custom res.message() method
// which stores messages in the session
@@ -34,7 +32,7 @@ app.response.message = function(msg){
if (!module.parent) app.use(logger('dev'));
// serve static files
app.use(express.static(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
// session support
app.use(session({
@@ -44,7 +42,7 @@ app.use(session({
}));
// parse request bodies (req.body)
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.urlencoded({ extended: true }))
// allow overriding methods in query (?_method=put)
app.use(methodOverride('_method'));

View File

@@ -4,22 +4,26 @@
var express = require('../../..');
var fs = require('fs');
var path = require('path');
module.exports = function(parent, options){
var dir = path.join(__dirname, '..', 'controllers');
var verbose = options.verbose;
fs.readdirSync(__dirname + '/../controllers').forEach(function(name){
fs.readdirSync(dir).forEach(function(name){
var file = path.join(dir, name)
if (!fs.statSync(file).isDirectory()) return;
verbose && console.log('\n %s:', name);
var obj = require('./../controllers/' + name);
var obj = require(file);
var name = obj.name || name;
var prefix = obj.prefix || '';
var app = express();
var handler;
var method;
var path;
var url;
// allow specifying the view engine
if (obj.engine) app.set('view engine', obj.engine);
app.set('views', __dirname + '/../controllers/' + name + '/views');
app.set('views', path.join(__dirname, '..', 'controllers', name, 'views'));
// generate routes based
// on the exported methods
@@ -30,27 +34,27 @@ module.exports = function(parent, options){
switch (key) {
case 'show':
method = 'get';
path = '/' + name + '/:' + name + '_id';
url = '/' + name + '/:' + name + '_id';
break;
case 'list':
method = 'get';
path = '/' + name + 's';
url = '/' + name + 's';
break;
case 'edit':
method = 'get';
path = '/' + name + '/:' + name + '_id/edit';
url = '/' + name + '/:' + name + '_id/edit';
break;
case 'update':
method = 'put';
path = '/' + name + '/:' + name + '_id';
url = '/' + name + '/:' + name + '_id';
break;
case 'create':
method = 'post';
path = '/' + name;
url = '/' + name;
break;
case 'index':
method = 'get';
path = '/';
url = '/';
break;
default:
/* istanbul ignore next */
@@ -59,15 +63,15 @@ module.exports = function(parent, options){
// setup
handler = obj[key];
path = prefix + path;
url = prefix + url;
// before middleware support
if (obj.before) {
app[method](path, obj.before, handler);
verbose && console.log(' %s %s -> before -> %s', method.toUpperCase(), path, key);
app[method](url, obj.before, handler);
verbose && console.log(' %s %s -> before -> %s', method.toUpperCase(), url, key);
} else {
app[method](path, handler);
verbose && console.log(' %s %s -> %s', method.toUpperCase(), path, key);
app[method](url, handler);
verbose && console.log(' %s %s -> %s', method.toUpperCase(), url, key);
}
}

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Not Found</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1>404: Not Found</h1>
<p>Sorry we can't find <%= url %></p>
</body>
</html>

View File

@@ -1,3 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1 404: Not Found
p Sorry we can't find #{url}

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Internal Server Error</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1>500: Internal Server Error</h1>
<p>Looks like something blew up!</p>
</body>
</html>

View File

@@ -1,3 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1 500: Internal Server Error
p Looks like something blew up!

View File

@@ -1,4 +1,8 @@
// first:
// install redis first:
// https://redis.io/
// then:
// $ npm install redis online
// $ redis-server

View File

@@ -68,7 +68,7 @@ app.get('/users/:from-:to', function(req, res, next){
var from = req.params.from;
var to = req.params.to;
var names = users.map(function(user){ return user.name; });
res.send('users ' + names.slice(from, to).join(', '));
res.send('users ' + names.slice(from, to + 1).join(', '));
});
/* istanbul ignore next */

View File

@@ -75,7 +75,7 @@ app.resource('/users', User);
app.get('/', function(req, res){
res.send([
'<h1>Examples:</h1> <ul>'
'<h1>Examples:</h1> <ul>'
, '<li>GET /users</li>'
, '<li>GET /users/1</li>'
, '<li>GET /users/3</li>'

View File

@@ -4,7 +4,7 @@
var express = require('../../lib/express');
var verbose = process.env.NODE_ENV != 'test';
var verbose = process.env.NODE_ENV !== 'test'
var app = module.exports = express();

View File

@@ -34,7 +34,7 @@ function loadUser(req, res, next) {
function andRestrictToSelf(req, res, next) {
// If our authenticated user is the user we are viewing
// then everything is fine :)
if (req.authenticatedUser.id == req.user.id) {
if (req.authenticatedUser.id === req.user.id) {
next();
} else {
// You may want to implement specific exceptions
@@ -47,7 +47,7 @@ function andRestrictToSelf(req, res, next) {
function andRestrictTo(role) {
return function(req, res, next) {
if (req.authenticatedUser.role == role) {
if (req.authenticatedUser.role === role) {
next();
} else {
next(new Error('Unauthorized'));

View File

@@ -3,10 +3,10 @@
*/
var express = require('../..');
var path = require('path');
var app = express();
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var site = require('./site');
var post = require('./post');
@@ -16,8 +16,8 @@ module.exports = app;
// Config
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
/* istanbul ignore next */
if (!module.parent) {
@@ -26,8 +26,8 @@ if (!module.parent) {
app.use(methodOverride('_method'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use(express.urlencoded({ extended: true }))
app.use(express.static(path.join(__dirname, 'public')));
// General

View File

@@ -1,3 +1,3 @@
exports.index = function(req, res){
res.render('index', { title: 'Route Separation Example' });
};
};

View File

@@ -0,0 +1,2 @@
</body>
</html>

View File

@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><%= title %></title>
<link rel="stylesheet" href="/style.css">
</head>
<body>

View File

@@ -0,0 +1,10 @@
<% include header %>
<h1><%= title %></h1>
<ul>
<li>Visit the <a href="/users">users</a> page.</li>
<li>Visit the <a href="/posts">posts</a> page.</li>
</ul>
<% include footer %>

View File

@@ -1,6 +0,0 @@
extends layout
block content
ul
li Visit the <a href="/users">users</a> page
li Visit the <a href="/posts">posts</a> page

View File

@@ -1,6 +0,0 @@
html
head
title= title
link(href="/style.css", rel="stylesheet")
body
block content

View File

@@ -0,0 +1,12 @@
<% include ../header %>
<h1>Posts</h1>
<dl id="posts">
<% posts.forEach(function(post) { %>
<dt><%= post.title %></dt>
<dd><%= post.body %></dd>
<% }) %>
</dl>
<% include ../footer %>

View File

@@ -1,8 +0,0 @@
extends ../layout
block content
h1 Posts
dl#posts
for post in posts
dt= post.title
dd= post.body

View File

@@ -0,0 +1,23 @@
<% include ../header %>
<h1>Editing <%= user.name %></h1>
<div id="user">
<form action="?_method=put", method="post">
<p>
Name:
<input type="text" value="<%= user.name %>" name="user[name]" />
</p>
<p>
Email:
<input type="email" value="<%= user.email %>" name="user[email]" />
</p>
<p>
<input type="submit" value="Save" />
</p>
</form>
</div>
<% include ../footer %>

View File

@@ -1,12 +0,0 @@
extends ../layout
block content
h1 Editing #{user.name}
#user
form(action="?_method=put", method="post")
p Name:
input(type="text", value= user.name, name="user[name]")
p Email:
input(type="text", value= user.email, name="user[email]")
p
input(type="submit", value="Save")

View File

@@ -0,0 +1,14 @@
<% include ../header %>
<h1><%= title %></h1>
<div id="users">
<% users.forEach(function(user, index) { %>
<li>
<a href="/user/<%= index %>"><%= user.name %></a>
<a href="/user/<%= index %>/edit">edit</a>
</li>
<% }) %>
</div>
<% include ../footer %>

View File

@@ -1,9 +0,0 @@
extends ../layout
block content
h1 Users
#users
for user, i in users
li
a(href="/user/#{i}")= user.name
a.edit(href="/user/#{i}/edit") edit

View File

@@ -0,0 +1,9 @@
<% include ../header %>
<h1><%= user.name %></h1>
<div id="user">
<p>Email: <%= user.email %></p>
</div>
<% include ../footer %>

View File

@@ -1,6 +0,0 @@
extends ../layout
block content
h1= user.name
#user
p Email: #{user.email}

View File

@@ -1,4 +1,8 @@
// first:
// install redis first:
// https://redis.io/
// then:
// $ npm install redis
// $ redis-server
@@ -7,6 +11,7 @@
*/
var express = require('../..');
var path = require('path');
var redis = require('redis');
var db = redis.createClient();
@@ -15,8 +20,7 @@ var db = redis.createClient();
var app = express();
app.set('view engine', 'jade');
app.set('views', __dirname);
app.use(express.static(path.join(__dirname, 'public')));
// populate search
@@ -26,14 +30,6 @@ db.sadd('ferret', 'jane');
db.sadd('cat', 'manny');
db.sadd('cat', 'luna');
/**
* GET the search page.
*/
app.get('/', function(req, res){
res.render('search');
});
/**
* GET search for :query.
*/
@@ -54,7 +50,7 @@ app.get('/search/:query?', function(req, res){
*/
app.get('/client.js', function(req, res){
res.sendFile(__dirname + '/client.js');
res.sendFile(path.join(__dirname, 'client.js'));
});
/* istanbul ignore next */

View File

@@ -5,9 +5,9 @@ search.addEventListener('keyup', function(){
var xhr = new XMLHttpRequest;
xhr.open('GET', '/search/' + search.value, true);
xhr.onreadystatechange = function(){
if (4 == xhr.readyState) {
if (xhr.readyState === 4) {
code.textContent = xhr.responseText;
}
};
xhr.send();
}, false);
}, false);

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Search example</title>
<style type="text/css">
body {
font: 14px "Helvetica Neue", Helvetica;
padding: 50px;
}
</style>
</head>
<body>
<h2>Search</h2>
<p>Try searching for "ferret" or "cat".</p>
<input type="search" name="search" value="" />
<pre />
<script src="/client.js" charset="utf-8"></script>
</body>
</html>

View File

@@ -1,15 +0,0 @@
doctype
html
head
title Search example
style.
body {
font: 14px "Helvetica Neue", Helvetica;
padding: 50px;
}
body
h2 Search
p Try searching for "ferret" or "cat".
input(type='search')
pre
script(src='client.js')

View File

@@ -1,4 +1,8 @@
// first:
// install redis first:
// https://redis.io/
// then:
// $ npm install redis
// $ redis-server

View File

@@ -4,6 +4,7 @@
var express = require('../..');
var logger = require('morgan');
var path = require('path');
var app = express();
// log requests
@@ -16,7 +17,7 @@ app.use(logger('dev'));
// that you pass it. In this case "GET /js/app.js"
// will look for "./public/js/app.js".
app.use(express.static(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
// if you wanted to "prefix" you may use
// the mounting feature of Connect, for example
@@ -24,13 +25,13 @@ app.use(express.static(__dirname + '/public'));
// The mount-path "/static" is simply removed before
// passing control to the express.static() middleware,
// thus it serves the file correctly by ignoring "/static"
app.use('/static', express.static(__dirname + '/public'));
app.use('/static', express.static(path.join(__dirname, 'public')));
// if for some reason you want to serve files from
// several directories, you can use express.static()
// multiple times! Here we're passing "./public/css",
// this will allow "GET /style.css" instead of "GET /css/style.css":
app.use(express.static(__dirname + '/public/css'));
app.use(express.static(path.join(__dirname, 'public', 'css')));
app.listen(3000);
console.log('listening on port 3000');

View File

@@ -1 +1 @@
foo
foo

View File

@@ -2,7 +2,7 @@
* Module dependencies.
*/
var http = require('http');
var https = require('https');
var path = require('path');
var extname = path.extname;

View File

@@ -3,7 +3,6 @@
*/
var express = require('../../');
var http = require('http');
var GithubView = require('./github-view');
var md = require('marked').parse;
@@ -23,7 +22,7 @@ app.engine('md', function(str, options, fn){
});
// pointing to a particular github repo to load files from it
app.set('views', 'strongloop/express');
app.set('views', 'expressjs/express');
// register a new view constructor
app.set('view', GithubView);
@@ -36,7 +35,7 @@ app.get('/', function(req, res){
});
app.get('/Readme.md', function(req, res){
// rendering a view from https://github.com/strongloop/express/blob/master/Readme.md
// rendering a view from https://github.com/expressjs/express/blob/master/Readme.md
res.render('Readme.md');
});

View File

@@ -3,16 +3,17 @@
*/
var express = require('../..');
var path = require('path');
var User = require('./user');
var app = express();
app.set('views', __dirname);
app.set('view engine', 'jade');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// filter ferrets only
function ferrets(user) {
return user.species == 'ferret';
return user.species === 'ferret'
}
// naive nesting approach,
@@ -25,7 +26,7 @@ app.get('/', function(req, res, next){
if (err) return next(err);
User.all(function(err, users){
if (err) return next(err);
res.render('user', {
res.render('index', {
title: 'Users',
count: count,
users: users.filter(ferrets)
@@ -59,7 +60,7 @@ function users(req, res, next) {
}
app.get('/middleware', count, users, function(req, res, next){
res.render('user', {
res.render('index', {
title: 'Users',
count: req.count,
users: req.users.filter(ferrets)
@@ -101,7 +102,7 @@ app.get('/middleware-locals', count2, users2, function(req, res, next){
// to pass to res.render(). If we have
// several routes related to users this
// can be a great productivity booster
res.render('user', { title: 'Users' });
res.render('index', { title: 'Users' });
});
// keep in mind that middleware may be placed anywhere

View File

@@ -1,12 +0,0 @@
doctype html
html
head
title= title
style.
body {
padding: 50px;
font: 16px Helvetica, Arial;
}
body
h2= title
block content

View File

@@ -1,8 +0,0 @@
extends layout
block content
for user in users
.user
h3= user.name
p #{user.name} is a #{user.age} year old #{user.species}.

View File

@@ -9,6 +9,9 @@ function User(name, age, species) {
}
User.all = function(fn){
// process.nextTick makes sure this function API
// behaves in an asynchronous manner, like if it
// was a real DB query to read all users.
process.nextTick(function(){
fn(null, users);
});

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= title %></title>
<style media="screen">
body {
padding: 50px;
font: 16px Helvetica, Arial;
}
</style>
</head>
<body>
<h2><%= title %></h2>
<% users.forEach(function(user) { %>
<li><strong><%= user.name %></strong> is a <% user.age %> year old <%= user.species %></li>
<% }); %>
</body>
</html>

View File

@@ -49,9 +49,9 @@ var apiKeys = ['foo', 'bar', 'baz'];
// these two objects will serve as our faux database
var repos = [
{ name: 'express', url: 'http://github.com/strongloop/express' }
, { name: 'stylus', url: 'http://github.com/learnboost/stylus' }
, { name: 'cluster', url: 'http://github.com/learnboost/cluster' }
{ name: 'express', url: 'https://github.com/expressjs/express' },
{ name: 'stylus', url: 'https://github.com/learnboost/stylus' },
{ name: 'cluster', url: 'https://github.com/learnboost/cluster' }
];
var users = [
@@ -61,7 +61,7 @@ var users = [
];
var userRepos = {
tobi: [repos[0], repos[1]]
tobi: [repos[0], repos[1]]
, loki: [repos[1]]
, jane: [repos[2]]
};
@@ -69,14 +69,17 @@ var userRepos = {
// we now can assume the api key is valid,
// and simply expose the data
// example: http://localhost:3000/api/users/?api-key=foo
app.get('/api/users', function(req, res, next){
res.send(users);
});
// example: http://localhost:3000/api/repos/?api-key=foo
app.get('/api/repos', function(req, res, next){
res.send(repos);
});
// example: http://localhost:3000/api/user/tobi/repos/?api-key=foo
app.get('/api/user/:name/repos', function(req, res, next){
var name = req.params.name;
var user = userRepos[name];

View File

@@ -28,6 +28,7 @@ var deprecate = require('depd')('express');
var flatten = require('array-flatten');
var merge = require('utils-merge');
var resolve = require('path').resolve;
var setPrototypeOf = require('setprototypeof')
var slice = Array.prototype.slice;
/**
@@ -94,10 +95,10 @@ app.defaultConfiguration = function defaultConfiguration() {
}
// inherit protos
this.request.__proto__ = parent.request;
this.response.__proto__ = parent.response;
this.engines.__proto__ = parent.engines;
this.settings.__proto__ = parent.settings;
setPrototypeOf(this.request, parent.request)
setPrototypeOf(this.response, parent.response)
setPrototypeOf(this.engines, parent.engines)
setPrototypeOf(this.settings, parent.settings)
});
// setup locals
@@ -206,7 +207,7 @@ app.use = function use(fn) {
var fns = flatten(slice.call(arguments, offset));
if (fns.length === 0) {
throw new TypeError('app.use() requires middleware functions');
throw new TypeError('app.use() requires a middleware function')
}
// setup router
@@ -227,8 +228,8 @@ app.use = function use(fn) {
router.use(path, function mounted_app(req, res, next) {
var orig = req.app;
fn.handle(req, res, function (err) {
req.__proto__ = orig.request;
res.__proto__ = orig.response;
setPrototypeOf(req, orig.request)
setPrototypeOf(res, orig.response)
next(err);
});
});
@@ -261,9 +262,9 @@ app.route = function route(path) {
*
* By default will `require()` the engine based on the
* file extension. For example if you try to render
* a "foo.jade" file Express will invoke the following internally:
* a "foo.ejs" file Express will invoke the following internally:
*
* app.engine('jade', require('jade').__express);
* app.engine('ejs', require('ejs').__express);
*
* For engines that do not provide `.__express` out of the box,
* or if you wish to "map" a different extension to the template engine
@@ -337,7 +338,7 @@ app.param = function param(name, fn) {
* Assign `setting` to `val`, or return `setting`'s value.
*
* app.set('foo', 'bar');
* app.get('foo');
* app.set('foo');
* // => "bar"
*
* Mounted servers inherit their parent server's settings.
@@ -522,7 +523,7 @@ app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead');
* })
*
* @param {String} name
* @param {String|Function} options or fn
* @param {Object|Function} options or fn
* @param {Function} callback
* @public
*/

View File

@@ -12,6 +12,7 @@
* Module dependencies.
*/
var bodyParser = require('body-parser')
var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');
var proto = require('./application');
@@ -41,8 +42,16 @@ function createApplication() {
mixin(app, EventEmitter.prototype, false);
mixin(app, proto, false);
app.request = { __proto__: req, app: app };
app.response = { __proto__: res, app: app };
// expose the prototype that will get set on requests
app.request = Object.create(req, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
// expose the prototype that will get set on responses
app.response = Object.create(res, {
app: { configurable: true, enumerable: true, writable: true, value: app }
})
app.init();
return app;
}
@@ -66,16 +75,16 @@ exports.Router = Router;
* Expose middleware
*/
exports.json = bodyParser.json
exports.query = require('./middleware/query');
exports.static = require('serve-static');
exports.urlencoded = bodyParser.urlencoded
/**
* Replace removed middleware with an appropriate error message.
*/
[
'json',
'urlencoded',
var removedMiddlewares = [
'bodyParser',
'compress',
'cookieSession',
@@ -92,8 +101,10 @@ exports.static = require('serve-static');
'directory',
'limit',
'multipart',
'staticCache',
].forEach(function (name) {
'staticCache'
]
removedMiddlewares.forEach(function (name) {
Object.defineProperty(exports, name, {
get: function () {
throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');

View File

@@ -8,6 +8,13 @@
'use strict';
/**
* Module dependencies.
* @private
*/
var setPrototypeOf = require('setprototypeof')
/**
* Initialization middleware, exposing the
* request and response to each other, as well
@@ -25,8 +32,8 @@ exports.init = function(app){
res.req = req;
req.next = next;
req.__proto__ = app.request;
res.__proto__ = app.response;
setPrototypeOf(req, app.request)
setPrototypeOf(res, app.response)
res.locals = res.locals || Object.create(null);

View File

@@ -12,6 +12,7 @@
* Module dependencies.
*/
var merge = require('utils-merge')
var parseUrl = require('parseurl');
var qs = require('qs');
@@ -22,7 +23,7 @@ var qs = require('qs');
*/
module.exports = function query(options) {
var opts = Object.create(options || null);
var opts = merge({}, options)
var queryparse = qs.parse;
if (typeof options === 'function') {
@@ -30,14 +31,9 @@ module.exports = function query(options) {
opts = undefined;
}
if (opts !== undefined) {
if (opts.allowDots === undefined) {
opts.allowDots = false;
}
if (opts.allowPrototypes === undefined) {
opts.allowPrototypes = true;
}
if (opts !== undefined && opts.allowPrototypes === undefined) {
// back-compat for qs module
opts.allowPrototypes = true;
}
return function query(req, res, next){

View File

@@ -25,11 +25,17 @@ var proxyaddr = require('proxy-addr');
/**
* Request prototype.
* @public
*/
var req = exports = module.exports = {
__proto__: http.IncomingMessage.prototype
};
var req = Object.create(http.IncomingMessage.prototype)
/**
* Module exports.
* @public
*/
module.exports = req
/**
* Return request header.
@@ -57,6 +63,14 @@ var req = exports = module.exports = {
req.get =
req.header = function header(name) {
if (!name) {
throw new TypeError('name argument is required to req.get');
}
if (typeof name !== 'string') {
throw new TypeError('name must be a string to req.get');
}
var lc = name.toLowerCase();
switch (lc) {
@@ -171,29 +185,34 @@ req.acceptsLanguage = deprecate.function(req.acceptsLanguages,
'req.acceptsLanguage: Use acceptsLanguages instead');
/**
* Parse Range header field,
* capping to the given `size`.
* Parse Range header field, capping to the given `size`.
*
* Unspecified ranges such as "0-" require
* knowledge of your resource length. In
* the case of a byte range this is of course
* the total number of bytes. If the Range
* header field is not given `null` is returned,
* `-1` when unsatisfiable, `-2` when syntactically invalid.
* Unspecified ranges such as "0-" require knowledge of your resource length. In
* the case of a byte range this is of course the total number of bytes. If the
* Range header field is not given `undefined` is returned, `-1` when unsatisfiable,
* and `-2` when syntactically invalid.
*
* NOTE: remember that ranges are inclusive, so
* for example "Range: users=0-3" should respond
* with 4 users when available, not 3.
* When ranges are returned, the array has a "type" property which is the type of
* range that is required (most commonly, "bytes"). Each array element is an object
* with a "start" and "end" property for the portion of the range.
*
* @param {Number} size
* @return {Array}
* The "combine" option can be set to `true` and overlapping & adjacent ranges
* will be combined into a single range.
*
* NOTE: remember that ranges are inclusive, so for example "Range: users=0-3"
* should respond with 4 users when available, not 3.
*
* @param {number} size
* @param {object} [options]
* @param {boolean} [options.combine=false]
* @return {number|array}
* @public
*/
req.range = function(size){
req.range = function range(size, options) {
var range = this.get('Range');
if (!range) return;
return parseRange(size, range);
return parseRange(size, range, options);
};
/**
@@ -296,14 +315,18 @@ defineGetter(req, 'protocol', function protocol(){
// Note: X-Forwarded-Proto is normally only ever a
// single value, but this is to be safe.
proto = this.get('X-Forwarded-Proto') || proto;
return proto.split(/\s*,\s*/)[0];
var header = this.get('X-Forwarded-Proto') || proto
var index = header.indexOf(',')
return index !== -1
? header.substring(0, index).trim()
: header.trim()
});
/**
* Short-hand for:
*
* req.protocol == 'https'
* req.protocol === 'https'
*
* @return {Boolean}
* @public
@@ -343,7 +366,12 @@ defineGetter(req, 'ip', function ip(){
defineGetter(req, 'ips', function ips() {
var trust = this.app.get('trust proxy fn');
var addrs = proxyaddr.all(this, trust);
return addrs.slice(1).reverse();
// reverse the order (to farthest -> closest)
// and remove socket address
addrs.reverse().pop()
return addrs
});
/**
@@ -434,14 +462,18 @@ defineGetter(req, 'host', deprecate.function(function host(){
defineGetter(req, 'fresh', function(){
var method = this.method;
var s = this.res.statusCode;
var res = this.res
var status = res.statusCode
// GET or HEAD for weak freshness validation only
if ('GET' != method && 'HEAD' != method) return false;
if ('GET' !== method && 'HEAD' !== method) return false;
// 2xx or 304 as per rfc2616 14.26
if ((s >= 200 && s < 300) || 304 == s) {
return fresh(this.headers, (this.res._headers || {}));
if ((status >= 200 && status < 300) || 304 === status) {
return fresh(this.headers, {
'etag': res.get('ETag'),
'last-modified': res.get('Last-Modified')
})
}
return false;
@@ -486,4 +518,4 @@ function defineGetter(obj, name, getter) {
enumerable: true,
get: getter
});
};
}

View File

@@ -12,19 +12,21 @@
* @private
*/
var Buffer = require('safe-buffer').Buffer
var contentDisposition = require('content-disposition');
var deprecate = require('depd')('express');
var encodeUrl = require('encodeurl');
var escapeHtml = require('escape-html');
var http = require('http');
var isAbsolute = require('./utils').isAbsolute;
var onFinished = require('on-finished');
var path = require('path');
var statuses = require('statuses')
var merge = require('utils-merge');
var sign = require('cookie-signature').sign;
var normalizeType = require('./utils').normalizeType;
var normalizeTypes = require('./utils').normalizeTypes;
var setCharset = require('./utils').setCharset;
var statusCodes = http.STATUS_CODES;
var cookie = require('cookie');
var send = require('send');
var extname = path.extname;
@@ -34,11 +36,17 @@ var vary = require('vary');
/**
* Response prototype.
* @public
*/
var res = module.exports = {
__proto__: http.ServerResponse.prototype
};
var res = Object.create(http.ServerResponse.prototype)
/**
* Module exports.
* @public
*/
module.exports = res
/**
* Module variables.
@@ -88,7 +96,7 @@ res.links = function(links){
*
* Examples:
*
* res.send(new Buffer('wahoo'));
* res.send(Buffer.from('wahoo'));
* res.send({ some: 'json' });
* res.send('<p>some html</p>');
*
@@ -99,7 +107,6 @@ res.links = function(links){
res.send = function send(body) {
var chunk = body;
var encoding;
var len;
var req = this.req;
var type;
@@ -128,7 +135,7 @@ res.send = function send(body) {
deprecate('res.send(status): Use res.sendStatus(status) instead');
this.statusCode = chunk;
chunk = statusCodes[chunk];
chunk = statuses[chunk]
}
switch (typeof chunk) {
@@ -164,23 +171,33 @@ res.send = function send(body) {
}
}
// determine if ETag should be generated
var etagFn = app.get('etag fn')
var generateETag = !this.get('ETag') && typeof etagFn === 'function'
// populate Content-Length
var len
if (chunk !== undefined) {
if (!Buffer.isBuffer(chunk)) {
// convert chunk to Buffer; saves later double conversions
chunk = new Buffer(chunk, encoding);
if (Buffer.isBuffer(chunk)) {
// get length of Buffer
len = chunk.length
} else if (!generateETag && chunk.length < 1000) {
// just calculate length when no ETag + small chunk
len = Buffer.byteLength(chunk, encoding)
} else {
// convert chunk to Buffer and calculate
chunk = Buffer.from(chunk, encoding)
encoding = undefined;
len = chunk.length
}
len = chunk.length;
this.set('Content-Length', len);
}
// populate ETag
var etag;
var generateETag = len !== undefined && app.get('etag fn');
if (typeof generateETag === 'function' && !this.get('ETag')) {
if ((etag = generateETag(chunk, encoding))) {
if (generateETag && len !== undefined) {
if ((etag = etagFn(chunk, encoding))) {
this.set('ETag', etag);
}
}
@@ -189,7 +206,7 @@ res.send = function send(body) {
if (req.fresh) this.statusCode = 304;
// strip irrelevant headers
if (204 == this.statusCode || 304 == this.statusCode) {
if (204 === this.statusCode || 304 === this.statusCode) {
this.removeHeader('Content-Type');
this.removeHeader('Content-Length');
this.removeHeader('Transfer-Encoding');
@@ -237,9 +254,10 @@ res.json = function json(obj) {
// settings
var app = this.app;
var escape = app.get('json escape')
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(val, replacer, spaces);
var body = stringify(val, replacer, spaces, escape)
// content-type
if (!this.get('Content-Type')) {
@@ -279,9 +297,10 @@ res.jsonp = function jsonp(obj) {
// settings
var app = this.app;
var escape = app.get('json escape')
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
var body = JSON.stringify(val, replacer, spaces);
var body = stringify(val, replacer, spaces, escape)
var callback = this.req.query[app.get('jsonp callback name')];
// content-type
@@ -297,7 +316,6 @@ res.jsonp = function jsonp(obj) {
// jsonp
if (typeof callback === 'string' && callback.length !== 0) {
this.charset = 'utf-8';
this.set('X-Content-Type-Options', 'nosniff');
this.set('Content-Type', 'text/javascript');
@@ -333,7 +351,7 @@ res.jsonp = function jsonp(obj) {
*/
res.sendStatus = function sendStatus(statusCode) {
var body = statusCodes[statusCode] || String(statusCode);
var body = statuses[statusCode] || String(statusCode)
this.statusCode = statusCode;
this.type('txt');
@@ -482,7 +500,7 @@ res.sendfile = function (path, options, callback) {
if (err && err.code === 'EISDIR') return next();
// next() all but write errors
if (err && err.code !== 'ECONNABORT' && err.syscall !== 'write') {
if (err && err.code !== 'ECONNABORTED' && err.syscall !== 'write') {
next(err);
}
});
@@ -499,19 +517,29 @@ res.sendfile = deprecate.function(res.sendfile,
* when the data transfer is complete, or when an error has
* ocurred. Be sure to check `res.headersSent` if you plan to respond.
*
* This method uses `res.sendfile()`.
* Optionally providing an `options` object to use with `res.sendFile()`.
* This function will set the `Content-Disposition` header, overriding
* any `Content-Disposition` header passed as header options in order
* to set the attachment and filename.
*
* This method uses `res.sendFile()`.
*
* @public
*/
res.download = function download(path, filename, callback) {
res.download = function download (path, filename, options, callback) {
var done = callback;
var name = filename;
var opts = options || null
// support function as second arg
// support function as second or third arg
if (typeof filename === 'function') {
done = filename;
name = null;
opts = null
} else if (typeof options === 'function') {
done = options
opts = null
}
// set Content-Disposition when file is sent
@@ -519,10 +547,26 @@ res.download = function download(path, filename, callback) {
'Content-Disposition': contentDisposition(name || path)
};
// merge user-provided headers
if (opts && opts.headers) {
var keys = Object.keys(opts.headers)
for (var i = 0; i < keys.length; i++) {
var key = keys[i]
if (key.toLowerCase() !== 'content-disposition') {
headers[key] = opts.headers[key]
}
}
}
// merge user-provided options
opts = Object.create(opts)
opts.headers = headers
// Resolve the full path for sendFile
var fullPath = resolve(path);
return this.sendFile(fullPath, { headers: headers }, done);
// send file
return this.sendFile(fullPath, opts, done)
};
/**
@@ -710,9 +754,14 @@ res.header = function header(field, val) {
: String(val);
// add charset to content-type
if (field.toLowerCase() === 'content-type' && !charsetRegExp.test(value)) {
var charset = mime.charsets.lookup(value.split(';')[0]);
if (charset) value += '; charset=' + charset.toLowerCase();
if (field.toLowerCase() === 'content-type') {
if (Array.isArray(value)) {
throw new TypeError('Content-Type cannot be set to an Array');
}
if (!charsetRegExp.test(value)) {
var charset = mime.charsets.lookup(value.split(';')[0]);
if (charset) value += '; charset=' + charset.toLowerCase();
}
}
this.setHeader(field, value);
@@ -740,7 +789,7 @@ res.get = function(field){
* Clear cookie `name`.
*
* @param {String} name
* @param {Object} options
* @param {Object} [options]
* @return {ServerResponse} for chaining
* @public
*/
@@ -770,7 +819,7 @@ res.clearCookie = function clearCookie(name, options) {
*
* @param {String} name
* @param {String|Object} value
* @param {Options} options
* @param {Object} [options]
* @return {ServerResponse} for chaining
* @public
*/
@@ -832,8 +881,7 @@ res.location = function location(url) {
}
// set location
this.set('Location', loc);
return this;
return this.set('Location', encodeUrl(loc));
};
/**
@@ -871,18 +919,17 @@ res.redirect = function redirect(url) {
}
// Set location header
this.location(address);
address = this.get('Location');
address = this.location(address).get('Location');
// Support text/{plain,html} by default
this.format({
text: function(){
body = statusCodes[status] + '. Redirecting to ' + encodeURI(address);
body = statuses[status] + '. Redirecting to ' + address
},
html: function(){
var u = escapeHtml(address);
body = '<p>' + statusCodes[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>';
body = '<p>' + statuses[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>'
},
default: function(){
@@ -1051,3 +1098,40 @@ function sendfile(res, file, options, callback) {
// pipe
file.pipe(res);
}
/**
* Stringify JSON, like JSON.stringify, but v8 optimized, with the
* ability to escape characters that can trigger HTML sniffing.
*
* @param {*} value
* @param {function} replaces
* @param {number} spaces
* @param {boolean} escape
* @returns {string}
* @private
*/
function stringify (value, replacer, spaces, escape) {
// v8 checks arguments.length for optimizing simple call
// https://bugs.chromium.org/p/v8/issues/detail?id=4730
var json = replacer || spaces
? JSON.stringify(value, replacer, spaces)
: JSON.stringify(value);
if (escape) {
json = json.replace(/[<>&]/g, function (c) {
switch (c.charCodeAt(0)) {
case 0x3c:
return '\\u003c'
case 0x3e:
return '\\u003e'
case 0x26:
return '\\u0026'
default:
return c
}
})
}
return json
}

View File

@@ -21,6 +21,7 @@ var debug = require('debug')('express:router');
var deprecate = require('depd')('express');
var flatten = require('array-flatten');
var parseUrl = require('parseurl');
var setPrototypeOf = require('setprototypeof')
/**
* Module variables.
@@ -34,7 +35,7 @@ var toString = Object.prototype.toString;
/**
* Initialize a new `Router` with the given `options`.
*
* @param {Object} options
* @param {Object} [options]
* @return {Router} which is an callable function
* @public
*/
@@ -47,7 +48,7 @@ var proto = module.exports = function(options) {
}
// mixin Router class functions
router.__proto__ = proto;
setPrototypeOf(router, proto)
router.params = {};
router._params = [];
@@ -119,7 +120,7 @@ proto.param = function param(name, fn) {
// ensure we end up with a
// middleware function
if ('function' != typeof fn) {
if ('function' !== typeof fn) {
throw new Error('invalid param() call for ' + name + ', got ' + fn);
}
@@ -137,11 +138,8 @@ proto.handle = function handle(req, res, out) {
debug('dispatching %s %s', req.method, req.url);
var search = 1 + req.url.indexOf('?');
var pathlength = search ? search - 1 : req.url.length;
var fqdn = req.url[0] !== '/' && 1 + req.url.substr(0, pathlength).indexOf('://');
var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : '';
var idx = 0;
var protohost = getProtohost(req.url) || ''
var removed = '';
var slashAdded = false;
var paramcalled = {};
@@ -193,6 +191,12 @@ proto.handle = function handle(req, res, out) {
removed = '';
}
// signal to exit router
if (layerError === 'router') {
setImmediate(done, null)
return
}
// no more matching layers
if (idx >= stack.length) {
setImmediate(done, layerError);
@@ -282,18 +286,19 @@ proto.handle = function handle(req, res, out) {
}
function trim_prefix(layer, layerError, layerPath, path) {
var c = path[layerPath.length];
if (c && '/' !== c && '.' !== c) return next(layerError);
// Trim off the part of the url that matches the route
// middleware (.use stuff) needs to have the path stripped
if (layerPath.length !== 0) {
// Validate path breaks on a path separator
var c = path[layerPath.length]
if (c && c !== '/' && c !== '.') return next(layerError)
// Trim off the part of the url that matches the route
// middleware (.use stuff) needs to have the path stripped
debug('trim prefix (%s) from url %s', layerPath, req.url);
removed = layerPath;
req.url = protohost + req.url.substr(protohost.length + removed.length);
// Ensure leading slash
if (!fqdn && req.url[0] !== '/') {
if (!protohost && req.url[0] !== '/') {
req.url = '/' + req.url;
slashAdded = true;
}
@@ -351,11 +356,6 @@ proto.process_params = function process_params(layer, called, req, res, done) {
paramIndex = 0;
key = keys[i++];
if (!key) {
return done();
}
name = key.name;
paramVal = req.params[name];
paramCallbacks = params[name];
@@ -448,18 +448,18 @@ proto.use = function use(fn) {
var callbacks = flatten(slice.call(arguments, offset));
if (callbacks.length === 0) {
throw new TypeError('Router.use() requires middleware functions');
throw new TypeError('Router.use() requires a middleware function')
}
for (var i = 0; i < callbacks.length; i++) {
var fn = callbacks[i];
if (typeof fn !== 'function') {
throw new TypeError('Router.use() requires middleware function but got a ' + gettype(fn));
throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
}
// add the middleware
debug('use %s %s', path, fn.name || '<anonymous>');
debug('use %o %s', path, fn.name || '<anonymous>')
var layer = new Layer(path, {
sensitive: this.caseSensitive,
@@ -531,6 +531,23 @@ function getPathname(req) {
}
}
// Get get protocol + host for a URL
function getProtohost(url) {
if (typeof url !== 'string' || url.length === 0 || url[0] === '/') {
return undefined
}
var searchIndex = url.indexOf('?')
var pathLength = searchIndex !== -1
? searchIndex
: url.length
var fqdnIndex = url.substr(0, pathLength).indexOf('://')
return fqdnIndex !== -1
? url.substr(0, url.indexOf('/', 3 + fqdnIndex))
: undefined
}
// get type for error message
function gettype(obj) {
var type = typeof obj;
@@ -578,9 +595,12 @@ function mergeParams(params, parent) {
var o = 0;
// determine numeric gaps
while (i === o || o in parent) {
if (i in params) i++;
if (o in parent) o++;
while (i in params) {
i++;
}
while (o in parent) {
o++;
}
// offset numeric indices in params before merge
@@ -593,7 +613,7 @@ function mergeParams(params, parent) {
}
}
return mixin(parent, params);
return mixin(obj, params);
}
// restore obj props after function
@@ -606,7 +626,7 @@ function restore(fn, obj) {
vals[i] = obj[props[i]];
}
return function(err){
return function () {
// restore vals
for (var i = 0; i < props.length; i++) {
obj[props[i]] = vals[i];

View File

@@ -35,7 +35,7 @@ function Layer(path, options, fn) {
return new Layer(path, options, fn);
}
debug('new %s', path);
debug('new %o', path)
var opts = options || {};
this.handle = fn;
@@ -44,9 +44,9 @@ function Layer(path, options, fn) {
this.path = undefined;
this.regexp = pathRegexp(path, this.keys = [], opts);
if (path === '/' && opts.end === false) {
this.regexp.fast_slash = true;
}
// set fast path flags
this.regexp.fast_star = path === '*'
this.regexp.fast_slash = path === '/' && opts.end === false
}
/**
@@ -108,23 +108,28 @@ Layer.prototype.handle_request = function handle(req, res, next) {
*/
Layer.prototype.match = function match(path) {
if (path == null) {
// no path, nothing matches
this.params = undefined;
this.path = undefined;
return false;
var match
if (path != null) {
// fast path non-ending match for / (any path matches)
if (this.regexp.fast_slash) {
this.params = {}
this.path = ''
return true
}
// fast path for * (everything matched in a param)
if (this.regexp.fast_star) {
this.params = {'0': decode_param(path)}
this.path = path
return true
}
// match the path
match = this.regexp.exec(path)
}
if (this.regexp.fast_slash) {
// fast path non-ending match for / (everything matches)
this.params = {};
this.path = '';
return true;
}
var m = this.regexp.exec(path);
if (!m) {
if (!match) {
this.params = undefined;
this.path = undefined;
return false;
@@ -132,15 +137,15 @@ Layer.prototype.match = function match(path) {
// store values
this.params = {};
this.path = m[0];
this.path = match[0]
var keys = this.keys;
var params = this.params;
for (var i = 1; i < m.length; i++) {
for (var i = 1; i < match.length; i++) {
var key = keys[i - 1];
var prop = key.name;
var val = decode_param(m[i]);
var val = decode_param(match[i])
if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
params[prop] = val;

View File

@@ -44,7 +44,7 @@ function Route(path) {
this.path = path;
this.stack = [];
debug('new %s', path);
debug('new %o', path)
// route handlers for various http methods
this.methods = {};
@@ -112,10 +112,16 @@ Route.prototype.dispatch = function dispatch(req, res, done) {
next();
function next(err) {
// signal to exit route
if (err && err === 'route') {
return done();
}
// signal to exit router
if (err && err === 'router') {
return done(err)
}
var layer = stack[idx++];
if (!layer) {
return done(err);
@@ -169,7 +175,7 @@ Route.prototype.all = function all() {
if (typeof handle !== 'function') {
var type = toString.call(handle);
var msg = 'Route.all() requires callback functions but got a ' + type;
var msg = 'Route.all() requires a callback function but got a ' + type
throw new TypeError(msg);
}
@@ -192,11 +198,11 @@ methods.forEach(function(method){
if (typeof handle !== 'function') {
var type = toString.call(handle);
var msg = 'Route.' + method + '() requires callback functions but got a ' + type;
var msg = 'Route.' + method + '() requires a callback function but got a ' + type
throw new Error(msg);
}
debug('%s %s', method, this.path);
debug('%s %o', method, this.path)
var layer = Layer('/', {}, handle);
layer.method = method;

View File

@@ -12,12 +12,12 @@
* @api private
*/
var Buffer = require('safe-buffer').Buffer
var contentDisposition = require('content-disposition');
var contentType = require('content-type');
var deprecate = require('depd')('express');
var flatten = require('array-flatten');
var mime = require('send').mime;
var basename = require('path').basename;
var etag = require('etag');
var proxyaddr = require('proxy-addr');
var qs = require('qs');
@@ -32,13 +32,7 @@ var querystring = require('querystring');
* @api private
*/
exports.etag = function (body, encoding) {
var buf = !Buffer.isBuffer(body)
? new Buffer(body, encoding)
: body;
return etag(buf, {weak: false});
};
exports.etag = createETagGenerator({ weak: false })
/**
* Return weak ETag for `body`.
@@ -49,13 +43,7 @@ exports.etag = function (body, encoding) {
* @api private
*/
exports.wetag = function wetag(body, encoding){
var buf = !Buffer.isBuffer(body)
? new Buffer(body, encoding)
: body;
return etag(buf, {weak: true});
};
exports.wetag = createETagGenerator({ weak: true })
/**
* Check if `path` looks absolute.
@@ -66,9 +54,9 @@ exports.wetag = function wetag(body, encoding){
*/
exports.isAbsolute = function(path){
if ('/' == path[0]) return true;
if (':' == path[1] && '\\' == path[2]) return true;
if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path
if ('/' === path[0]) return true;
if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path
if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path
};
/**
@@ -142,7 +130,7 @@ function acceptParams(str, index) {
for (var i = 1; i < parts.length; ++i) {
var pms = parts[i].split(/ *= */);
if ('q' == pms[0]) {
if ('q' === pms[0]) {
ret.quality = parseFloat(pms[1]);
} else {
ret.params[pms[0]] = pms[1];
@@ -274,6 +262,25 @@ exports.setCharset = function setCharset(type, charset) {
return contentType.format(parsed);
};
/**
* Create an ETag generator function, generating ETags with
* the given options.
*
* @param {object} options
* @return {function}
* @private
*/
function createETagGenerator (options) {
return function generateETag (body, encoding) {
var buf = !Buffer.isBuffer(body)
? Buffer.from(body, encoding)
: body
return etag(buf, options)
}
}
/**
* Parse an extended query string with qs.
*
@@ -283,7 +290,6 @@ exports.setCharset = function setCharset(type, charset) {
function parseExtendedQueryString(str) {
return qs.parse(str, {
allowDots: false,
allowPrototypes: true
});
}

View File

@@ -16,7 +16,6 @@
var debug = require('debug')('express:view');
var path = require('path');
var fs = require('fs');
var utils = require('./utils');
/**
* Module variables.
@@ -75,7 +74,17 @@ function View(name, options) {
if (!opts.engines[this.ext]) {
// load engine
opts.engines[this.ext] = require(this.ext.substr(1)).__express;
var mod = this.ext.substr(1)
debug('require "%s"', mod)
// default engine export
var fn = require(mod).__express
if (typeof fn !== 'function') {
throw new Error('Module "' + mod + '" does not provide a view engine.')
}
opts.engines[this.ext] = fn
}
// store loaded engine

View File

@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Fast, unopinionated, minimalist web framework",
"version": "4.13.2",
"version": "4.16.4",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
@@ -13,7 +13,7 @@
"Young Jae Sim <hanul@hanul.me>"
],
"license": "MIT",
"repository": "strongloop/express",
"repository": "expressjs/express",
"homepage": "http://expressjs.com/",
"keywords": [
"express",
@@ -27,50 +27,56 @@
"api"
],
"dependencies": {
"accepts": "~1.2.12",
"accepts": "~1.3.5",
"array-flatten": "1.1.1",
"content-disposition": "0.5.0",
"content-type": "~1.0.1",
"cookie": "0.1.3",
"body-parser": "1.18.3",
"content-disposition": "0.5.2",
"content-type": "~1.0.4",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "~2.2.0",
"depd": "~1.0.1",
"escape-html": "1.0.2",
"etag": "~1.7.0",
"finalhandler": "0.4.0",
"fresh": "0.3.0",
"merge-descriptors": "1.0.0",
"methods": "~1.1.1",
"debug": "2.6.9",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.1.1",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.0",
"parseurl": "~1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "~1.0.8",
"qs": "4.0.0",
"range-parser": "~1.0.2",
"send": "0.13.0",
"serve-static": "~1.10.0",
"type-is": "~1.6.6",
"utils-merge": "1.0.0",
"vary": "~1.0.1"
"proxy-addr": "~2.0.4",
"qs": "6.5.2",
"range-parser": "~1.2.0",
"safe-buffer": "5.1.2",
"send": "0.16.2",
"serve-static": "1.13.2",
"setprototypeof": "1.1.0",
"statuses": "~1.4.0",
"type-is": "~1.6.16",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"devDependencies": {
"after": "0.8.1",
"ejs": "2.3.3",
"istanbul": "0.3.17",
"marked": "0.3.5",
"mocha": "2.2.5",
"should": "7.0.2",
"supertest": "1.0.1",
"body-parser": "~1.13.3",
"connect-redis": "~2.4.1",
"cookie-parser": "~1.3.5",
"cookie-session": "~1.2.0",
"express-session": "~1.11.3",
"jade": "~1.11.0",
"method-override": "~2.3.5",
"morgan": "~1.6.1",
"multiparty": "~4.1.2",
"vhost": "~3.0.1"
"after": "0.8.2",
"connect-redis": "3.4.0",
"cookie-parser": "~1.4.3",
"cookie-session": "1.3.2",
"ejs": "2.6.1",
"eslint": "2.13.1",
"express-session": "1.15.6",
"hbs": "4.0.1",
"istanbul": "0.4.5",
"marked": "0.5.1",
"method-override": "3.0.0",
"mocha": "5.2.0",
"morgan": "1.9.1",
"multiparty": "4.2.1",
"pbkdf2-password": "1.2.1",
"should": "13.2.3",
"supertest": "3.3.0",
"vhost": "~3.0.2"
},
"engines": {
"node": ">= 0.10.0"
@@ -83,6 +89,7 @@
"lib/"
],
"scripts": {
"lint": "eslint .",
"test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --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/",

View File

@@ -4,9 +4,13 @@ var should = require('should');
var express = require('../')
, Route = express.Route
, methods = require('methods')
, assert = require('assert');
describe('Route', function(){
it('should work without handlers', function(done) {
var req = { method: 'GET', url: '/' }
var route = new Route('/foo')
route.dispatch(req, {}, done)
})
describe('.all', function(){
it('should add handler', function(done){
@@ -20,7 +24,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
should(req.called).be.ok;
should(req.called).be.ok()
done();
});
})
@@ -79,7 +83,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
should(req.called).be.ok;
should(req.called).be.ok()
done();
});
})
@@ -99,7 +103,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
should(req.called).be.true;
should(req.called).be.true()
done();
});
})
@@ -151,7 +155,7 @@ describe('Route', function(){
});
route.dispatch(req, {}, function (err) {
should(err).be.ok;
should(err).be.ok()
should(err.message).equal('foobar');
req.order.should.equal('a');
done();
@@ -177,7 +181,7 @@ describe('Route', function(){
});
route.dispatch(req, {}, function (err) {
should(err).be.ok;
should(err).be.ok()
should(err.message).equal('foobar');
req.order.should.equal('a');
done();
@@ -217,7 +221,7 @@ describe('Route', function(){
});
route.dispatch(req, {}, function(err){
should(err).be.ok;
should(err).be.ok()
err.message.should.equal('boom!');
done();
});
@@ -229,7 +233,7 @@ describe('Route', function(){
route.all(function(err, req, res, next){
// this should not execute
true.should.be.false;
true.should.be.false()
});
route.dispatch(req, {}, done);

View File

@@ -7,15 +7,12 @@ var express = require('../')
describe('Router', function(){
it('should return a function with router methods', function() {
var router = Router();
assert(typeof router == 'function');
var router = new Router();
assert(typeof router == 'function');
assert(typeof router === 'function')
assert(typeof router.get == 'function');
assert(typeof router.handle == 'function');
assert(typeof router.use == 'function');
assert(typeof router.get === 'function')
assert(typeof router.handle === 'function')
assert(typeof router.use === 'function')
});
it('should support .use of other routers', function(done){
@@ -47,12 +44,22 @@ describe('Router', function(){
var router = new Router();
router.use(function (req, res) {
false.should.be.true;
false.should.be.true()
});
router.handle({ url: '', method: 'GET' }, {}, done);
});
it('should handle missing URL', function (done) {
var router = new Router()
router.use(function (req, res) {
throw new Error('should not be called')
})
router.handle({ method: 'GET' }, {}, done)
})
it('should not stack overflow with many registered routes', function(done){
var handler = function(req, res){ res.end(new Error('wrong handler')) };
var router = new Router();
@@ -337,20 +344,68 @@ describe('Router', function(){
assert.equal(count, methods.length);
done();
})
it('should be called for any URL when "*"', function (done) {
var cb = after(4, done)
var router = new Router()
function no () {
throw new Error('should not be called')
}
router.all('*', function (req, res) {
res.end()
})
router.handle({ url: '/', method: 'GET' }, { end: cb }, no)
router.handle({ url: '/foo', method: 'GET' }, { end: cb }, no)
router.handle({ url: 'foo', method: 'GET' }, { end: cb }, no)
router.handle({ url: '*', method: 'GET' }, { end: cb }, no)
})
})
describe('.use', function() {
it('should require arguments', function(){
var router = new Router();
router.use.bind(router).should.throw(/requires middleware function/)
it('should require middleware', function () {
var router = new Router()
assert.throws(function () { router.use('/') }, /requires a middleware function/)
})
it('should not accept non-functions', function(){
var router = new Router();
router.use.bind(router, '/', 'hello').should.throw(/requires middleware function.*string/)
router.use.bind(router, '/', 5).should.throw(/requires middleware function.*number/)
router.use.bind(router, '/', null).should.throw(/requires middleware function.*Null/)
router.use.bind(router, '/', new Date()).should.throw(/requires middleware function.*Date/)
it('should reject string as middleware', function () {
var router = new Router()
assert.throws(function () { router.use('/', 'foo') }, /requires a middleware function but got a string/)
})
it('should reject number as middleware', function () {
var router = new Router()
assert.throws(function () { router.use('/', 42) }, /requires a middleware function but got a number/)
})
it('should reject null as middleware', function () {
var router = new Router()
assert.throws(function () { router.use('/', null) }, /requires a middleware function but got a Null/)
})
it('should reject Date as middleware', function () {
var router = new Router()
assert.throws(function () { router.use('/', new Date()) }, /requires a middleware function but got a Date/)
})
it('should be called for any URL', function (done) {
var cb = after(4, done)
var router = new Router()
function no () {
throw new Error('should not be called')
}
router.use(function (req, res) {
res.end()
})
router.handle({ url: '/', method: 'GET' }, { end: cb }, no)
router.handle({ url: '/foo', method: 'GET' }, { end: cb }, no)
router.handle({ url: 'foo', method: 'GET' }, { end: cb }, no)
router.handle({ url: '*', method: 'GET' }, { end: cb }, no)
})
it('should accept array of middleware', function(done){

Some files were not shown because too many files have changed in this diff Show More