Compare commits

...

405 Commits

Author SHA1 Message Date
Wes Todd
4f0f6cc67d 4.19.1 2024-03-20 17:17:59 -05:00
Wes Todd
a003cfab03 Allow passing non-strings to res.location with new encoding handling checks fixes #5554 #5555 2024-03-20 17:12:46 -05:00
Wes Todd
a1fa90fcea fixed un-edited version in history.md for 4.19.0 2024-03-20 16:52:48 -05:00
Wes Todd
11f2b1db22 build: fix build due to inconsistent supertest behavior in older versions 2024-03-20 16:33:03 -05:00
Wes Todd
084e36506a 4.19.0 2024-03-20 10:18:54 -05:00
FDrag0n
0867302ddb Prevent open redirect allow list bypass due to encodeurl
Co-authored-by: Jon Church <me@jonchurch.com>
2024-03-20 10:18:54 -05:00
Rand McKinney
567c9c665d Add note on how to update docs for new release (#5541)
* Update Release-Process.md

Add note about updating docs.

* Update Release-Process.md

* Update Release-Process.md
2024-03-16 11:57:42 -06:00
Rich Hodgkins
69a4cf2819 deps: cookie@0.6.0
closes #5404
2024-03-15 10:27:45 -05:00
Wes Todd
4ee853e837 docs: loosen TC activity rules 2024-03-14 12:43:12 +01:00
Wes Todd
414854b82e docs: nominating @wesleytodd to be project captian 2024-03-14 12:40:52 +01:00
Ulises Gascón
06c6b88808 docs: update release date 2024-03-11 16:19:21 +01:00
Ulises Gascón
1b51edac7c 4.18.3 2024-02-26 20:20:53 +01:00
Ulises Gascón
b625132864 build: pin Node 21.x to minor
Co-authored-by: Aravind Nair <22199259+aravindvnair99@users.noreply.github.com>
closes #5430
2024-02-26 20:08:10 +01:00
Ulises Gascón
e3eca80584 build: pin Node 21.x to minor
Co-authored-by: Aravind Nair <22199259+aravindvnair99@users.noreply.github.com>
2024-02-26 20:07:59 +01:00
Ulises Gascon
23b44b3ddd build: support Node.js 21.6.2 2024-02-26 20:07:27 +01:00
Ulises Gascon
b9fea12245 build: support Node.js 21.x in appveyor 2024-02-26 20:06:49 +01:00
Ulises Gascon
c259c3407f build: support Node.js 21.x 2024-02-26 20:05:58 +01:00
Ulises Gascon
fdeb1d3176 build: support Node.js 20.x in appveyor
closes #5429
2024-02-26 19:57:01 +01:00
Ulises Gascón
734b281900 build: support Node.js 20.x 2024-02-26 19:41:28 +01:00
Dmitry Kondar
0e3ab6ec21 examples: improve view count in cookie-sessions
closes #5414
2024-02-19 16:47:26 -05:00
Ulises Gascon
59af63ac2e build: Node.js@18.19
closes #5490
2024-02-19 14:18:24 -05:00
Ulises Gascon
e720c5a21b docs: add documentation for benchmarks
closes #5312
2024-02-19 12:04:49 -05:00
riddlew
3abea7f818 examples: remove multipart example
Closes #5193
closes #5195
2024-02-19 10:04:05 -05:00
christof louw
2a89eb5c74 tests: fix handling multiple callbacks
closes #5233
2024-02-19 08:20:39 -05:00
Gireesh Punathil
59aae7686b docs: add project captains to contribution
closes #4210
closes #5484
2024-02-18 12:21:22 -06:00
Wes Todd
c4fe7de7bc docs: update TC governance rules
closes #5483
2024-02-18 22:04:47 -05:00
Douglas Christopher Wilson
a22920707b build: actions/checkout@v4 2023-11-01 22:08:37 -04:00
Douglas Christopher Wilson
02d1c3916e build: Node.js@19.9 2023-08-23 20:07:50 -04:00
Douglas Christopher Wilson
8d8bfaac7b build: Node.js@18.17 2023-08-23 19:58:41 -04:00
Douglas Christopher Wilson
13df1de857 build: eslint@8.47.0 2023-08-23 19:49:36 -04:00
Raz Luvaton
2a00da2067 tests: use random port in listen test
closes #5162
2023-06-04 11:47:20 -04:00
Douglas Christopher Wilson
24e4a2570d build: Node.js@16.20 2023-04-06 20:43:53 -04:00
Douglas Christopher Wilson
91b6fb83b4 build: use nyc@14.1.1 for Node.js < 10 2023-04-06 20:40:27 -04:00
Rakesh Bisht
3531987844 lint: remove unused function arguments in Route tests
closes #5137
2023-05-15 21:53:48 -04:00
Douglas Christopher Wilson
f540c3b019 build: Node.js@18.15 2023-03-13 22:59:15 -04:00
Douglas Christopher Wilson
b8b2eff3c3 build: eslint@8.36.0 2023-03-13 22:52:34 -04:00
Douglas Christopher Wilson
f4e48bc43e build: ejs@3.1.9 2023-03-13 22:49:54 -04:00
Douglas Christopher Wilson
8c24fa8f7b tests: wait for server close in app.listen() 2023-03-13 22:43:19 -04:00
Douglas Christopher Wilson
0debedf4f3 build: fix code coverage aggregate upload 2023-02-26 13:34:32 -05:00
Douglas Christopher Wilson
74beeac071 Fix routing requests without method 2023-02-23 17:23:22 -05:00
Arnaud Benhamdine
9bc1742937 build: support Node.js 19.x 2023-02-23 15:28:18 -05:00
Rakesh Bisht
5ad95419ba docs: fix typos in history
closes #5131
2023-02-23 12:14:47 -05:00
Douglas Christopher Wilson
8a76f39d98 build: eslint@8.34.0 2023-02-23 00:28:41 -05:00
Douglas Christopher Wilson
60b7c672c1 build: mocha@10.2.0 2023-02-23 00:27:06 -05:00
Douglas Christopher Wilson
1e42a98db6 deps: body-parser@1.20.2 2023-02-23 00:24:20 -05:00
Rakesh Bisht
506fbd63be docs: add missing JSDoc param for parseExtendedQueryString
closes #5130
2023-02-22 21:10:07 -05:00
Douglas Christopher Wilson
b9f7a97fe1 build: use $GITHUB_OUTPUT for environment list 2023-02-22 18:10:59 -05:00
Douglas Christopher Wilson
546969d198 build: Node.js@18.14 2023-02-22 12:07:48 -05:00
Douglas Christopher Wilson
f05b5d0e9c build: Node.js@16.19 2023-02-22 11:59:40 -05:00
Rakesh Bisht
3c1d605da7 lint: remove unused parameters in examples
closes #5113
2023-02-22 10:25:07 -05:00
Rakesh Bisht
6b4c4f5426 docs: fix typos in JSDoc comments
closes #5117
2023-02-22 00:16:40 -05:00
Rakesh Bisht
a1efd9d6cf lint: remove unused parameter from internal function
coses #5119
2023-02-21 22:55:22 -05:00
Rakesh Bisht
c6ee8d6e7f lint: remove unused function arguments in tests
closes #5124
2023-02-20 22:57:13 -05:00
Abdul Rauf
442fd46799 build: actions/checkout@v3
closes #5027
2022-11-01 21:13:10 -04:00
Arnaud Benhamdine
723b67766f build: Node.js@18.12 2022-11-01 21:10:12 -04:00
Arnaud Benhamdine
29e117e676 build: Node.js@16.18 2022-11-01 21:08:43 -04:00
Kevin Jones
06b2b1416d docs: update git clone to https protocol
closes #5032
2022-11-01 21:05:31 -04:00
Douglas Christopher Wilson
8368dc178a 4.18.2 2022-10-08 16:11:42 -04:00
Abhinav Das
61f4049122 docs: replace Freenode with Libera Chat
closes #5013
2022-10-08 14:52:31 -04:00
Douglas Christopher Wilson
bb7907b932 build: Node.js@18.10
closes #5014
2022-10-07 17:48:59 -04:00
Douglas Christopher Wilson
f56ce73186 build: supertest@6.3.0 2022-10-06 10:28:13 -04:00
Douglas Christopher Wilson
24b3dc5516 deps: qs@6.11.0 2022-10-06 10:27:01 -04:00
Douglas Christopher Wilson
689d175b8b deps: body-parser@1.20.1 2022-10-06 10:26:18 -04:00
Douglas Christopher Wilson
340be0f79a build: eslint@8.24.0 2022-10-05 22:40:51 -04:00
REALSTEVEIG
33e8dc303a docs: use Node.js name style
closes #4926
2022-08-19 21:12:14 -04:00
Douglas Christopher Wilson
644f6464b9 build: supertest@6.2.4 2022-08-18 23:42:39 -04:00
Douglas Christopher Wilson
ecd7572f1e build: Node.js@14.20 2022-08-18 23:41:10 -04:00
Douglas Christopher Wilson
97131bcda8 build: Node.js@18.7 2022-08-18 23:01:25 -04:00
Douglas Christopher Wilson
8d98e86d7f build: Node.js@16.17 2022-08-18 23:00:36 -04:00
Alexandru Dragomir
2c47827053 examples: remove unused function arguments in params
closes #4914
2022-05-20 11:57:37 -04:00
Douglas Christopher Wilson
97f0a518d8 tests: verify all handlers called in stack tests 2022-05-20 11:54:35 -04:00
Douglas Christopher Wilson
7ec5dd2b3c Fix regression routing a large stack in a single route
fixes #4913
2022-05-20 09:37:20 -04:00
Douglas Christopher Wilson
ab2c70b954 build: Node.js@18.1 2022-05-20 09:35:20 -04:00
Douglas Christopher Wilson
745a63f825 build: ejs@3.1.8 2022-05-20 09:34:47 -04:00
Douglas Christopher Wilson
a2dfc56a49 build: mocha@10.0.0 2022-05-20 09:33:19 -04:00
Douglas Christopher Wilson
d854c43ea1 4.18.1 2022-04-29 15:32:26 -04:00
Douglas Christopher Wilson
b02a95c693 build: Node.js@16.15 2022-04-29 14:52:20 -04:00
Douglas Christopher Wilson
631ada0c64 Fix hanging on large stack of sync routes
fixes #4899
2022-04-29 13:34:47 -04:00
Hashen
75e0c7a2c9 bench: remove unused parameter
closes #4898
2022-04-28 22:00:49 -04:00
Douglas Christopher Wilson
e2482b7e36 build: ejs@3.1.7 2022-04-28 21:59:32 -04:00
Douglas Christopher Wilson
2df96e349f build: supertest@6.2.3 2022-04-28 13:04:38 -04:00
Douglas Christopher Wilson
a38fae126a build: mocha@9.2.2 2022-04-28 13:04:11 -04:00
Douglas Christopher Wilson
547fdd41dc 4.18.0 2022-04-25 14:53:28 -04:00
Deniz
0b330ef57c bench: print latency and vary connections
closes #4880
2022-04-24 19:31:42 -04:00
Douglas Christopher Wilson
158a17031a build: support Node.js 18.x 2022-04-21 02:09:08 -04:00
Douglas Christopher Wilson
29ea1b2f74 build: use 64-bit Node.js in AppVeyor 2022-04-21 01:38:59 -04:00
Douglas Christopher Wilson
11a209e4b7 build: support Node.js 17.x 2022-04-20 22:02:37 -04:00
phoenix
fd8e45c344 tests: mark stack overflow as long running
closes #4887
2022-04-20 19:52:20 -04:00
Douglas Christopher Wilson
708ac4cdf5 Fix handling very large stacks of sync middleware
closes #4891
2022-04-13 23:29:25 -04:00
Douglas Christopher Wilson
92c5ce59f5 deps: cookie@0.5.0 2022-04-11 22:51:13 -04:00
Hashen
8880ddad1c examples: add missing html label associations
closes #4884
2022-04-11 19:29:14 -04:00
Douglas Christopher Wilson
b91c7ffb28 examples: use http-errors to create errors 2022-04-11 19:28:50 -04:00
Eslam Salem
ecaf67c930 docs: remove Node Security Project from security policy
closes #4890
2022-04-11 18:54:33 -04:00
Ghouse Mohamed
99175c3ef6 docs: fix typo in casing of HTTP
closes #4872
2022-04-08 03:42:09 -04:00
Hashen
1b2e097be2 tests: fix typo in description
closes #4882
2022-04-07 19:20:41 -04:00
Douglas Christopher Wilson
04da4aaf1a build: use supertest@3.4.2 for Node.js 6.x 2022-04-07 19:17:10 -04:00
Douglas Christopher Wilson
2e2d78c4d9 deps: on-finished@2.4.1 2022-04-03 01:15:37 -04:00
3imed-jaberi
980d881e3b deps: statuses@2.0.1
closes #4336
2022-04-02 22:39:35 -04:00
Douglas Christopher Wilson
1df75763e3 deps: qs@6.10.3 2022-04-02 21:56:41 -04:00
Douglas Christopher Wilson
32c558d414 deps: body-parser@1.20.0 2022-04-02 21:51:31 -04:00
Douglas Christopher Wilson
a10770286e Use http-errors for res.format error 2022-03-27 23:41:31 -04:00
Chris Barth
5855339455 Fix behavior of null/undefined as "maxAge" in res.cookie
fixes #3935
closes #3936
2022-03-26 23:11:48 -04:00
Ulises Gascon
1cc8169938 deps: depd@2.0.0
closes #4174
2022-03-26 14:05:25 -04:00
Nadav Ivgi
9482b82d0b Invoke default with same arguments as types in res.format
closes #3587
2022-03-26 01:29:40 -04:00
Douglas Christopher Wilson
10b9b507b7 examples: use updated res.download in example 2022-03-25 18:14:27 -04:00
Douglas Christopher Wilson
03dc367187 Allow options without filename in res.download 2022-03-25 18:13:42 -04:00
Douglas Christopher Wilson
f739b162d9 deps: finalhandler@1.2.0 2022-03-25 01:46:32 -04:00
Douglas Christopher Wilson
c92420648e deps: serve-static@1.15.0 2022-03-25 01:44:51 -04:00
Douglas Christopher Wilson
dd69eedd18 deps: send@0.18.0 2022-03-25 01:43:45 -04:00
Tommaso Tofacchi
0def9bb659 Add "root" option to res.download
fixes #4834
closes #4855
2022-03-25 00:08:38 -04:00
Jon Church
4847d0efa1 Deprecate string and non-integer arguments to res.status
closes #4223
2022-03-23 23:14:08 -04:00
Evan Hahn
c17fe05861 Ignore Object.prototype values in settings through app.set/app.get
closes #4802
closes #4803
2022-03-23 20:05:05 -04:00
Tito D. Kesumo Siregar
87279c08aa Support proper 205 responses using res.send
closes #4592
closes #4596
2022-03-23 20:05:05 -04:00
Kris Kalavantavanich
8bf0720391 build: support Node.js 16.x 2022-03-23 20:05:05 -04:00
Kris Kalavantavanich
eb4c930d5f build: support Node.js 15.x 2022-03-23 20:05:05 -04:00
Hashen
947b6b7d57 lint: remove unnecessary continue statement in loop
closes #4868
2022-03-20 22:59:20 -04:00
Hashen
bf4c3ee00f docs: fix incomplete JSDoc comment
closes #4867
2022-03-20 20:51:39 -04:00
Hashen
2a7417dd84 examples: fixup html
closes #4866
2022-03-20 15:14:33 -04:00
Tobias Speicher
490f1a1738 lint: remove deprecated String.prototype.substr
closes #4860
2022-03-20 12:34:37 -04:00
Douglas Christopher Wilson
446046f886 build: mocha@9.2.1 2022-03-01 00:27:48 -05:00
Douglas Christopher Wilson
291993d73c tests: expand res.sendFile options tests 2022-03-01 00:22:09 -05:00
Steven
e8594c3571 docs: add install size badge
closes #3710
2022-02-28 23:41:41 -05:00
Douglas Christopher Wilson
07aa91f7cb docs: consolidate contributing in readme 2022-02-28 21:52:57 -05:00
Douglas Christopher Wilson
4ed35b4202 docs: switch badges to badgen 2022-02-28 21:23:49 -05:00
Douglas Christopher Wilson
ea66a9b81b docs: update link to github actions ci 2022-02-28 21:15:08 -05:00
apeltop
d0e166c3c6 docs: fix typo in private api jsdoc
closes #4843
2022-02-28 18:37:41 -05:00
Douglas Christopher Wilson
cf9f662655 tests: fix position of res.sendfile(path, options) test 2022-02-24 00:17:01 -05:00
Douglas Christopher Wilson
8da8f79c44 tests: fix callback in res.download test 2022-02-23 00:20:34 -05:00
Douglas Christopher Wilson
18f782bba9 tests: remove duplicate utils 2022-02-23 00:18:36 -05:00
Douglas Christopher Wilson
bc5ca05509 tests: remove usage of should 2022-02-21 19:54:52 -05:00
Douglas Christopher Wilson
9967ffbdc2 tests: update res.append to verify separate header lines 2022-02-21 19:23:25 -05:00
Douglas Christopher Wilson
7df0c840e0 tests: fix up app.locals tests 2022-02-21 19:07:26 -05:00
Douglas Christopher Wilson
d8ed591117 tests: fix req.acceptsLanguage tests 2022-02-20 23:49:42 -05:00
Douglas Christopher Wilson
8ee3420f0f tests: fix req.acceptsEncodings tests 2022-02-20 23:43:02 -05:00
Douglas Christopher Wilson
3d7fce56a3 4.17.3 2022-02-16 21:03:42 -05:00
Douglas Christopher Wilson
f9063712e0 build: update example dependencies 2022-02-16 00:11:24 -05:00
Douglas Christopher Wilson
6381bc6317 deps: qs@6.9.7 2022-02-16 00:03:16 -05:00
Douglas Christopher Wilson
a007863096 deps: body-parser@1.19.2 2022-02-15 23:43:41 -05:00
Douglas Christopher Wilson
e98f5848a0 Revert "build: use minimatch@3.0.4 for Node.js < 4" 2022-02-14 18:42:47 -05:00
Douglas Christopher Wilson
a65913776d tests: use strict mode 2022-02-09 01:07:08 -05:00
Douglas Christopher Wilson
a39e409cf3 tests: prevent leaking changes to NODE_ENV 2022-02-08 18:40:07 -05:00
KoyamaSohei
82de4de5ab examples: fix path traversal in downloads example
closes #4120
2022-02-08 17:32:10 -05:00
Douglas Christopher Wilson
12310c5294 build: use nyc for test coverage 2022-02-07 23:08:12 -05:00
Thomas Strauß
884657d546 examples: remove bitwise syntax for includes check
closes #4814
2022-02-07 22:58:44 -05:00
Douglas Christopher Wilson
7511d08328 build: use minimatch@3.0.4 for Node.js < 4 2022-02-07 17:46:47 -05:00
Douglas Christopher Wilson
2585f209f9 tests: fix test missing assertion 2022-02-04 21:18:47 -05:00
Douglas Christopher Wilson
9d0976229d build: supertest@6.2.2 2022-02-04 21:14:41 -05:00
Douglas Christopher Wilson
43cc56eb9e build: clean up gitignore 2022-02-04 16:48:33 -05:00
Douglas Christopher Wilson
1c7bbcc143 build: Node.js@14.19 2022-02-04 16:36:47 -05:00
Douglas Christopher Wilson
9cbbc8ae74 deps: cookie@0.4.2 2022-02-04 16:35:50 -05:00
Douglas Christopher Wilson
6fbc269563 pref: remove unnecessary regexp for trust proxy 2022-02-04 16:34:56 -05:00
Douglas Christopher Wilson
2bc734aa3f deps: accepts@~1.3.8 2022-02-04 16:21:11 -05:00
caioagiani
89bb531b31 docs: fix typo in res.download jsdoc
closes #4805
2022-02-03 23:26:17 -05:00
Douglas Christopher Wilson
744564fcf8 tests: add test for multiple ips in "trust proxy" 2022-02-02 16:19:01 -05:00
Douglas Christopher Wilson
da6cb0ed8a tests: add range tests to res.download 2022-02-02 15:15:41 -05:00
Douglas Christopher Wilson
00ad5bee96 tests: add more tests for app.request & app.response 2022-02-02 15:02:46 -05:00
Douglas Christopher Wilson
141914e817 tests: fix tests that did not bubble errors 2022-02-02 14:16:20 -05:00
Douglas Christopher Wilson
bd4fdfe5f7 tests: remove global dependency on should
fixes #4797
2022-02-02 01:55:16 -05:00
Douglas Christopher Wilson
215f484fb4 tests: fix wording of req.accepts* test cases 2022-02-02 01:42:35 -05:00
Douglas Christopher Wilson
20047bb6e4 examples: use strict mode 2022-02-02 01:30:51 -05:00
Douglas Christopher Wilson
8b9757e8b8 build: fix running linter in CI 2022-02-02 01:25:55 -05:00
Douglas Christopher Wilson
a84e73b958 tests: add test for hello-world example 2022-02-02 01:23:40 -05:00
Douglas Christopher Wilson
69997cbdbe examples: fix error handling in auth example 2022-02-02 00:44:28 -05:00
Douglas Christopher Wilson
c221b8596e build: mocha@9.2.0 2022-01-27 19:02:58 -05:00
Douglas Christopher Wilson
ea537d907d 4.17.2 2021-12-16 22:40:49 -05:00
Douglas Christopher Wilson
eee93a2760 build: update example dependencies 2021-12-16 21:47:10 -05:00
Douglas Christopher Wilson
b35773cf19 build: eslint@7.32.0 2021-12-16 21:44:26 -05:00
Douglas Christopher Wilson
c8a42006b8 build: mocha@9.1.3 2021-12-16 21:39:43 -05:00
Aalaap Ghag
21cf522dcd examples: improve 404 message wording
closes #4471
2021-12-16 13:00:12 -05:00
Douglas Christopher Wilson
a24f27aba7 deps: serve-static@1.14.2 2021-12-16 12:54:18 -05:00
3imed-jaberi
a33266a206 build: support Node.js 14.x 2021-12-16 00:22:28 -05:00
3imed-jaberi
6fe271e8aa build: support Node.js 13.x 2021-12-16 00:22:28 -05:00
Wes Todd
cbe25d66b3 deps: setprototypeof@1.2.0
closes #4011
2021-12-15 22:38:19 -05:00
Douglas Christopher Wilson
3bb6d96ba9 examples: demonstrate sub directory download 2021-12-15 21:06:33 -05:00
Douglas Christopher Wilson
6660649f1b deps: qs@6.9.6 2021-12-15 20:48:00 -05:00
Douglas Christopher Wilson
a75e4707b9 docs: add note about security report location 2021-12-15 20:45:56 -05:00
Douglas Christopher Wilson
db05a741f0 deps: send@0.17.2 2021-12-11 20:19:38 -05:00
Douglas Christopher Wilson
c2e23ece2e deps: body-parser@1.19.1 2021-12-11 03:45:46 -05:00
Douglas Christopher Wilson
96850e872a deps: content-disposition@0.5.4 2021-12-10 17:58:03 -05:00
Douglas Christopher Wilson
b8d59d5c98 deps: safe-buffer@5.2.1 2021-12-10 17:56:56 -05:00
Douglas Christopher Wilson
59d695c447 build: update example dependencies 2021-12-10 15:47:40 -05:00
Andy
e242796eb3 tests: fix test in app.head
closes #4765
2021-12-04 09:36:34 -05:00
Douglas Christopher Wilson
aaa9690bcf deps: proxy-addr@~2.0.7 2021-11-17 16:16:04 -05:00
drewm
f275e87dff Fix handling of undefined when "json escape" is enabled
closes #4744
2021-11-17 00:00:56 -05:00
Douglas Christopher Wilson
9dd0e7afdb Fix handling of undefined in res.jsonp 2021-11-16 23:58:17 -05:00
Douglas Christopher Wilson
1b2f3a0698 tests: fix up primitive tests for res.jsonp 2021-11-16 23:53:10 -05:00
3imed-jaberi
519126d732 deps: cookie@0.4.1
closes #4337
2021-11-16 21:59:01 -05:00
Ivan Derevianko
99a369f3d5 Fix incorrect middleware execution with unanchored RegExps
fixes #4204
closes #4205
2021-11-16 21:52:11 -05:00
Kim
a1dbb11377 Fix res.jsonp(obj, status) deprecation message
closes #4155
2021-11-16 00:41:19 -05:00
Florian Brandt
353348a83e Fix typo in res.is JSDoc
closes #4192
2021-11-16 00:25:10 -05:00
Juan José Arboleda
dab6ee5822 tests: remove extraneous code from app.listen test
closes #4714
2021-11-15 23:56:46 -05:00
3imed-jaberi
fc138c108f deps: proxy-addr@~2.0.6
closes #4340
2021-11-15 23:14:48 -05:00
Douglas Christopher Wilson
61a23e801f build: mocha@8.4.0 2021-10-05 21:55:00 -04:00
Douglas Christopher Wilson
313d54f033 build: supertest@6.1.6 2021-09-01 19:32:00 -04:00
Douglas Christopher Wilson
de081eb70f build: eslint@4.19.1 2021-09-01 19:27:00 -04:00
Aravind Nair
06d11755c9 build: Node.js@12.22 2021-08-14 01:12:32 -04:00
Aravind Nair
6f2afd3d80 build: Node.js@10.24 2021-08-14 01:12:31 -04:00
Aravind Nair
d5a1cbee70 build: fix wrong Node.js 8.x in AppVeyor
closes #4574
2021-08-14 01:12:24 -04:00
zhangky
f9a0560a9c docs: fix res.sendStatus/sendFile jsdoc comments
closes #4673
2021-08-14 00:39:56 -04:00
Andrew Heaney
821b7f0624 examples: fix typo in comment
closes #4667
2021-08-11 20:39:01 -04:00
Douglas Christopher Wilson
f490f78563 build: reduce npm output 2021-08-11 20:38:31 -04:00
Aravind Nair
884e080a19 build: ejs@3.1.6
closes #4572
closes #4573
2021-07-31 21:54:15 -04:00
alberto barboza
eb76236e2f build: hbs@4.1.2
closes #4643
2021-07-31 18:31:10 -04:00
Hussein Mohamed
52e9bd67b7 tests: fix typos
closes #4564
2021-07-31 16:00:16 -04:00
Hussein Mohamed
135a05c524 docs: fix typos in jsdoc
closes #4564
2021-07-31 16:00:00 -04:00
Lutger Kunst
30afebf8da examples: fixed typo in ejs example css
closes #4554
2021-07-30 16:22:34 -04:00
Douglas Christopher Wilson
8e4add7f74 tests: remove should usage from Router tests
fixes #4635
2021-07-30 16:19:55 -04:00
Abderrahmenla
0fbbc29632 lint: coalesce duplicate switch statements
closes #4587
2021-07-30 15:46:10 -04:00
Aravind Nair
2402126988 build: disable fast-fail for GitHub Actions
closes #4628
2021-07-02 15:53:27 -04:00
Douglas Christopher Wilson
ca3c863428 build: use GitHub Actions instead of Travis CI 2021-07-01 15:22:40 -04:00
Douglas Christopher Wilson
28db2c2c5c build: supertest@6.1.3 2021-01-28 20:17:55 -05:00
Douglas Christopher Wilson
685d4665fd build: mocha@8.2.1 2020-12-23 20:41:52 -05:00
Douglas Christopher Wilson
280a8d39ec build: fix Node.js version check in AppVeyor 2020-12-22 23:41:28 -05:00
Douglas Christopher Wilson
5c4f3e7cc7 build: supertest@6.0.1 2020-11-09 21:44:32 -05:00
Douglas Christopher Wilson
de122c14f5 build: Node.js@12.18 2020-10-21 19:48:58 -04:00
Douglas Christopher Wilson
2a2dd5d32b build: Node.js@10.23 2020-10-19 21:33:05 -04:00
H3RSKO
508936853a docs: update grammar in readme
closes #4376
2020-09-16 21:27:53 -04:00
Rodion Abdurakhimov
5596222f6a docs: update example summaries
closes #4370
2020-08-04 09:46:42 -04:00
Rodion Abdurakhimov
fe67523b9c docs: add examples summary page
closes #4343
closes #4354
2020-07-27 15:15:54 -04:00
yasser
4486fa6324 docs: fix Code of Conduct link in Contributing
closes #4351
2020-07-16 15:06:57 -04:00
Yogi
ecd8a08c1c docs: fix typos in Contributing 2020-07-07 22:43:16 -04:00
Yogi
a75728432e docs: fix typos in Collaborator Guide 2020-07-07 22:42:34 -04:00
Yogi
9007dcbdba docs: fix typos in Triager Guide 2020-07-07 22:42:01 -04:00
Yogi
c519886be5 docs: fix typos in Charter 2020-07-07 22:41:04 -04:00
Moni
3ff1dbeb73 docs: fix markdown links in contributing
closes #4315
2020-06-21 23:06:54 -04:00
Gireesh Punathil
18da651c5b docs: add triager guide
closes #4055
closes #4211
2020-05-06 09:58:29 -07:00
Douglas Christopher Wilson
1b48a5cc3c docs: fix heading levels 2020-04-14 21:12:37 -04:00
Wes Todd
561b4b601e docs: add Charter
closes #4144
2020-04-14 01:39:53 -04:00
Wes Todd
67e64ca4c1 docs: add Code of Conduct
closes #4143
2020-04-07 01:35:34 -04:00
Manuel Baesler
922e9a4615 build: add http keyword for npm search
closes #4102
2020-03-25 19:00:15 -04:00
KoyamaSohei
323a38965a examples: properly escape user input in route-map
fixes #3992
closes #4119
2020-03-25 17:35:14 -04:00
Aditya Srivastava
3f1dcb96e0 examples: add viewport and charset where missing
closes #3860
2020-03-25 17:10:34 -04:00
yanokenken
4b4fa26298 docs: add npm init hint to install section 2020-03-25 16:26:39 -04:00
Chang Wang
47c1d2a816 docs: point npm downloads badge to npm charts of express
closes #3579
2020-03-25 15:37:04 -04:00
Douglas Christopher Wilson
65aff94ec6 build: remove deprecated Travis CI directive 2020-03-17 20:37:16 -04:00
Douglas Christopher Wilson
2d519077ea build: supertest@4.0.2 2020-03-17 20:31:10 -04:00
Douglas Christopher Wilson
d967675852 build: mocha@7.0.1 2020-02-19 00:49:36 -05:00
Douglas Christopher Wilson
22d5b7ed10 build: Node.js@12.16 2020-02-19 00:32:14 -05:00
Douglas Christopher Wilson
872aa4741c build: Node.js@10.19 2020-02-19 00:27:51 -05:00
Douglas Christopher Wilson
87bc4ef763 build: update example dependencies 2020-02-11 23:10:15 -05:00
Douglas Christopher Wilson
f0cbdeadf6 build: mocha@7.0.0 2020-01-09 18:58:52 -05:00
Douglas Christopher Wilson
f1e8a877f4 build: Node.js@12.14 2020-01-09 18:40:28 -05:00
Douglas Christopher Wilson
55831bbd08 build: Node.js@10.18 2020-01-09 18:37:52 -05:00
Douglas Christopher Wilson
e757fa0039 build: Node.js@8.17 2020-01-09 18:30:57 -05:00
Douglas Christopher Wilson
95735a6fcc build: supertest@3.4.2 2019-11-10 22:21:57 -05:00
Douglas Christopher Wilson
668d029a14 build: mocha@6.2.2 2019-11-10 22:15:49 -05:00
Douglas Christopher Wilson
866ffd67d7 build: Node.js@12.13 2019-11-10 22:09:43 -05:00
Douglas Christopher Wilson
741e3f81af build: Node.js@10.17 2019-11-10 22:04:12 -05:00
Douglas Christopher Wilson
4efb49866d build: mocha@6.2.0 2019-08-04 22:23:09 -04:00
Douglas Christopher Wilson
6506fb578c build: Node.js@12.7 2019-08-04 22:09:45 -04:00
Douglas Christopher Wilson
dfa7b80642 build: Node.js@10.16 2019-08-04 22:03:22 -04:00
Douglas Christopher Wilson
e1b45ebd05 4.17.1 2019-05-26 00:24:55 -04:00
Douglas Christopher Wilson
0a48e18056 Revert "Improve error message for null/undefined to res.status"
fixes #3968
2019-05-25 18:15:13 -04:00
Douglas Christopher Wilson
eed05a1464 build: Node.js@12.3 2019-05-24 23:20:52 -04:00
Douglas Christopher Wilson
10c7756764 4.17.0 2019-05-16 21:25:42 -04:00
Douglas Christopher Wilson
9dadca2c64 docs: remove Gratipay links 2019-05-16 20:53:07 -04:00
Douglas Christopher Wilson
b8e50568af tests: ignore unreachable line 2019-05-16 10:04:24 -04:00
Douglas Christopher Wilson
94e48a16f2 build: update example dependencies 2019-05-16 09:58:40 -04:00
Douglas Christopher Wilson
efcb17dcb2 deps: cookie@0.4.0
closes #3958
2019-05-16 09:55:26 -04:00
huadong zuo
b9ecb9afe3 build: support Node.js 12.x
closes #3946
2019-05-16 01:20:24 -04:00
Douglas Christopher Wilson
5266f3a5cb build: test against Node.js 13.x nightly 2019-05-12 22:15:36 -04:00
Douglas Christopher Wilson
e502dde3c8 build: Node.js@10.15 2019-05-12 22:09:35 -04:00
Douglas Christopher Wilson
da6f701317 deps: range-parser@~1.2.1 2019-05-12 22:01:06 -04:00
Douglas Christopher Wilson
88f9733ffa deps: serve-static@1.14.1 2019-05-11 19:29:33 -04:00
Douglas Christopher Wilson
8267c4b724 deps: send@0.17.1 2019-05-10 23:49:13 -04:00
Douglas Christopher Wilson
bc07a41693 deps: finalhandler@~1.1.2 2019-05-09 22:09:56 -04:00
Douglas Christopher Wilson
c754c8ad7b build: support Node.js 11.x 2019-05-09 19:45:01 -04:00
Douglas Christopher Wilson
e917028729 build: Node.js@8.16 2019-05-09 18:03:56 -04:00
Douglas Christopher Wilson
7b076bd8e1 build: Node.js@6.17 2019-05-09 18:03:12 -04:00
Douglas Christopher Wilson
bb5211fa1c tests: add express.text test suite 2019-05-08 23:39:45 -04:00
Ilya Guterman
7f4e37f3ea Add express.text to parse bodies into string
closes #3455
2019-05-08 23:39:16 -04:00
Douglas Christopher Wilson
11192bd168 tests: add express.raw test suite 2019-05-08 00:58:08 -04:00
Amit Zur
0bcdd88dd0 Add express.raw to parse bodies into Buffer
closes #3708
2019-05-08 00:57:02 -04:00
Douglas Christopher Wilson
60aacac167 deps: serve-static@1.14.0
closes #3486
2019-05-07 23:42:36 -04:00
Douglas Christopher Wilson
70a19472f1 deps: send@0.17.0 2019-05-07 23:05:37 -04:00
Douglas Christopher Wilson
6f7a8301a1 tests: add express.static test suite 2019-05-02 17:49:29 -04:00
Douglas Christopher Wilson
8b71f39516 tests: add express.urlencoded test suite 2019-05-01 23:29:28 -04:00
Douglas Christopher Wilson
955f2a5f78 tests: add express.json test suite 2019-05-01 22:59:42 -04:00
Douglas Christopher Wilson
2f782d8478 deps: body-parser@1.19.0 2019-04-30 23:31:32 -04:00
Douglas Christopher Wilson
32f5293afa deps: qs@6.7.0 2019-04-30 23:06:50 -04:00
Douglas Christopher Wilson
6d9dd2da49 deps: type-is@~1.6.18 2019-04-30 22:48:56 -04:00
Douglas Christopher Wilson
40dbfa2de2 deps: accepts@~1.3.7 2019-04-30 22:24:35 -04:00
Douglas Christopher Wilson
9afa1cfc85 deps: statuses@~1.5.0 2019-04-30 22:17:03 -04:00
Douglas Christopher Wilson
7eacdcef19 deps: setprototypeof@1.1.1 2019-04-22 13:40:23 -04:00
James George
b02d3a1744 docs: add link to contributing guide
closes #3846
2019-04-17 16:18:37 -04:00
Douglas Christopher Wilson
03341204ff deps: parseurl@~1.3.3 2019-04-17 16:06:35 -04:00
Douglas Christopher Wilson
50eb5e4377 deps: proxy-addr@~2.0.5 2019-04-17 16:05:17 -04:00
Douglas Christopher Wilson
952484f73a deps: content-disposition@0.5.3 2019-04-17 16:00:02 -04:00
Douglas Christopher Wilson
4218d04183 build: marked@0.6.2 2019-04-17 15:58:26 -04:00
Douglas Christopher Wilson
cf5c813d2f build: hbs@4.0.4 2019-04-17 15:51:33 -04:00
Douglas Christopher Wilson
9e5d1a30c3 build: test against Node.js 12.x nightly 2019-04-17 10:44:27 -04:00
김정환
8a97346eaf tests: assert calls order in middleware basic tests
closes #3878
2019-04-17 10:41:43 -04:00
Marcin Wanago
6eda52a3dc docs: use const in readme example
fixes #3867
closes #3868
2019-04-16 17:56:38 -04:00
김정환
b9b1b19758 tests: fix typos in descriptions
closes #3875
2019-04-16 12:40:59 -04:00
Louis
6f12eee8ab docs: fix typo in jsdoc comment
closes #3859
2019-04-16 10:29:07 -04:00
Ciro Santilli
186a206a0a docs: add listening address to example
closes #3873
2019-04-16 00:28:15 -04:00
Alvin Smith
02f3933b69 examples: minor fixes to some examples
closes #3812
2018-12-17 23:00:19 -05:00
Austin Scriver
0ae10bb154 docs: fix typos in history
closes #3810
2018-12-17 19:49:39 -05:00
HubCodes
95c31f7041 docs: fix typo in contributing
closes #3827
2018-12-17 19:12:37 -05:00
Horatiu Eugen Vlad
b93ffd4bdc Support multiple hosts in X-Forwarded-Host
fixes #3494
closes #3495
2018-10-28 15:58:25 -04:00
Joshua Caron
8da51108e7 Improve error message for null/undefined to res.status
closes #2795
closes #2797
closes #3111
2018-10-27 14:04:49 -04:00
void
6bcdfef6ad Improve error message for non-strings to res.sendFile
closes #3582
2018-10-27 02:27:15 -04:00
Felix Bünemann
44e539e1dc build: support Node.js 10.x
closes #3617
2018-10-27 01:28:11 -04:00
Nacim Goura
003459b795 build: support Node.js 9.x
closes #3617
2018-10-27 00:55:42 -04:00
Douglas Christopher Wilson
6295b45920 build: test against Node.js 11.x nightly 2018-10-27 00:50:58 -04:00
Douglas Christopher Wilson
a6b119d27a build: coveralls@2.12.0 2018-10-27 00:05:00 -04:00
Douglas Christopher Wilson
d0421ac7e1 tests: use supertest to perform assertions 2018-10-26 23:34:00 -04:00
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
194 changed files with 8429 additions and 1246 deletions

View File

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

8
.eslintrc.yml Normal file
View File

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

218
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,218 @@
name: ci
on:
- pull_request
- push
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
name:
- Node.js 0.10
- Node.js 0.12
- io.js 1.x
- io.js 2.x
- io.js 3.x
- Node.js 4.x
- Node.js 5.x
- Node.js 6.x
- Node.js 7.x
- Node.js 8.x
- Node.js 9.x
- Node.js 10.x
- Node.js 11.x
- Node.js 12.x
- Node.js 13.x
- Node.js 14.x
- Node.js 15.x
- Node.js 16.x
- Node.js 17.x
- Node.js 18.x
- Node.js 19.x
- Node.js 20.x
- Node.js 21.x
include:
- name: Node.js 0.10
node-version: "0.10"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
- name: Node.js 0.12
node-version: "0.12"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
- name: io.js 1.x
node-version: "1.8"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
- name: io.js 2.x
node-version: "2.5"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
- name: io.js 3.x
node-version: "3.3"
npm-i: mocha@3.5.3 nyc@10.3.2 supertest@2.0.0
- name: Node.js 4.x
node-version: "4.9"
npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2
- name: Node.js 5.x
node-version: "5.12"
npm-i: mocha@5.2.0 nyc@11.9.0 supertest@3.4.2
- name: Node.js 6.x
node-version: "6.17"
npm-i: mocha@6.2.2 nyc@14.1.1 supertest@3.4.2
- name: Node.js 7.x
node-version: "7.10"
npm-i: mocha@6.2.2 nyc@14.1.1 supertest@6.1.6
- name: Node.js 8.x
node-version: "8.17"
npm-i: mocha@7.2.0 nyc@14.1.1
- name: Node.js 9.x
node-version: "9.11"
npm-i: mocha@7.2.0 nyc@14.1.1
- name: Node.js 10.x
node-version: "10.24"
npm-i: mocha@8.4.0
- name: Node.js 11.x
node-version: "11.15"
npm-i: mocha@8.4.0
- name: Node.js 12.x
node-version: "12.22"
npm-i: mocha@9.2.2
- name: Node.js 13.x
node-version: "13.14"
npm-i: mocha@9.2.2
- name: Node.js 14.x
node-version: "14.20"
- name: Node.js 15.x
node-version: "15.14"
- name: Node.js 16.x
node-version: "16.20"
- name: Node.js 17.x
node-version: "17.9"
- name: Node.js 18.x
node-version: "18.19"
- name: Node.js 19.x
node-version: "19.9"
- name: Node.js 20.x
node-version: "20.11"
- name: Node.js 21.x
node-version: "21.6"
steps:
- uses: actions/checkout@v4
- name: Install Node.js ${{ matrix.node-version }}
shell: bash -eo pipefail -l {0}
run: |
nvm install --default ${{ matrix.node-version }}
dirname "$(nvm which ${{ matrix.node-version }})" >> "$GITHUB_PATH"
- name: Configure npm
run: |
npm config set loglevel error
if [[ "$(npm config get package-lock)" == "true" ]]; then
npm config set package-lock false
else
npm config set shrinkwrap false
fi
- name: Install npm module(s) ${{ matrix.npm-i }}
run: npm install --save-dev ${{ matrix.npm-i }}
if: matrix.npm-i != ''
- name: Remove non-test dependencies
run: npm rm --silent --save-dev connect-redis
- name: Setup Node.js version-specific dependencies
shell: bash
run: |
# eslint for linting
# - remove on Node.js < 12
if [[ "$(cut -d. -f1 <<< "${{ matrix.node-version }}")" -lt 12 ]]; then
node -pe 'Object.keys(require("./package").devDependencies).join("\n")' | \
grep -E '^eslint(-|$)' | \
sort -r | \
xargs -n1 npm rm --silent --save-dev
fi
- name: Install Node.js dependencies
run: npm install
- name: List environment
id: list_env
shell: bash
run: |
echo "node@$(node -v)"
echo "npm@$(npm -v)"
npm -s ls ||:
(npm -s ls --depth=0 ||:) | awk -F'[ @]' 'NR>1 && $2 { print $2 "=" $3 }' >> "$GITHUB_OUTPUT"
- name: Run tests
shell: bash
run: |
npm run test-ci
cp coverage/lcov.info "coverage/${{ matrix.name }}.lcov"
- name: Lint code
if: steps.list_env.outputs.eslint != ''
run: npm run lint
- name: Collect code coverage
run: |
mv ./coverage "./${{ matrix.name }}"
mkdir ./coverage
mv "./${{ matrix.name }}" "./coverage/${{ matrix.name }}"
- name: Upload code coverage
uses: actions/upload-artifact@v3
with:
name: coverage
path: ./coverage
retention-days: 1
coverage:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install lcov
shell: bash
run: sudo apt-get -y install lcov
- name: Collect coverage reports
uses: actions/download-artifact@v3
with:
name: coverage
path: ./coverage
- name: Merge coverage reports
shell: bash
run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./coverage/lcov.info
- name: Upload coverage report
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

21
.gitignore vendored
View File

@@ -1,26 +1,15 @@
# OS X
.DS_Store*
Icon?
._*
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# Linux
.directory
*~
# npm
node_modules
package-lock.json
*.log
*.gz
# Coveralls
.nyc_output
coverage
# Benchmarking
benchmarks/graphs
# ignore additional files using core.excludesFile
# https://git-scm.com/docs/gitignore

View File

@@ -1,33 +0,0 @@
language: node_js
node_js:
- "0.10"
- "0.12"
- "1.8"
- "2.5"
- "3.3"
- "4.8"
- "5.12"
- "6.11"
- "7.10"
matrix:
include:
- node_js: "8.0"
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
cache:
directories:
- node_modules
before_install:
# Remove all non-test dependencies
- "npm rm --save-dev connect-redis"
# Update Node.js modules
- "test ! -d node_modules || npm prune"
- "test ! -d node_modules || npm rebuild"
script:
- "npm run test-ci"
- "npm run lint"
after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls"

92
Charter.md Normal file
View File

@@ -0,0 +1,92 @@
# Express Charter
## Section 0: Guiding Principles
The Express project is part of the OpenJS Foundation which operates
transparently, openly, collaboratively, and ethically.
Project proposals, timelines, and status must not merely be open, but
also easily visible to outsiders.
## Section 1: Scope
Express is a HTTP web server framework with a simple and expressive API
which is highly aligned with Node.js core. We aim to be the best in
class for writing performant, spec compliant, and powerful web servers
in Node.js. As one of the oldest and most popular web frameworks in
the ecosystem, we have an important place for new users and experts
alike.
### 1.1: In-scope
Express is made of many modules spread between three GitHub Orgs:
- [expressjs](http://github.com/expressjs/): Top level middleware and
libraries
- [pillarjs](http://github.com/pillarjs/): Components which make up
Express but can also be used for other web frameworks
- [jshttp](http://github.com/jshttp/): Low level HTTP libraries
### 1.2: Out-of-Scope
Section Intentionally Left Blank
## Section 2: Relationship with OpenJS Foundation CPC.
Technical leadership for the projects within the OpenJS Foundation is
delegated to the projects through their project charters by the OpenJS
Cross Project Council (CPC). In the case of the Express project, it is
delegated to the Express Technical Committee ("TC").
This Technical Committee is in charge of both the day-to-day operations
of the project, as well as its technical management. This charter can
be amended by the TC requiring at least two approvals and a minimum two
week comment period for other TC members or CPC members to object. Any
changes the CPC wishes to propose will be considered a priority but
will follow the same process.
### 2.1 Other Formal Project Relationships
Section Intentionally Left Blank
## Section 3: Express Governing Body
The Express project is managed by the Technical Committee ("TC").
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.
## Section 4: Roles & Responsibilities
The Express TC manages all aspects of both the technical and community
parts of the project. Members of the TC should attend the regular
meetings when possible, and be available for discussion of time
sensitive or important issues.
### Section 4.1 Project Operations & Management
Section Intentionally Left Blank
### Section 4.2: Decision-making, Voting, and/or Elections
The Express 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.
### Section 4.3: Other Project Roles
Section Intentionally Left Blank
## Section 5: Definitions
Section Intentionally Left Blank

139
Code-Of-Conduct.md Normal file
View File

@@ -0,0 +1,139 @@
# Contributor Covenant Code of Conduct
As a member of the Open JS Foundation, Express has adopted the
[Contributor Covenant 2.0][cc-20-doc].
If an issue arises and you cannot resolve it directly with the parties
involved, you can report it to the Express project TC through the following
email: express-coc@lists.openjsf.org
In addition, the OpenJS Foundation maintains a Code of Conduct Panel (CoCP).
This is a foundation-wide team established to manage escalation when a reporter
believes that a report to a member project or the CPC has not been properly
handled. In order to escalate to the CoCP send an email to
coc-escalation@lists.openjsf.org.
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances
of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for
moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail
address, posting via an official social media account, or acting as an
appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
express-coc@lists.openjsf.org. All complaints will be reviewed and
investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited
interaction with those enforcing the Code of Conduct, is allowed during this
period. Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
project community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant, version 2.0](cc-20-doc).
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
[cc-20-doc]: https://www.contributor-covenant.org/version/2/0/code_of_conduct/
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,3 +1,4 @@
# Express Collaborator Guide
## Website Issues
@@ -21,7 +22,7 @@ a future release of Express.
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
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.

View File

@@ -12,14 +12,16 @@ contributors can be involved in decision making.
* 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 **Project Captain** is the lead maintainer of a repository.
* A **TC (Technical Committee)** is a group of committers representing the required technical
expertise to resolve rare disputes.
* A **Triager** is a subset of contributors who have been given triage access to the repository.
# Logging Issues
## 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.
exception is security disclosures 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.
@@ -27,7 +29,7 @@ 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
## 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
@@ -41,7 +43,7 @@ weekends and other holiday periods to ensure active committers all have reasonab
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
During a 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.
@@ -56,7 +58,36 @@ discuss pending contributions in order to find a resolution. It is expected that
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
## Becoming a Triager
Anyone can become a triager! Read more about the process of being a triager in
[the triage process document](Triager-Guide.md).
[Open an issue in `expressjs/express` repo](https://github.com/expressjs/express/issues/new)
to request the triage role. State that you have read and agree to the
[Code of Conduct](Code-Of-Conduct.md) and details of the role.
Here is an example issue content you can copy and paste:
```
Title: Request triager role for <your GitHub username>
I have read and understood the project's Code of Conduct.
I also have read and understood the process and best practices around Express triaging.
I request for a triager role for the following GitHub organizations:
jshttp
pillarjs
express
```
Once you have opened your issue, a member of the TC will add you to the `triage` team in
the organizations requested. They will then close the issue.
Happy triaging!
## 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.
@@ -64,7 +95,7 @@ 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
## 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.
@@ -72,14 +103,74 @@ If a consensus cannot be reached that has no objections then a majority wins vot
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
Resolution may involve returning the issue to project captains 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.
the discussion happening among the project captains.
Members can be added to the TC at any time. Any committer can nominate another committer
Members can be added to the TC at any time. Any TC member 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.
not to add this new member. The TC will consist of a minimum of 3 active members and a
maximum of 10. If the TC should drop below 5 members the active TC members should nominate
someone new. If a TC member is stepping down, they are encouraged (but not required) to
nominate someone to take their place.
TC members will be added as admin's on the Github orgs, npm orgs, and other resources as
necessary to be effective in the role.
To remain "active" a TC member should have participation within the last 12 months and miss
no more than six consecutive TC meetings. Our goal is to increase participation, not punish
people for any lack of participation, this guideline should be only be used as such
(replace an inactive member with a new active one, for example). Members who do not meet this
are expected to step down. If A TC member does not step down, an issue can be opened in the
discussions repo to move them to inactive status. TC members who step down or are removed due
to inactivity will be moved into inactive status.
Inactive status members can become active members by self nomination if the TC is not already
larger than the maximum of 10. They will also be given preference if, while at max size, an
active member steps down.
## Project Captains
The Express TC can designate captains for individual projects/repos in the
organizations. These captains are responsible for being the primary
day-to-day maintainers of the repo on a technical and community front.
Repo captains are empowered with repo ownership and package publication rights.
When there are conflicts, especially on topics that effect the Express project
at large, captains are responsible to raise it up to the TC and drive
those conflicts to resolution. Captains are also responsible for making sure
community members follow the community guidelines, maintaining the repo
and the published package, as well as in providing user support.
Like TC members, Repo captains are a subset of committers.
To become a captain for a project the candidate is expected to participate in that
project for at least 6 months as a committer prior to the request. They should have
helped with code contributions as well as triaging issues. They are also required to
have 2FA enabled on both their GitHub and npm accounts. Any TC member or existing
captain on the repo can nominate another committer to the captain role, submit a PR to
this doc, under `Current Project Captains` section (maintaining the sort order) with
the project, their GitHub handle and npm username (if different). The PR will require
at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or
dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups.
### Current Project Captains
- `expressjs/express`: @wesleytodd
- `expressjs/discussions`: @wesleytodd
- `expressjs/expressjs.com`: @crandmck
- `expressjs/body-parser`: @wesleytodd
- `expressjs/multer`: @LinusU
- `expressjs/cookie-parser`: @wesleytodd
- `expressjs/generator`: @wesleytodd
- `expressjs/statusboard`: @wesleytodd
- `pillarjs/path-to-regexp`: @blakeembrey
- `pillarjs/router`: @dougwilson, @wesleytodd
- `pillarjs/finalhandler`: @wesleytodd
- `pillarjs/request`: @wesleytodd
- `jshttp/http-errors`: @wesleytodd
- `jshttp/cookie`: @wesleytodd
- `jshttp/on-finished`: @wesleytodd
- `jshttp/forwarded`: @wesleytodd
- `jshttp/proxy-addr`: @wesleytodd

View File

@@ -1,3 +1,324 @@
4.19.1 / 2024-03-20
==========
* Allow passing non-strings to res.location with new encoding handling checks
4.19.0 / 2024-03-20
==========
* Prevent open redirect allow list bypass due to encodeurl
* deps: cookie@0.6.0
4.18.3 / 2024-02-29
==========
* Fix routing requests without method
* deps: body-parser@1.20.2
- Fix strict json error message on Node.js 19+
- deps: content-type@~1.0.5
- deps: raw-body@2.5.2
* deps: cookie@0.6.0
- Add `partitioned` option
4.18.2 / 2022-10-08
===================
* Fix regression routing a large stack in a single route
* deps: body-parser@1.20.1
- deps: qs@6.11.0
- perf: remove unnecessary object clone
* deps: qs@6.11.0
4.18.1 / 2022-04-29
===================
* Fix hanging on large stack of sync routes
4.18.0 / 2022-04-25
===================
* Add "root" option to `res.download`
* Allow `options` without `filename` in `res.download`
* Deprecate string and non-integer arguments to `res.status`
* Fix behavior of `null`/`undefined` as `maxAge` in `res.cookie`
* Fix handling very large stacks of sync middleware
* Ignore `Object.prototype` values in settings through `app.set`/`app.get`
* Invoke `default` with same arguments as types in `res.format`
* Support proper 205 responses using `res.send`
* Use `http-errors` for `res.format` error
* deps: body-parser@1.20.0
- Fix error message for json parse whitespace in `strict`
- Fix internal error when inflated body exceeds limit
- Prevent loss of async hooks context
- Prevent hanging when request already read
- deps: depd@2.0.0
- deps: http-errors@2.0.0
- deps: on-finished@2.4.1
- deps: qs@6.10.3
- deps: raw-body@2.5.1
* deps: cookie@0.5.0
- Add `priority` option
- Fix `expires` option to reject invalid dates
* deps: depd@2.0.0
- Replace internal `eval` usage with `Function` constructor
- Use instance methods on `process` to check for listeners
* deps: finalhandler@1.2.0
- Remove set content headers that break response
- deps: on-finished@2.4.1
- deps: statuses@2.0.1
* deps: on-finished@2.4.1
- Prevent loss of async hooks context
* deps: qs@6.10.3
* deps: send@0.18.0
- Fix emitted 416 error missing headers property
- Limit the headers removed for 304 response
- deps: depd@2.0.0
- deps: destroy@1.2.0
- deps: http-errors@2.0.0
- deps: on-finished@2.4.1
- deps: statuses@2.0.1
* deps: serve-static@1.15.0
- deps: send@0.18.0
* deps: statuses@2.0.1
- Remove code 306
- Rename `425 Unordered Collection` to standard `425 Too Early`
4.17.3 / 2022-02-16
===================
* deps: accepts@~1.3.8
- deps: mime-types@~2.1.34
- deps: negotiator@0.6.3
* deps: body-parser@1.19.2
- deps: bytes@3.1.2
- deps: qs@6.9.7
- deps: raw-body@2.4.3
* deps: cookie@0.4.2
* deps: qs@6.9.7
* Fix handling of `__proto__` keys
* pref: remove unnecessary regexp for trust proxy
4.17.2 / 2021-12-16
===================
* Fix handling of `undefined` in `res.jsonp`
* Fix handling of `undefined` when `"json escape"` is enabled
* Fix incorrect middleware execution with unanchored `RegExp`s
* Fix `res.jsonp(obj, status)` deprecation message
* Fix typo in `res.is` JSDoc
* deps: body-parser@1.19.1
- deps: bytes@3.1.1
- deps: http-errors@1.8.1
- deps: qs@6.9.6
- deps: raw-body@2.4.2
- deps: safe-buffer@5.2.1
- deps: type-is@~1.6.18
* deps: content-disposition@0.5.4
- deps: safe-buffer@5.2.1
* deps: cookie@0.4.1
- Fix `maxAge` option to reject invalid values
* deps: proxy-addr@~2.0.7
- Use `req.socket` over deprecated `req.connection`
- deps: forwarded@0.2.0
- deps: ipaddr.js@1.9.1
* deps: qs@6.9.6
* deps: safe-buffer@5.2.1
* deps: send@0.17.2
- deps: http-errors@1.8.1
- deps: ms@2.1.3
- pref: ignore empty http tokens
* deps: serve-static@1.14.2
- deps: send@0.17.2
* deps: setprototypeof@1.2.0
4.17.1 / 2019-05-25
===================
* Revert "Improve error message for `null`/`undefined` to `res.status`"
4.17.0 / 2019-05-16
===================
* Add `express.raw` to parse bodies into `Buffer`
* Add `express.text` to parse bodies into string
* Improve error message for non-strings to `res.sendFile`
* Improve error message for `null`/`undefined` to `res.status`
* Support multiple hosts in `X-Forwarded-Host`
* deps: accepts@~1.3.7
* deps: body-parser@1.19.0
- Add encoding MIK
- Add petabyte (`pb`) support
- Fix parsing array brackets after index
- deps: bytes@3.1.0
- deps: http-errors@1.7.2
- deps: iconv-lite@0.4.24
- deps: qs@6.7.0
- deps: raw-body@2.4.0
- deps: type-is@~1.6.17
* deps: content-disposition@0.5.3
* deps: cookie@0.4.0
- Add `SameSite=None` support
* deps: finalhandler@~1.1.2
- Set stricter `Content-Security-Policy` header
- deps: parseurl@~1.3.3
- deps: statuses@~1.5.0
* deps: parseurl@~1.3.3
* deps: proxy-addr@~2.0.5
- deps: ipaddr.js@1.9.0
* deps: qs@6.7.0
- Fix parsing array brackets after index
* deps: range-parser@~1.2.1
* deps: send@0.17.1
- Set stricter CSP header in redirect & error responses
- deps: http-errors@~1.7.2
- deps: mime@1.6.0
- deps: ms@2.1.1
- deps: range-parser@~1.2.1
- deps: statuses@~1.5.0
- perf: remove redundant `path.normalize` call
* deps: serve-static@1.14.1
- Set stricter CSP header in redirect response
- deps: parseurl@~1.3.3
- deps: send@0.17.1
* deps: setprototypeof@1.1.1
* deps: statuses@~1.5.0
- Add `103 Early Hints`
* deps: type-is@~1.6.18
- deps: mime-types@~2.1.24
- perf: prevent internal `throw` on invalid type
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
===================
@@ -162,7 +483,7 @@
- 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
- Many performance improvements
- deps: mime-types@~2.1.11
- deps: negotiator@0.6.1
* deps: content-type@~1.0.2
@@ -177,7 +498,7 @@
- perf: enable strict mode
- perf: hoist regular expression
- perf: use for loop in parse
- perf: use string concatination for serialization
- perf: use string concatenation for serialization
* deps: finalhandler@0.5.0
- Change invalid or non-numeric status code to 500
- Overwrite status message to match set status code
@@ -187,7 +508,7 @@
* deps: proxy-addr@~1.1.2
- Fix accepting various invalid netmasks
- Fix IPv6-mapped IPv4 validation edge cases
- IPv4 netmasks must be contingous
- IPv4 netmasks must be contiguous
- IPv6 addresses cannot be used as a netmask
- deps: ipaddr.js@1.1.1
* deps: qs@6.2.0
@@ -965,13 +1286,13 @@
- deps: negotiator@0.4.6
* deps: debug@1.0.2
* deps: send@0.4.3
- Do not throw un-catchable error on file open race condition
- Do not throw uncatchable error on file open race condition
- Use `escape-html` for HTML escaping
- deps: debug@1.0.2
- deps: finished@1.2.2
- deps: fresh@0.2.2
* deps: serve-static@1.2.3
- Do not throw un-catchable error on file open race condition
- Do not throw uncatchable error on file open race condition
- deps: send@0.4.3
4.4.2 / 2014-06-09
@@ -1812,7 +2133,7 @@
* deps: connect@2.21.0
- deprecate `connect(middleware)` -- use `app.use(middleware)` instead
- deprecate `connect.createServer()` -- use `connect()` instead
- fix `res.setHeader()` patch to work with with get -> append -> set pattern
- fix `res.setHeader()` patch to work with get -> append -> set pattern
- deps: compression@~1.0.8
- deps: errorhandler@~1.1.1
- deps: express-session@~1.5.0
@@ -1851,7 +2172,7 @@
- deps: serve-static@1.2.3
* deps: debug@1.0.2
* deps: send@0.4.3
- Do not throw un-catchable error on file open race condition
- Do not throw uncatchable error on file open race condition
- Use `escape-html` for HTML escaping
- deps: debug@1.0.2
- deps: finished@1.2.2
@@ -3023,8 +3344,8 @@ Shaw]
* Added node v0.1.97 compatibility
* Added support for deleting cookies via Request#cookie('key', null)
* Updated haml submodule
* Fixed not-found page, now using using charset utf-8
* Fixed show-exceptions page, now using using charset utf-8
* Fixed not-found page, now using charset utf-8
* Fixed show-exceptions page, now using charset utf-8
* Fixed view support due to fs.readFile Buffers
* Changed; mime.type() no longer accepts ".type" due to node extname() changes
@@ -3036,7 +3357,7 @@ Shaw]
* Updated haml submodule
* Changed ETag; removed inode, modified time only
* Fixed LF to CRLF for setting multiple cookies
* Fixed cookie complation; values are now urlencoded
* Fixed cookie compilation; values are now urlencoded
* Fixed cookies parsing; accepts quoted values and url escaped cookies
0.11.0 / 2010-05-06
@@ -3059,7 +3380,7 @@ Shaw]
==================
* Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s
encoding is set to 'utf8' or 'utf-8'.
encoding is set to 'utf8' or 'utf-8').
* Added "encoding" option to Request#render(). Closes #299
* Added "dump exceptions" setting, which is enabled by default.
* Added simple ejs template engine support
@@ -3098,7 +3419,7 @@ Shaw]
* Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js
* Added callback function support to Request#halt() as 3rd/4th arg
* Added preprocessing of route param wildcards using param(). Closes #251
* Added view partial support (with collections etc)
* Added view partial support (with collections etc.)
* Fixed bug preventing falsey params (such as ?page=0). Closes #286
* Fixed setting of multiple cookies. Closes #199
* Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
@@ -3231,7 +3552,7 @@ Shaw]
* Added "plot" format option for Profiler (for gnuplot processing)
* Added request number to Profiler plugin
* Fixed binary encoding for multi-part file uploads, was previously defaulting to UTF8
* Fixed binary encoding for multipart file uploads, was previously defaulting to UTF8
* Fixed issue with routes not firing when not files are present. Closes #184
* Fixed process.Promise -> events.Promise
@@ -3277,7 +3598,7 @@ Shaw]
* Updated sample chat app to show messages on load
* Updated libxmljs parseString -> parseHtmlString
* Fixed `make init` to work with older versions of git
* Fixed specs can now run independent specs for those who cant build deps. Closes #127
* Fixed specs can now run independent specs for those who can't build deps. Closes #127
* Fixed issues introduced by the node url module changes. Closes 126.
* Fixed two assertions failing due to Collection#keys() returning strings
* Fixed faulty Collection#toArray() spec due to keys() returning strings

103
Readme.md
View File

@@ -1,16 +1,14 @@
[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/)
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
Fast, unopinionated, minimalist web framework for [Node.js](http://nodejs.org).
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Linux Build][travis-image]][travis-url]
[![Windows Build][appveyor-image]][appveyor-url]
[![Test Coverage][coveralls-image]][coveralls-url]
[![NPM Version][npm-version-image]][npm-url]
[![NPM Install Size][npm-install-size-image]][npm-install-size-url]
[![NPM Downloads][npm-downloads-image]][npm-downloads-url]
```js
var express = require('express')
var app = express()
const express = require('express')
const app = express()
app.get('/', function (req, res) {
res.send('Hello World')
@@ -21,10 +19,25 @@ app.listen(3000)
## Installation
```bash
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.
If this is a brand new project, make sure to create a `package.json` first with
the [`npm init` command](https://docs.npmjs.com/creating-a-package-json-file).
Installation is done using the
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
```console
$ npm install express
```
Follow [our installing guide](http://expressjs.com/en/starter/installing.html)
for more information.
## Features
* Robust routing
@@ -38,7 +51,7 @@ $ npm install express
## Docs & Community
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
* [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
* [#express](https://web.libera.chat/#express) on [Libera Chat](https://libera.chat) IRC
* [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
@@ -46,42 +59,40 @@ $ npm install express
**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
The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below:
Install the executable. The executable's major version will match Express's:
```bash
```console
$ npm install -g express-generator@4
```
Create the app:
```bash
```console
$ express /tmp/foo && cd /tmp/foo
```
Install dependencies:
```bash
```console
$ npm install
```
Start the server:
```bash
```console
$ npm start
```
View the website at: http://localhost:3000
## Philosophy
The Express philosophy is to provide small, robust tooling for HTTP servers, making
it a great solution for single page applications, web sites, hybrids, or public
it a great solution for single page applications, websites, hybrids, or public
HTTP APIs.
Express does not force you to use any specific ORM or template engine. With support for over
@@ -92,32 +103,48 @@ $ npm start
To view the examples, clone the Express repo and install the dependencies:
```bash
$ git clone git://github.com/expressjs/express.git --depth 1
```console
$ git clone https://github.com/expressjs/express.git --depth 1
$ cd express
$ npm install
```
Then run whichever example you want:
```bash
```console
$ node examples/content-negotiation
```
## Tests
## Contributing
To run the test suite, first install the dependencies, then run `npm test`:
[![Linux Build][github-actions-ci-image]][github-actions-ci-url]
[![Windows Build][appveyor-image]][appveyor-url]
[![Test Coverage][coveralls-image]][coveralls-url]
```bash
The Express.js project welcomes all constructive contributions. Contributions take many forms,
from code for bug fixes and enhancements, to additions and fixes to documentation, additional
tests, triaging incoming pull requests and issues, and more!
See the [Contributing Guide](Contributing.md) for more technical details on contributing.
### Security Issues
If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
### Running Tests
To run the test suite, first install the dependencies, then run `npm test`:
```console
$ npm install
$ 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/expressjs/express/graphs/contributors)
@@ -125,17 +152,15 @@ The current lead maintainer is [Douglas Christopher Wilson](https://github.com/d
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/express.svg
[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/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-image]: https://badgen.net/appveyor/ci/dougwilson/express/master?label=windows
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express
[coveralls-image]: https://img.shields.io/coveralls/expressjs/express/master.svg
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master
[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
[gratipay-url-dougwilson]: https://gratipay.com/dougwilson/
[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/master?label=linux
[github-actions-ci-url]: https://github.com/expressjs/express/actions/workflows/ci.yml
[npm-downloads-image]: https://badgen.net/npm/dm/express
[npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true
[npm-install-size-image]: https://badgen.net/packagephobia/install/express
[npm-install-size-url]: https://packagephobia.com/result?p=express
[npm-url]: https://npmjs.org/package/express
[npm-version-image]: https://badgen.net/npm/v/express

View File

@@ -184,3 +184,9 @@ $ npm publish
**NOTE:** The version number to publish will be picked up automatically from
package.json.
### Step 7. Update documentation website
The documentation website https://expressjs.com/ documents the current release version in various places. For a new release:
1. Change the value of `current_version` in https://github.com/expressjs/expressjs.com/blob/gh-pages/_data/express.yml to match the latest version number.
2. Add a new section to the change log. For example, for a 4.x release, https://github.com/expressjs/expressjs.com/blob/gh-pages/en/changelog/4x.md,

View File

@@ -16,6 +16,10 @@ contributions.
Report security bugs by emailing the lead maintainer in the Readme.md file.
To ensure the timely response to your report, please ensure that the entirety
of the report is contained within the email body and not solely behind a web
link or an attachment.
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
@@ -23,8 +27,7 @@ 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).
the module.
## Disclosure Policy

63
Triager-Guide.md Normal file
View File

@@ -0,0 +1,63 @@
# Express Triager Guide
## Issue Triage Process
When a new issue or pull request is opened the issue will be labeled with `needs triage`.
If a triage team member is available they can help make sure all the required information
is provided. Depending on the issue or PR there are several next labels they can add for further
classification:
* `needs triage`: This can be kept if the triager is unsure which next steps to take
* `awaiting more info`: If more info has been requested from the author, apply this label.
* `question`: User questions that do not appear to be bugs or enhancements.
* `discuss`: Topics for discussion. Might end in an `enhancement` or `question` label.
* `bug`: Issues that present a reasonable conviction there is a reproducible bug.
* `enhancement`: Issues that are found to be a reasonable candidate feature additions.
In all cases, issues may be closed by maintainers if they don't receive a timely response when
further information is sought, or when additional questions are asked.
## Approaches and Best Practices for getting into triage contributions
Review the organization's [StatusBoard](https://expressjs.github.io/statusboard/),
pay special attention to these columns: stars, watchers, open issues, and contributors.
This gives you a general idea about the criticality and health of the repository.
Pick a few projects based on that criteria, your interests, and skills (existing or aspiring).
Review the project's contribution guideline if present. In a nutshell,
commit to the community's standards and values. Review the
documentation, for most of the projects it is just the README.md, and
make sure you understand the key APIs, semantics, configurations, and use cases.
It might be helpful to write your own test apps to re-affirm your
understanding of the key functions. This may identify some gaps in
documentation, record those as they might be good PR's to open.
Skim through the issue backlog; identify low hanging issues and mostly new ones.
From those, attempt to recreate issues based on the OP description and
ask questions if required. No question is a bad question!
## Removal of Triage Role
There are a few cases where members can be removed as triagers:
- Breaking the CoC or project contributor guidelines
- Abuse or misuse of the role as deemed by the TC
- Lack of participation for more than 6 months
If any of these happen we will discuss as a part of the triage portion of the regular TC meetings.
If you have questions feel free to reach out to any of the TC members.
## Other Helpful Hints:
- Everyone is welcome to attend the [Express Technical Committee Meetings](https://github.com/expressjs/discussions#expressjs-tc-meetings), and as a triager, it might help to get a better idea of what's happening with the project.
- When exploring the module's functionality there are a few helpful steps:
- Turn on `DEBUG=*` (see https://www.npmjs.com/package/debug) to get detailed log information
- It is also a good idea to do live debugging to follow the control flow, try using `node --inspect`
- It is a good idea to make at least one pass of reading through the entire source
- When reviewing the list of open issues there are some common types and suggested actions:
- New/unattended issues or simple questions: A good place to start
- Hard bugs & ongoing discussions: always feel free to chime in and help
- Issues that imply gaps in the documentation: open PRs with changes or help the user to do so
- For recurring issues, it is helpful to create functional examples to demonstrate (publish as gists or a repo)
- Review and identify the maintainers. If necessary, at-mention one or more of them if you are unsure what to do
- Make sure all your interactions are professional, welcoming, and respectful to the parties involved.

View File

@@ -5,22 +5,108 @@ environment:
- nodejs_version: "1.8"
- nodejs_version: "2.5"
- nodejs_version: "3.3"
- nodejs_version: "4.8"
- nodejs_version: "4.9"
- nodejs_version: "5.12"
- nodejs_version: "6.11"
- nodejs_version: "6.17"
- nodejs_version: "7.10"
- nodejs_version: "8.17"
- nodejs_version: "9.11"
- nodejs_version: "10.24"
- nodejs_version: "11.15"
- nodejs_version: "12.22"
- nodejs_version: "13.14"
- nodejs_version: "14.20"
- nodejs_version: "15.14"
- nodejs_version: "16.20"
- nodejs_version: "17.9"
- nodejs_version: "18.19"
- nodejs_version: "19.9"
- nodejs_version: "20.11"
- nodejs_version: "21.6"
cache:
- node_modules
install:
- ps: Install-Product node $env:nodejs_version
- npm rm --save-dev connect-redis
- if exist node_modules npm prune
- if exist node_modules npm rebuild
# Install Node.js
- ps: >-
try { Install-Product node $env:nodejs_version -ErrorAction Stop }
catch { Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) x64 }
# Configure npm
- ps: |
npm config set loglevel error
if ((npm config get package-lock) -eq "true") {
npm config set package-lock false
} else {
npm config set shrinkwrap false
}
# Remove all non-test dependencies
- ps: |
# Remove example dependencies
npm rm --silent --save-dev connect-redis
# Remove lint dependencies
cmd.exe /c "node -pe `"Object.keys(require('./package').devDependencies).join('\n')`"" | `
sls "^eslint(-|$)" | `
%{ npm rm --silent --save-dev $_ }
# Setup Node.js version-specific dependencies
- ps: |
# mocha for testing
# - use 3.x for Node.js < 4
# - use 5.x for Node.js < 6
# - use 6.x for Node.js < 8
# - use 7.x for Node.js < 10
# - use 8.x for Node.js < 12
# - use 9.x for Node.js < 14
if ([int]$env:nodejs_version.split(".")[0] -lt 4) {
npm install --silent --save-dev mocha@3.5.3
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) {
npm install --silent --save-dev mocha@5.2.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 8) {
npm install --silent --save-dev mocha@6.2.2
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 10) {
npm install --silent --save-dev mocha@7.2.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 12) {
npm install --silent --save-dev mocha@8.4.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 14) {
npm install --silent --save-dev mocha@9.2.2
}
- ps: |
# nyc for test coverage
# - use 10.3.2 for Node.js < 4
# - use 11.9.0 for Node.js < 6
# - use 14.1.1 for Node.js < 10
if ([int]$env:nodejs_version.split(".")[0] -lt 4) {
npm install --silent --save-dev nyc@10.3.2
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 6) {
npm install --silent --save-dev nyc@11.9.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 10) {
npm install --silent --save-dev nyc@14.1.1
}
- ps: |
# supertest for http calls
# - use 2.0.0 for Node.js < 4
# - use 3.4.2 for Node.js < 7
# - use 6.1.6 for Node.js < 8
if ([int]$env:nodejs_version.split(".")[0] -lt 4) {
npm install --silent --save-dev supertest@2.0.0
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 7) {
npm install --silent --save-dev supertest@3.4.2
} elseif ([int]$env:nodejs_version.split(".")[0] -lt 8) {
npm install --silent --save-dev supertest@6.1.6
}
# 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
- npm run lint
version: "{build}"

View File

@@ -1,13 +1,17 @@
all:
@./run 1 middleware
@./run 5 middleware
@./run 10 middleware
@./run 15 middleware
@./run 20 middleware
@./run 30 middleware
@./run 50 middleware
@./run 100 middleware
@./run 1 middleware 50
@./run 5 middleware 50
@./run 10 middleware 50
@./run 15 middleware 50
@./run 20 middleware 50
@./run 30 middleware 50
@./run 50 middleware 50
@./run 100 middleware 50
@./run 10 middleware 100
@./run 10 middleware 250
@./run 10 middleware 500
@./run 10 middleware 1000
@echo
.PHONY: all

34
benchmarks/README.md Normal file
View File

@@ -0,0 +1,34 @@
# Express Benchmarks
## Installation
You will need to install [wrk](https://github.com/wg/wrk/blob/master/INSTALL) in order to run the benchmarks.
## Running
To run the benchmarks, first install the dependencies `npm i`, then run `make`
The output will look something like this:
```
50 connections
1 middleware
7.15ms
6784.01
[...redacted...]
1000 connections
10 middleware
139.21ms
6155.19
```
### Tip: Include Node.js version in output
You can use `make && node -v` to include the node.js version in the output.
### Tip: Save the results to a file
You can use `make > results.log` to save the results to a file `results.log`.

View File

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

View File

@@ -4,13 +4,15 @@ echo
MW=$1 node $2 &
pid=$!
echo " $3 connections"
sleep 2
wrk 'http://localhost:3333/?foo[bar]=baz' \
-d 3 \
-c 50 \
-c $3 \
-t 8 \
| grep 'Requests/sec' \
| awk '{ print " " $2 }'
| grep 'Requests/sec\|Latency' \
| awk '{ print " " $2 }'
kill $pid

29
examples/README.md Normal file
View File

@@ -0,0 +1,29 @@
# Express examples
This page contains list of examples using Express.
- [auth](./auth) - Authentication with login and password
- [content-negotiation](./content-negotiation) - HTTP content negotiation
- [cookie-sessions](./cookie-sessions) - Working with cookie-based sessions
- [cookies](./cookies) - Working with cookies
- [downloads](./downloads) - Transferring files to client
- [ejs](./ejs) - Working with Embedded JavaScript templating (ejs)
- [error-pages](./error-pages) - Creating error pages
- [error](./error) - Working with error middleware
- [hello-world](./hello-world) - Simple request handler
- [markdown](./markdown) - Markdown as template engine
- [multi-router](./multi-router) - Working with multiple Express routers
- [mvc](./mvc) - MVC-style controllers
- [online](./online) - Tracking online user activity with `online` and `redis` packages
- [params](./params) - Working with route parameters
- [resource](./resource) - Multiple HTTP operations on the same resource
- [route-map](./route-map) - Organizing routes using a map
- [route-middleware](./route-middleware) - Working with route middleware
- [route-separation](./route-separation) - Organizing routes per each resource
- [search](./search) - Search API
- [session](./session) - User sessions
- [static-files](./static-files) - Serving static files
- [vhost](./vhost) - Working with virtual hosts
- [view-constructor](./view-constructor) - Rendering views dynamically
- [view-locals](./view-locals) - Saving data in request object between middleware calls
- [web-service](./web-service) - Simple API service

View File

@@ -1,9 +1,10 @@
'use strict'
/**
* Module dependencies.
*/
var express = require('../..');
var bodyParser = require('body-parser');
var hash = require('pbkdf2-password')()
var path = require('path');
var session = require('express-session');
@@ -17,7 +18,7 @@ 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
@@ -60,14 +61,14 @@ function authenticate(name, pass, fn) {
if (!module.parent) console.log('authenticating %s:%s', name, pass);
var user = users[name];
// query the db for the given username
if (!user) return fn(new Error('cannot find user'));
if (!user) return fn(null, null)
// 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({ password: pass, salt: user.salt }, function (err, pass, salt, hash) {
if (err) return fn(err);
if (hash == user.hash) return fn(null, user);
fn(new Error('invalid password'));
if (hash === user.hash) return fn(null, user)
fn(null, null)
});
}
@@ -100,8 +101,9 @@ app.get('/login', function(req, res){
res.render('login');
});
app.post('/login', function(req, res){
app.post('/login', function (req, res, next) {
authenticate(req.body.username, req.body.password, function(err, user){
if (err) return next(err)
if (user) {
// Regenerate session when signing in
// to prevent fixation

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><%= title %></title>
<style>
body {

View File

@@ -1,22 +1,21 @@
<% var title = 'Authentication Example' %>
<% include head %>
<%- include('head', { title: 'Authentication Example' }) -%>
<h1>Login</h1>
<%- message %>
Try accessing <a href="/restricted">/restricted</a>, then authenticate with "tj" and "foobar".
<form method="post" action="/login">
<p>
<label>Username:</label>
<input type="text" name="username">
<label for="username">Username:</label>
<input type="text" name="username" id="username">
</p>
<p>
<label>Password:</label>
<input type="text" name="password">
<label for="password">Password:</label>
<input type="text" name="password" id="password">
</p>
<p>
<input type="submit" value="Login">
</p>
</form>
<% include foot %>
<%- include('foot') -%>

View File

@@ -1,3 +1,5 @@
'use strict'
var users = [];
users.push({ name: 'Tobi' });

View File

@@ -1,3 +1,5 @@
'use strict'
var express = require('../../');
var app = module.exports = express();
var users = require('./db');

View File

@@ -1,3 +1,4 @@
'use strict'
var users = require('./db');

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -11,13 +13,10 @@ var app = module.exports = express();
app.use(cookieSession({ secret: 'manny is cool' }));
// do something with the session
app.use(count);
// custom middleware
function count(req, res) {
app.get('/', function (req, res) {
req.session.count = (req.session.count || 0) + 1
res.send('viewed ' + req.session.count + ' times\n')
}
})
/* istanbul ignore next */
if (!module.parent) {

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -6,10 +8,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 +19,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

@@ -0,0 +1,3 @@
* milk
* eggs
* bread

View File

@@ -1,27 +1,32 @@
'use strict'
/**
* Module dependencies.
*/
var express = require('../../');
var path = require('path');
var app = module.exports = express();
// path to where the files are stored on disk
var FILES_DIR = path.join(__dirname, 'files')
app.get('/', function(req, res){
res.send('<ul>'
+ '<li>Download <a href="/files/amazing.txt">amazing.txt</a>.</li>'
+ '<li>Download <a href="/files/missing.txt">missing.txt</a>.</li>'
+ '<li>Download <a href="/files/CCTV大赛上海分赛区.txt">CCTV大赛上海分赛区.txt</a>.</li>'
+ '</ul>');
res.send('<ul>' +
'<li>Download <a href="/files/notes/groceries.txt">notes/groceries.txt</a>.</li>' +
'<li>Download <a href="/files/amazing.txt">amazing.txt</a>.</li>' +
'<li>Download <a href="/files/missing.txt">missing.txt</a>.</li>' +
'<li>Download <a href="/files/CCTV大赛上海分赛区.txt">CCTV大赛上海分赛区.txt</a>.</li>' +
'</ul>')
});
// /files/* is accessed via req.params[0]
// but here we name it :file
app.get('/files/:file(*)', function(req, res, next){
var filePath = path.join(__dirname, 'files', req.params.file);
res.download(filePath, function (err) {
res.download(req.params.file, { root: FILES_DIR }, function (err) {
if (!err) return; // file sent
if (err && err.status !== 404) return next(err); // non-404 error
if (err.status !== 404) return next(err); // non-404 error
// file for download not found
res.statusCode = 404;
res.send('Cant find that file, sorry!');

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,4 +1,4 @@
body {
padding: 50px 80px;
font: 14px "Helvetica Nueue", "Lucida Grande", Arial, sans-serif;
font: 14px "Helvetica Neue", "Lucida Grande", Arial, sans-serif;
}

View File

@@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><%= title %></title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>

View File

@@ -1,4 +1,4 @@
<% include header.html %>
<%- include('header.html') -%>
<h1>Users</h1>
<ul id="users">
@@ -7,4 +7,4 @@
<% }) %>
</ul>
<% include footer.html %>
<%- include('footer.html') -%>

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -6,7 +8,7 @@ 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', path.join(__dirname, 'views'));
@@ -19,7 +21,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'));

View File

@@ -1,3 +1,3 @@
<% include error_header %>
<%- include('error_header') -%>
<h2>Cannot find <%= url %></h2>
<% include footer %>
<%- include('footer') -%>

View File

@@ -1,8 +1,8 @@
<% include error_header %>
<%- include('error_header') -%>
<h2>Error: <%= error.message %></h2>
<% if (settings['verbose errors']) { %>
<pre><%= error.stack %></pre>
<% } else { %>
<p>An error occurred!</p>
<% } %>
<% include footer %>
<%- include('footer') -%>

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Error</title>
</head>

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Custom Pages Example</title>
</head>

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -5,7 +7,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'));
@@ -24,7 +26,7 @@ function error(err, req, res, next) {
res.send('Internal Server Error');
}
app.get('/', function(req, res){
app.get('/', function () {
// Caught and passed down to the errorHandler middleware
throw new Error('something broke!');
});

View File

@@ -1,6 +1,8 @@
'use strict'
var express = require('../../');
var app = express();
var app = module.exports = express()
app.get('/', function(req, res){
res.send('Hello World');

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -24,7 +26,7 @@ app.engine('md', function(path, options, fn){
app.set('views', path.join(__dirname, 'views'));
// make it the default so we dont need .md
// make it the default, so we don't need .md
app.set('view engine', 'md');
app.get('/', function(req, res){

View File

@@ -1,3 +1,5 @@
'use strict'
var express = require('../../..');
var apiv1 = express.Router();

View File

@@ -1,3 +1,5 @@
'use strict'
var express = require('../../..');
var apiv2 = express.Router();

View File

@@ -1,3 +1,5 @@
'use strict'
var express = require('../..');
var app = module.exports = express();
@@ -6,7 +8,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,60 +0,0 @@
/**
* Module dependencies.
*/
var express = require('../..');
var multiparty = require('multiparty');
var format = require('util').format;
var app = module.exports = express();
app.get('/', function(req, res){
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Title: <input type="text" name="title" /></p>'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', function(req, res, next){
// create a form to begin parsing
var form = new multiparty.Form();
var image;
var title;
form.on('error', next);
form.on('close', function(){
res.send(format('\nuploaded %s (%d Kb) as %s'
, image.filename
, image.size / 1024 | 0
, title));
});
// listen on field event for title
form.on('field', function(name, val){
if (name !== 'title') return;
title = val;
});
// listen on part event for image file
form.on('part', function(part){
if (!part.filename) return;
if (part.name !== 'image') return part.resume();
image = {};
image.filename = part.filename;
image.size = 0;
part.on('data', function(buf){
image.size += buf.length;
});
});
// parse the form
form.parse(req);
});
/* istanbul ignore next */
if (!module.parent) {
app.listen(4000);
console.log('Express started on port 4000');
}

View File

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

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/style.css">
<title>Edit <%= pet.name %></title>
</head>

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/style.css">
<title><%= pet.name %></title>
</head>

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/style.css">
<title>Edit {{user.name}}</title>
</head>

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/style.css">
<title>Users</title>
</head>

View File

@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="/style.css">
<title>{{user.name}}</title>
</head>

View File

@@ -1,3 +1,5 @@
'use strict'
// faux database
var pets = exports.pets = [];

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -6,7 +8,6 @@ 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();
@@ -43,7 +44,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

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,6 +1,6 @@
body {
padding: 50px;
font: 16px "Helvetica Neue", Helvetica, Arial;
font: 16px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
a {
color: #107aff;

View File

@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Not Found</title>
<link rel="stylesheet" href="/style.css">
</head>

View File

@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Internal Server Error</title>
<link rel="stylesheet" href="/style.css">
</head>

View File

@@ -1,3 +1,4 @@
'use strict'
// install redis first:
// https://redis.io/

View File

@@ -1,28 +1,23 @@
'use strict'
/**
* Module dependencies.
*/
var createError = require('http-errors')
var express = require('../../');
var app = module.exports = express();
// Faux database
var users = [
{ name: 'tj' }
{ name: 'tj' }
, { name: 'tobi' }
, { name: 'loki' }
, { name: 'jane' }
, { name: 'bandit' }
];
// Create HTTP error
function createError(status, message) {
var err = new Error(message);
err.status = status;
return err;
}
// Convert :to and :from to integers
app.param(['to', 'from'], function(req, res, next, num, name){
@@ -56,7 +51,7 @@ app.get('/', function(req, res){
* GET :user.
*/
app.get('/user/:user', function(req, res, next){
app.get('/user/:user', function (req, res) {
res.send('user ' + req.user.name);
});
@@ -64,7 +59,7 @@ app.get('/user/:user', function(req, res, next){
* GET users :from - :to.
*/
app.get('/users/:from-:to', function(req, res, next){
app.get('/users/:from-:to', function (req, res) {
var from = req.params.from;
var to = req.params.to;
var names = users.map(function(user){ return user.name; });

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -26,7 +28,7 @@ app.resource = function(path, obj) {
// Fake records
var users = [
{ name: 'tj' }
{ name: 'tj' }
, { name: 'ciaran' }
, { name: 'aaron' }
, { name: 'guillermo' }

View File

@@ -1,10 +1,13 @@
'use strict'
/**
* Module dependencies.
*/
var escapeHtml = require('escape-html')
var express = require('../../lib/express');
var verbose = process.env.NODE_ENV != 'test';
var verbose = process.env.NODE_ENV !== 'test'
var app = module.exports = express();
@@ -31,7 +34,7 @@ var users = {
},
get: function(req, res){
res.send('user ' + req.params.uid);
res.send('user ' + escapeHtml(req.params.uid))
},
delete: function(req, res){
@@ -41,11 +44,11 @@ var users = {
var pets = {
list: function(req, res){
res.send('user ' + req.params.uid + '\'s pets');
res.send('user ' + escapeHtml(req.params.uid) + '\'s pets')
},
delete: function(req, res){
res.send('delete ' + req.params.uid + '\'s pet ' + req.params.pid);
res.send('delete ' + escapeHtml(req.params.uid) + '\'s pet ' + escapeHtml(req.params.pid))
}
};

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -15,7 +17,7 @@ var app = express();
// Dummy users
var users = [
{ id: 0, name: 'tj', email: 'tj@vision-media.ca', role: 'member' }
{ id: 0, name: 'tj', email: 'tj@vision-media.ca', role: 'member' }
, { id: 1, name: 'ciaran', email: 'ciaranj@gmail.com', role: 'member' }
, { id: 2, name: 'aaron', email: 'aaron.heckmann+github@gmail.com', role: 'admin' }
];
@@ -34,7 +36,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 +49,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

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -7,7 +9,6 @@ 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');
@@ -27,7 +28,7 @@ if (!module.parent) {
app.use(methodOverride('_method'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.urlencoded({ extended: true }))
app.use(express.static(path.join(__dirname, 'public')));
// General

View File

@@ -1,3 +1,5 @@
'use strict'
// Fake posts database
var posts = [

View File

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

View File

@@ -1,3 +1,5 @@
'use strict'
// Fake user database
var users = [

View File

@@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><%= title %></title>
<link rel="stylesheet" href="/style.css">
</head>

View File

@@ -1,4 +1,4 @@
<% include header %>
<%- include('header') -%>
<h1><%= title %></h1>
@@ -7,4 +7,4 @@
<li>Visit the <a href="/posts">posts</a> page.</li>
</ul>
<% include footer %>
<%- include('footer') -%>

View File

@@ -1,4 +1,4 @@
<% include ../header %>
<%- include('../header') -%>
<h1>Posts</h1>
@@ -9,4 +9,4 @@
<% }) %>
</dl>
<% include ../footer %>
<%- include('../footer') -%>

View File

@@ -1,9 +1,9 @@
<% include ../header %>
<%- include('../header') -%>
<h1>Editing <%= user.name %></h1>
<div id="user">
<form action="?_method=put", method="post">
<form action="?_method=put" method="post">
<p>
Name:
<input type="text" value="<%= user.name %>" name="user[name]" />
@@ -20,4 +20,4 @@
</form>
</div>
<% include ../footer %>
<%- include('../footer') -%>

View File

@@ -1,4 +1,4 @@
<% include ../header %>
<%- include('../header') -%>
<h1><%= title %></h1>
@@ -11,4 +11,4 @@
<% }) %>
</div>
<% include ../footer %>
<%- include('../footer') -%>

View File

@@ -1,4 +1,4 @@
<% include ../header %>
<%- include('../header') -%>
<h1><%= user.name %></h1>
@@ -6,4 +6,4 @@
<p>Email: <%= user.email %></p>
</div>
<% include ../footer %>
<%- include('../footer') -%>

View File

@@ -1,3 +1,4 @@
'use strict'
// install redis first:
// https://redis.io/

View File

@@ -1,3 +1,5 @@
'use strict'
var search = document.querySelector('[type=search]');
var code = document.querySelector('pre');
@@ -5,7 +7,7 @@ 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;
}
};

View File

@@ -2,8 +2,9 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Search example</title>
<style type="text/css">
<style>
body {
font: 14px "Helvetica Neue", Helvetica;
padding: 50px;
@@ -14,7 +15,7 @@
<h2>Search</h2>
<p>Try searching for "ferret" or "cat".</p>
<input type="search" name="search" value="" />
<pre />
<pre></pre>
<script src="/client.js" charset="utf-8"></script>
</body>
</html>

View File

@@ -1,3 +1,4 @@
'use strict'
// install redis first:
// https://redis.io/

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1 +1 @@
foo
// foo

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -13,7 +15,7 @@ app.set('view engine', 'ejs');
// filter ferrets only
function ferrets(user) {
return user.species == 'ferret';
return user.species === 'ferret'
}
// naive nesting approach,
@@ -59,7 +61,7 @@ function users(req, res, next) {
})
}
app.get('/middleware', count, users, function(req, res, next){
app.get('/middleware', count, users, function (req, res) {
res.render('index', {
title: 'Users',
count: req.count,
@@ -97,7 +99,7 @@ function users2(req, res, next) {
})
}
app.get('/middleware-locals', count2, users2, function(req, res, next){
app.get('/middleware-locals', count2, users2, function (req, res) {
// you can see now how we have much less
// to pass to res.render(). If we have
// several routes related to users this

View File

@@ -1,3 +1,5 @@
'use strict'
module.exports = User;
// faux model

View File

@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><%= title %></title>
<style media="screen">
body {

View File

@@ -1,3 +1,5 @@
'use strict'
/**
* Module dependencies.
*/
@@ -8,7 +10,7 @@ var app = module.exports = express();
// create an error with .status. we
// can then use the property in our
// custom error handler (Connect repects this prop as well)
// custom error handler (Connect respects this prop as well)
function error(status, msg) {
var err = new Error(msg);
@@ -32,7 +34,7 @@ app.use('/api', function(req, res, next){
if (!key) return next(error(400, 'api key required'));
// key is invalid
if (!~apiKeys.indexOf(key)) return next(error(401, 'invalid api key'));
if (apiKeys.indexOf(key) === -1) return next(error(401, 'invalid api key'))
// all good, store req.key for route access
req.key = key;
@@ -49,13 +51,13 @@ var apiKeys = ['foo', 'bar', 'baz'];
// these two objects will serve as our faux database
var repos = [
{ name: 'express', url: 'http://github.com/expressjs/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 = [
{ name: 'tobi' }
{ name: 'tobi' }
, { name: 'loki' }
, { name: 'jane' }
];
@@ -69,14 +71,17 @@ var userRepos = {
// we now can assume the api key is valid,
// and simply expose the data
app.get('/api/users', function(req, res, next){
// example: http://localhost:3000/api/users/?api-key=foo
app.get('/api/users', function (req, res) {
res.send(users);
});
app.get('/api/repos', function(req, res, next){
// example: http://localhost:3000/api/repos/?api-key=foo
app.get('/api/repos', function (req, res) {
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];
@@ -102,7 +107,7 @@ app.use(function(err, req, res, next){
// invoke next() and do not respond.
app.use(function(req, res){
res.status(404);
res.send({ error: "Lame, can't find that" });
res.send({ error: "Sorry, can't find that" })
});
/* istanbul ignore next */

View File

@@ -29,6 +29,13 @@ var flatten = require('array-flatten');
var merge = require('utils-merge');
var resolve = require('path').resolve;
var setPrototypeOf = require('setprototypeof')
/**
* Module variables.
* @private
*/
var hasOwnProperty = Object.prototype.hasOwnProperty
var slice = Array.prototype.slice;
/**
@@ -207,7 +214,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
@@ -276,7 +283,7 @@ app.route = function route(path) {
* In this case EJS provides a `.renderFile()` method with
* the same signature that Express expects: `(path, options, callback)`,
* though note that it aliases this method as `ejs.__express` internally
* so if you're using ".ejs" extensions you dont need to do anything.
* so if you're using ".ejs" extensions you don't need to do anything.
*
* Some template engines do not follow this convention, the
* [Consolidate.js](https://github.com/tj/consolidate.js)
@@ -338,7 +345,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.
@@ -352,7 +359,17 @@ app.param = function param(name, fn) {
app.set = function set(setting, val) {
if (arguments.length === 1) {
// app.get(setting)
return this.settings[setting];
var settings = this.settings
while (settings && settings !== Object.prototype) {
if (hasOwnProperty.call(settings, setting)) {
return settings[setting]
}
settings = Object.getPrototypeOf(settings)
}
return undefined
}
debug('set "%s" to %o', setting, val);

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');
@@ -74,16 +75,18 @@ exports.Router = Router;
* Expose middleware
*/
exports.json = bodyParser.json
exports.query = require('./middleware/query');
exports.raw = bodyParser.raw
exports.static = require('serve-static');
exports.text = bodyParser.text
exports.urlencoded = bodyParser.urlencoded
/**
* Replace removed middleware with an appropriate error message.
*/
[
'json',
'urlencoded',
var removedMiddlewares = [
'bodyParser',
'compress',
'cookieSession',
@@ -100,8 +103,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

@@ -251,7 +251,7 @@ req.param = function param(name, defaultValue) {
/**
* Check if the incoming request contains the "Content-Type"
* header field, and it contains the give mime `type`.
* header field, and it contains the given mime `type`.
*
* Examples:
*
@@ -315,8 +315,12 @@ 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()
});
/**
@@ -426,6 +430,10 @@ defineGetter(req, 'hostname', function hostname(){
if (!host || !trust(this.connection.remoteAddress, 0)) {
host = this.get('Host');
} else if (host.indexOf(',') !== -1) {
// Note: X-Forwarded-Host is normally only ever a
// single value, but this is to be safe.
host = host.substring(0, host.indexOf(',')).trimRight()
}
if (!host) return;

View File

@@ -12,7 +12,9 @@
* @private
*/
var Buffer = require('safe-buffer').Buffer
var contentDisposition = require('content-disposition');
var createError = require('http-errors')
var deprecate = require('depd')('express');
var encodeUrl = require('encodeurl');
var escapeHtml = require('escape-html');
@@ -32,6 +34,7 @@ var extname = path.extname;
var mime = send.mime;
var resolve = path.resolve;
var vary = require('vary');
var urlParse = require('url').parse;
/**
* Response prototype.
@@ -63,6 +66,9 @@ var charsetRegExp = /;\s*charset\s*=/;
*/
res.status = function status(code) {
if ((typeof code === 'string' || Math.floor(code) !== code) && code > 99 && code < 1000) {
deprecate('res.status(' + JSON.stringify(code) + '): use res.status(' + Math.floor(code) + ') instead')
}
this.statusCode = code;
return this;
};
@@ -95,7 +101,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>');
*
@@ -106,7 +112,6 @@ res.links = function(links){
res.send = function send(body) {
var chunk = body;
var encoding;
var len;
var req = this.req;
var type;
@@ -135,7 +140,7 @@ res.send = function send(body) {
deprecate('res.send(status): Use res.sendStatus(status) instead');
this.statusCode = chunk;
chunk = statuses[chunk]
chunk = statuses.message[chunk]
}
switch (typeof chunk) {
@@ -171,23 +176,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);
}
}
@@ -203,6 +218,13 @@ res.send = function send(body) {
chunk = '';
}
// alter headers for 205
if (this.statusCode === 205) {
this.set('Content-Length', '0')
this.removeHeader('Transfer-Encoding')
chunk = ''
}
if (req.method === 'HEAD') {
// skip body for HEAD
this.end();
@@ -244,9 +266,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 = stringify(val, replacer, spaces);
var body = stringify(val, replacer, spaces, escape)
// content-type
if (!this.get('Content-Type')) {
@@ -273,9 +296,9 @@ res.jsonp = function jsonp(obj) {
// allow status / body
if (arguments.length === 2) {
// res.json(body, status) backwards compat
// res.jsonp(body, status) backwards compat
if (typeof arguments[1] === 'number') {
deprecate('res.jsonp(obj, status): Use res.status(status).json(obj) instead');
deprecate('res.jsonp(obj, status): Use res.status(status).jsonp(obj) instead');
this.statusCode = arguments[1];
} else {
deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead');
@@ -286,9 +309,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 = stringify(val, replacer, spaces);
var body = stringify(val, replacer, spaces, escape)
var callback = this.req.query[app.get('jsonp callback name')];
// content-type
@@ -304,17 +328,21 @@ 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');
// restrict callback charset
callback = callback.replace(/[^\[\]\w$.]/g, '');
// replace chars not allowed in JavaScript that are in JSON
body = body
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029');
if (body === undefined) {
// empty argument
body = ''
} else if (typeof body === 'string') {
// replace chars not allowed in JavaScript that are in JSON
body = body
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029')
}
// the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse"
// the typeof check is just to reduce client error noise
@@ -340,7 +368,7 @@ res.jsonp = function jsonp(obj) {
*/
res.sendStatus = function sendStatus(statusCode) {
var body = statuses[statusCode] || String(statusCode)
var body = statuses.message[statusCode] || String(statusCode)
this.statusCode = statusCode;
this.type('txt');
@@ -353,7 +381,7 @@ res.sendStatus = function sendStatus(statusCode) {
*
* Automatically sets the _Content-Type_ response header field.
* The callback `callback(err)` is invoked when the transfer is complete
* or when an error occurs. Be sure to check `res.sentHeader`
* or when an error occurs. Be sure to check `res.headersSent`
* if you wish to attempt responding, as the header and some data
* may have already been transferred.
*
@@ -400,6 +428,10 @@ res.sendFile = function sendFile(path, options, callback) {
throw new TypeError('path argument is required to res.sendFile');
}
if (typeof path !== 'string') {
throw new TypeError('path must be a string to res.sendFile')
}
// support function as second arg
if (typeof options === 'function') {
done = options;
@@ -431,7 +463,7 @@ res.sendFile = function sendFile(path, options, callback) {
*
* Automatically sets the _Content-Type_ response header field.
* The callback `callback(err)` is invoked when the transfer is complete
* or when an error occurs. Be sure to check `res.sentHeader`
* or when an error occurs. Be sure to check `res.headersSent`
* if you wish to attempt responding, as the header and some data
* may have already been transferred.
*
@@ -489,7 +521,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);
}
});
@@ -504,21 +536,38 @@ res.sendfile = deprecate.function(res.sendfile,
* Optionally providing an alternate attachment `filename`,
* and optional callback `callback(err)`. The callback is invoked
* when the data transfer is complete, or when an error has
* ocurred. Be sure to check `res.headersSent` if you plan to respond.
* occurred. 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
}
// support optional filename, where options may be in it's place
if (typeof filename === 'object' &&
(typeof options === 'function' || options === undefined)) {
name = null
opts = filename
}
// set Content-Disposition when file is sent
@@ -526,10 +575,28 @@ res.download = function download(path, filename, callback) {
'Content-Disposition': contentDisposition(name || path)
};
// Resolve the full path for sendFile
var fullPath = resolve(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]
}
}
}
return this.sendFile(fullPath, { headers: headers }, done);
// merge user-provided options
opts = Object.create(opts)
opts.headers = headers
// Resolve the full path for sendFile
var fullPath = !opts.root
? resolve(path)
: path
// send file
return this.sendFile(fullPath, opts, done)
};
/**
@@ -582,7 +649,7 @@ res.type = function contentType(type) {
* res.send('<p>hey</p>');
* },
*
* 'appliation/json': function(){
* 'application/json': function () {
* res.send({ message: 'hey' });
* }
* });
@@ -619,9 +686,8 @@ res.format = function(obj){
var req = this.req;
var next = req.next;
var fn = obj.default;
if (fn) delete obj.default;
var keys = Object.keys(obj);
var keys = Object.keys(obj)
.filter(function (v) { return v !== 'default' })
var key = keys.length > 0
? req.accepts(keys)
@@ -632,13 +698,12 @@ res.format = function(obj){
if (key) {
this.set('Content-Type', normalizeType(key).value);
obj[key](req, this, next);
} else if (fn) {
fn();
} else if (obj.default) {
obj.default(req, this, next)
} else {
var err = new Error('Not Acceptable');
err.status = err.statusCode = 406;
err.types = normalizeTypes(keys).map(function(o){ return o.value });
next(err);
next(createError(406, {
types: normalizeTypes(keys).map(function (o) { return o.value })
}))
}
return this;
@@ -685,7 +750,7 @@ res.append = function append(field, val) {
// concat the new and prev vals
value = Array.isArray(prev) ? prev.concat(val)
: Array.isArray(val) ? [prev].concat(val)
: [prev, val];
: [prev, val]
}
return this.set(field, value);
@@ -777,7 +842,7 @@ res.clearCookie = function clearCookie(name, options) {
* // "Remember Me" for 15 minutes
* res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
*
* // save as above
* // same as above
* res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
*
* @param {String} name
@@ -804,9 +869,13 @@ res.cookie = function (name, value, options) {
val = 's:' + sign(val, secret);
}
if ('maxAge' in opts) {
opts.expires = new Date(Date.now() + opts.maxAge);
opts.maxAge /= 1000;
if (opts.maxAge != null) {
var maxAge = opts.maxAge - 0
if (!isNaN(maxAge)) {
opts.expires = new Date(Date.now() + maxAge)
opts.maxAge = Math.floor(maxAge / 1000)
}
}
if (opts.path == null) {
@@ -836,15 +905,32 @@ res.cookie = function (name, value, options) {
*/
res.location = function location(url) {
var loc = url;
var loc = String(url);
// "back" is an alias for the referrer
if (url === 'back') {
loc = this.req.get('Referrer') || '/';
}
var lowerLoc = loc.toLowerCase();
var encodedUrl = encodeUrl(loc);
if (lowerLoc.indexOf('https://') === 0 || lowerLoc.indexOf('http://') === 0) {
try {
var parsedUrl = urlParse(loc);
var parsedEncodedUrl = urlParse(encodedUrl);
// Because this can encode the host, check that we did not change the host
if (parsedUrl.host !== parsedEncodedUrl.host) {
// If the host changes after encodeUrl, return the original url
return this.set('Location', loc);
}
} catch (e) {
// If parse fails, return the original url
return this.set('Location', loc);
}
}
// set location
return this.set('Location', encodeUrl(loc));
return this.set('Location', encodedUrl);
};
/**
@@ -887,12 +973,12 @@ res.redirect = function redirect(url) {
// Support text/{plain,html} by default
this.format({
text: function(){
body = statuses[status] + '. Redirecting to ' + address
body = statuses.message[status] + '. Redirecting to ' + address
},
html: function(){
var u = escapeHtml(address);
body = '<p>' + statuses[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>'
body = '<p>' + statuses.message[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>'
},
default: function(){
@@ -1063,14 +1149,39 @@ function sendfile(res, file, options, callback) {
}
/**
* Stringify JSON, like JSON.stringify, but v8 optimized.
* Stringify JSON, like JSON.stringify, but v8 optimized, with the
* ability to escape characters that can trigger HTML sniffing.
*
* @param {*} value
* @param {function} replacer
* @param {number} spaces
* @param {boolean} escape
* @returns {string}
* @private
*/
function stringify(value, replacer, spaces) {
function stringify (value, replacer, spaces, escape) {
// v8 checks arguments.length for optimizing simple call
// https://bugs.chromium.org/p/v8/issues/detail?id=4730
return replacer || spaces
var json = replacer || spaces
? JSON.stringify(value, replacer, spaces)
: JSON.stringify(value);
if (escape && typeof json === 'string') {
json = json.replace(/[<>&]/g, function (c) {
switch (c.charCodeAt(0)) {
case 0x3c:
return '\\u003c'
case 0x3e:
return '\\u003e'
case 0x26:
return '\\u0026'
/* istanbul ignore next: unreachable default */
default:
return c
}
})
}
return json
}

View File

@@ -35,8 +35,8 @@ var toString = Object.prototype.toString;
/**
* Initialize a new `Router` with the given `options`.
*
* @param {Object} options
* @return {Router} which is an callable function
* @param {Object} [options]
* @return {Router} which is a callable function
* @public
*/
@@ -108,8 +108,8 @@ proto.param = function param(name, fn) {
var ret;
if (name[0] === ':') {
deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead');
name = name.substr(1);
deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.slice(1)) + ', fn) instead')
name = name.slice(1)
}
for (var i = 0; i < len; ++i) {
@@ -142,6 +142,7 @@ proto.handle = function handle(req, res, out) {
var protohost = getProtohost(req.url) || ''
var removed = '';
var slashAdded = false;
var sync = 0
var paramcalled = {};
// store options for OPTIONS request
@@ -180,14 +181,14 @@ proto.handle = function handle(req, res, out) {
// remove added slash
if (slashAdded) {
req.url = req.url.substr(1);
req.url = req.url.slice(1)
slashAdded = false;
}
// restore altered req.url
if (removed.length !== 0) {
req.baseUrl = parentUrl;
req.url = protohost + removed + req.url.substr(protohost.length);
req.url = protohost + removed + req.url.slice(protohost.length)
removed = '';
}
@@ -203,6 +204,11 @@ proto.handle = function handle(req, res, out) {
return;
}
// max sync stack
if (++sync > 100) {
return setImmediate(next, err)
}
// get pathname of request
var path = getPathname(req);
@@ -251,7 +257,6 @@ proto.handle = function handle(req, res, out) {
// don't even bother matching route
if (!has_method && method !== 'HEAD') {
match = false;
continue;
}
}
@@ -274,19 +279,25 @@ proto.handle = function handle(req, res, out) {
// this should be done for the layer
self.process_params(layer, paramcalled, req, res, function (err) {
if (err) {
return next(layerError || err);
next(layerError || err)
} else if (route) {
layer.handle_request(req, res, next)
} else {
trim_prefix(layer, layerError, layerPath, path)
}
if (route) {
return layer.handle_request(req, res, next);
}
trim_prefix(layer, layerError, layerPath, path);
sync = 0
});
}
function trim_prefix(layer, layerError, layerPath, path) {
if (layerPath.length !== 0) {
// Validate path is a prefix match
if (layerPath !== path.slice(0, layerPath.length)) {
next(layerError)
return
}
// Validate path breaks on a path separator
var c = path[layerPath.length]
if (c && c !== '/' && c !== '.') return next(layerError)
@@ -295,7 +306,7 @@ proto.handle = function handle(req, res, out) {
// 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);
req.url = protohost + req.url.slice(protohost.length + removed.length)
// Ensure leading slash
if (!protohost && req.url[0] !== '/') {
@@ -448,14 +459,14 @@ 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
@@ -541,10 +552,10 @@ function getProtohost(url) {
var pathLength = searchIndex !== -1
? searchIndex
: url.length
var fqdnIndex = url.substr(0, pathLength).indexOf('://')
var fqdnIndex = url.slice(0, pathLength).indexOf('://')
return fqdnIndex !== -1
? url.substr(0, url.indexOf('/', 3 + fqdnIndex))
? url.substring(0, url.indexOf('/', 3 + fqdnIndex))
: undefined
}

View File

@@ -60,7 +60,10 @@ Route.prototype._handles_method = function _handles_method(method) {
return true;
}
var name = method.toLowerCase();
// normalize name
var name = typeof method === 'string'
? method.toLowerCase()
: method
if (name === 'head' && !this.methods['head']) {
name = 'get';
@@ -98,11 +101,15 @@ Route.prototype._options = function _options() {
Route.prototype.dispatch = function dispatch(req, res, done) {
var idx = 0;
var stack = this.stack;
var sync = 0
if (stack.length === 0) {
return done();
}
var method = typeof req.method === 'string'
? req.method.toLowerCase()
: req.method
var method = req.method.toLowerCase();
if (method === 'head' && !this.methods['head']) {
method = 'get';
}
@@ -122,20 +129,27 @@ Route.prototype.dispatch = function dispatch(req, res, done) {
return done(err)
}
var layer = stack[idx++];
// max sync stack
if (++sync > 100) {
return setImmediate(next, err)
}
var layer = stack[idx++]
// end of layers
if (!layer) {
return done(err);
return done(err)
}
if (layer.method && layer.method !== method) {
return next(err);
}
if (err) {
next(err)
} else if (err) {
layer.handle_error(err, req, res, next);
} else {
layer.handle_request(req, res, next);
}
sync = 0
}
};
@@ -175,7 +189,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);
}
@@ -198,7 +212,7 @@ 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);
}

View File

@@ -12,6 +12,7 @@
* @api private
*/
var Buffer = require('safe-buffer').Buffer
var contentDisposition = require('content-disposition');
var contentType = require('content-type');
var deprecate = require('depd')('express');
@@ -31,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`.
@@ -48,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.
@@ -128,16 +117,15 @@ exports.contentDisposition = deprecate.function(contentDisposition,
/**
* Parse accept params `str` returning an
* object with `.value`, `.quality` and `.params`.
* also includes `.originalIndex` for stable sorting
*
* @param {String} str
* @return {Object}
* @api private
*/
function acceptParams(str, index) {
function acceptParams (str) {
var parts = str.split(/ *; */);
var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
var ret = { value: parts[0], quality: 1, params: {} }
for (var i = 1; i < parts.length; ++i) {
var pms = parts[i].split(/ *= */);
@@ -168,6 +156,7 @@ exports.compileETag = function(val) {
switch (val) {
case true:
case 'weak':
fn = exports.wetag;
break;
case false:
@@ -175,9 +164,6 @@ exports.compileETag = function(val) {
case 'strong':
fn = exports.etag;
break;
case 'weak':
fn = exports.wetag;
break;
default:
throw new TypeError('unknown value for etag function: ' + val);
}
@@ -202,6 +188,7 @@ exports.compileQueryParser = function compileQueryParser(val) {
switch (val) {
case true:
case 'simple':
fn = querystring.parse;
break;
case false:
@@ -210,9 +197,6 @@ exports.compileQueryParser = function compileQueryParser(val) {
case 'extended':
fn = parseExtendedQueryString;
break;
case 'simple':
fn = querystring.parse;
break;
default:
throw new TypeError('unknown value for query parser function: ' + val);
}
@@ -243,7 +227,8 @@ exports.compileTrust = function(val) {
if (typeof val === 'string') {
// Support comma-separated values
val = val.split(/ *, */);
val = val.split(',')
.map(function (v) { return v.trim() })
}
return proxyaddr.compile(val || []);
@@ -273,9 +258,29 @@ 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.
*
* @param {String} str
* @return {Object}
* @private
*/

View File

@@ -74,9 +74,17 @@ function View(name, options) {
if (!opts.engines[this.ext]) {
// load engine
var mod = this.ext.substr(1)
var mod = this.ext.slice(1)
debug('require "%s"', mod)
opts.engines[this.ext] = require(mod).__express
// 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.15.4",
"version": "4.19.1",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
@@ -20,6 +20,7 @@
"framework",
"sinatra",
"web",
"http",
"rest",
"restful",
"router",
@@ -27,54 +28,54 @@
"api"
],
"dependencies": {
"accepts": "~1.3.3",
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"content-disposition": "0.5.2",
"content-type": "~1.0.2",
"cookie": "0.3.1",
"body-parser": "1.20.2",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.8",
"depd": "~1.1.1",
"encodeurl": "~1.0.1",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.0",
"finalhandler": "~1.0.4",
"fresh": "0.5.0",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.1",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~1.1.5",
"qs": "6.5.0",
"range-parser": "~1.2.0",
"send": "0.15.4",
"serve-static": "1.12.4",
"setprototypeof": "1.0.3",
"statuses": "~1.3.1",
"type-is": "~1.6.15",
"utils-merge": "1.0.0",
"vary": "~1.1.1"
"proxy-addr": "~2.0.7",
"qs": "6.11.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"devDependencies": {
"after": "0.8.2",
"body-parser": "1.17.2",
"cookie-parser": "~1.4.3",
"cookie-session": "1.3.0",
"ejs": "2.5.7",
"eslint": "2.13.1",
"express-session": "1.15.5",
"hbs": "4.0.1",
"istanbul": "0.4.5",
"marked": "0.3.6",
"method-override": "2.3.9",
"mocha": "3.5.0",
"morgan": "1.8.2",
"multiparty": "4.1.3",
"connect-redis": "3.4.2",
"cookie-parser": "1.4.6",
"cookie-session": "2.0.0",
"ejs": "3.1.9",
"eslint": "8.47.0",
"express-session": "1.17.2",
"hbs": "4.2.0",
"marked": "0.7.0",
"method-override": "3.0.0",
"mocha": "10.2.0",
"morgan": "1.10.0",
"nyc": "15.1.0",
"pbkdf2-password": "1.2.1",
"should": "11.2.1",
"supertest": "1.2.0",
"connect-redis": "~2.4.1",
"supertest": "6.3.0",
"vhost": "~3.0.2"
},
"engines": {
@@ -90,8 +91,8 @@
"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/",
"test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test",
"test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"
}
}

View File

@@ -1,6 +1,7 @@
'use strict'
var after = require('after');
var should = require('should');
var assert = require('assert')
var express = require('../')
, Route = express.Route
, methods = require('methods')
@@ -12,6 +13,37 @@ describe('Route', function(){
route.dispatch(req, {}, done)
})
it('should not stack overflow with a large sync stack', function (done) {
this.timeout(5000) // long-running test
var req = { method: 'GET', url: '/' }
var route = new Route('/foo')
route.get(function (req, res, next) {
req.counter = 0
next()
})
for (var i = 0; i < 6000; i++) {
route.all(function (req, res, next) {
req.counter++
next()
})
}
route.get(function (req, res, next) {
req.called = true
next()
})
route.dispatch(req, {}, function (err) {
if (err) return done(err)
assert.ok(req.called)
assert.strictEqual(req.counter, 6000)
done()
})
})
describe('.all', function(){
it('should add handler', function(done){
var req = { method: 'GET', url: '/' };
@@ -24,7 +56,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
should(req.called).be.ok()
assert.ok(req.called)
done();
});
})
@@ -34,7 +66,7 @@ describe('Route', function(){
var route = new Route('/foo');
var cb = after(methods.length, function (err) {
if (err) return done(err);
count.should.equal(methods.length);
assert.strictEqual(count, methods.length)
done();
});
@@ -65,7 +97,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
req.count.should.equal(2);
assert.strictEqual(req.count, 2)
done();
});
})
@@ -83,7 +115,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
should(req.called).be.ok()
assert.ok(req.called)
done();
});
})
@@ -92,7 +124,7 @@ describe('Route', function(){
var req = { method: 'POST', url: '/' };
var route = new Route('');
route.get(function(req, res, next) {
route.get(function () {
throw new Error('not me!');
})
@@ -103,7 +135,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
should(req.called).be.true()
assert.ok(req.called)
done();
});
})
@@ -129,7 +161,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
req.order.should.equal('abc');
assert.strictEqual(req.order, 'abc')
done();
});
})
@@ -155,9 +187,9 @@ describe('Route', function(){
});
route.dispatch(req, {}, function (err) {
should(err).be.ok()
should(err.message).equal('foobar');
req.order.should.equal('a');
assert.ok(err)
assert.strictEqual(err.message, 'foobar')
assert.strictEqual(req.order, 'a')
done();
});
})
@@ -166,7 +198,7 @@ describe('Route', function(){
var req = { order: '', method: 'GET', url: '/' };
var route = new Route('');
route.all(function(req, res, next){
route.all(function () {
throw new Error('foobar');
});
@@ -181,9 +213,9 @@ describe('Route', function(){
});
route.dispatch(req, {}, function (err) {
should(err).be.ok()
should(err.message).equal('foobar');
req.order.should.equal('a');
assert.ok(err)
assert.strictEqual(err.message, 'foobar')
assert.strictEqual(req.order, 'a')
done();
});
});
@@ -192,7 +224,7 @@ describe('Route', function(){
var req = { method: 'GET', url: '/' };
var route = new Route('');
route.get(function(req, res, next){
route.get(function () {
throw new Error('boom!');
});
@@ -207,7 +239,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) {
if (err) return done(err);
should(req.message).equal('oops');
assert.strictEqual(req.message, 'oops')
done();
});
});
@@ -221,8 +253,8 @@ describe('Route', function(){
});
route.dispatch(req, {}, function(err){
should(err).be.ok()
err.message.should.equal('boom!');
assert.ok(err)
assert.strictEqual(err.message, 'boom!')
done();
});
});
@@ -233,7 +265,7 @@ describe('Route', function(){
route.all(function(err, req, res, next){
// this should not execute
true.should.be.false()
throw new Error('should not be called')
});
route.dispatch(req, {}, done);

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