Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: expressjs/express
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e9c9f95ade0f20a048861ac886d4767a839d5286
Choose a base ref
...
head repository: expressjs/express
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7e562c6d8daddff4604f8efaaf9db2cf98c6dcff
Choose a head ref

Commits on Jun 17, 2015

  1. build: should@6.0.3

    dougwilson committed Jun 17, 2015

    Verified

    This commit was signed with the committer’s verified signature.
    minborg Per-Ake Minborg
    Copy the full SHA
    9ae08f9 View commit details
  2. deps: mkdirp@0.5.1

    dougwilson committed Jun 17, 2015
    Copy the full SHA
    a20a9a1 View commit details
  3. docs: fix typos in history

    closes #2676
    closes #2677
    closes #2678
    dougwilson committed Jun 17, 2015
    Copy the full SHA
    29f51c6 View commit details

Commits on Jun 19, 2015

  1. deps: connect@2.30.0

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    62dfa79 View commit details
  2. build: should@7.0.1

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    92b5fa8 View commit details
  3. deps: basic-auth@1.0.2

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    5207b99 View commit details
  4. deps: cookie@0.1.3

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    7740211 View commit details
  5. deps: escape-html@1.0.2

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    0fbf207 View commit details
  6. deps: etag@~1.7.0

    fixes #2667
    dougwilson committed Jun 19, 2015
    Copy the full SHA
    c8d61b6 View commit details
  7. deps: send@0.13.0

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    14b8492 View commit details
  8. deps: fresh@0.3.0

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    4729685 View commit details
  9. 3.21.0

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    115dbe1 View commit details
  10. docs: update res.set jsdoc

    closes #2600
    damphat authored and dougwilson committed Jun 19, 2015
    Copy the full SHA
    4b70375 View commit details
  11. docs: update return types for req.accept*()

    closes #2663
    ioncreature authored and dougwilson committed Jun 19, 2015
    Copy the full SHA
    fce3d14 View commit details
  12. Merge tag '3.21.0'

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    3d2ecdd View commit details
  13. Copy the full SHA
    8da51e3 View commit details
  14. Use array-flatten module for flattening arrays

    closes #2624
    dee-kap authored and dougwilson committed Jun 19, 2015
    Copy the full SHA
    f7e94a3 View commit details
  15. deps: serve-static@~1.10.0

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    b5f98ab View commit details
  16. deps: finalhandler@0.4.0

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    7b7aaf0 View commit details
  17. deps: on-finished@~2.3.0

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    8ad7e8f View commit details
  18. deps: type-is@~1.6.3

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    7b86a0e View commit details
  19. deps: accepts@~1.2.9

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    4212efa View commit details
  20. Copy the full SHA
    9073bb4 View commit details
  21. perf: use saved reference to http.STATUS_CODES

    closes #2602
    tcort authored and dougwilson committed Jun 19, 2015
    Copy the full SHA
    91731b4 View commit details
  22. docs: add license comments

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    95ad276 View commit details
  23. perf: enable strict mode

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    e71014f View commit details
  24. Fix res.format error when only default provided

    fixes #2665
    Behcet Uyar authored and dougwilson committed Jun 19, 2015
    Copy the full SHA
    24d1c98 View commit details
  25. deps: path-to-regexp@0.1.4

    dougwilson committed Jun 19, 2015
    Copy the full SHA
    e66bb4f View commit details
  26. deps: path-to-regexp@0.1.6

    fixes #2491
    fixes #2617
    closes #2637
    closes #2683
    blakeembrey authored and dougwilson committed Jun 19, 2015
    Copy the full SHA
    60e2008 View commit details

Commits on Jun 20, 2015

  1. Copy the full SHA
    0634e7e View commit details
  2. Copy the full SHA
    a8a8564 View commit details
  3. Copy the full SHA
    1050248 View commit details
  4. Copy the full SHA
    f5a2406 View commit details
  5. Copy the full SHA
    d414a2d View commit details
  6. Copy the full SHA
    bb53b20 View commit details
  7. Copy the full SHA
    5915894 View commit details
  8. Copy the full SHA
    3b3e1fc View commit details
  9. Copy the full SHA
    7d6c1e5 View commit details
  10. Copy the full SHA
    5b4d4b4 View commit details
  11. Copy the full SHA
    9302acc View commit details
  12. Add settings to debug output

    closes #2675
    dougwilson committed Jun 20, 2015
    Copy the full SHA
    2a45589 View commit details
  13. build: support io.js 2.x

    dougwilson committed Jun 20, 2015
    Copy the full SHA
    f73ff92 View commit details

Commits on Jun 21, 2015

  1. 4.13.0

    dougwilson committed Jun 21, 2015
    Copy the full SHA
    6c7a367 View commit details

Commits on Jul 6, 2015

  1. deps: connect@2.30.1

    dougwilson committed Jul 6, 2015
    Copy the full SHA
    3ec7cca View commit details
  2. build: ejs@2.3.2

    dougwilson committed Jul 6, 2015
    Copy the full SHA
    71d56db View commit details
  3. deps: basic-auth@~1.0.3

    dougwilson committed Jul 6, 2015
    Copy the full SHA
    f247a41 View commit details
  4. 3.21.1

    dougwilson committed Jul 6, 2015
    Copy the full SHA
    3c0ff81 View commit details
  5. Merge tag '3.21.1'

    dougwilson committed Jul 6, 2015
    Copy the full SHA
    1f906d4 View commit details
  6. deps: type-is@~1.6.4

    dougwilson committed Jul 6, 2015
    Copy the full SHA
    2870add View commit details
  7. deps: accepts@~1.2.10

    dougwilson committed Jul 6, 2015
    Copy the full SHA
    3314f76 View commit details
Showing with 11,951 additions and 2,421 deletions.
  1. +11 −0 .editorconfig
  2. +2 −0 .eslintignore
  3. +8 −0 .eslintrc.yml
  4. +190 −0 .github/workflows/ci.yml
  5. +66 −0 .github/workflows/codeql.yml
  6. +69 −0 .github/workflows/iojs.yml
  7. +6 −16 .gitignore
  8. +1 −0 .npmrc
  9. +0 −10 .travis.yml
  10. +92 −0 Charter.md
  11. +139 −0 Code-Of-Conduct.md
  12. +51 −0 Collaborator-Guide.md
  13. +198 −14 Contributing.md
  14. +827 −14 History.md
  15. +125 −0 Readme-Guide.md
  16. +166 −44 Readme.md
  17. +199 −0 Release-Process.md
  18. +56 −0 Security.md
  19. +70 −0 Triager-Guide.md
  20. +102 −5 appveyor.yml
  21. +12 −8 benchmarks/Makefile
  22. +34 −0 benchmarks/README.md
  23. +2 −5 benchmarks/middleware.js
  24. +5 −3 benchmarks/run
  25. +29 −0 examples/README.md
  26. +13 −10 examples/auth/index.js
  27. +0 −48 examples/auth/pass.js
  28. +2 −0 examples/auth/views/head.ejs
  29. +6 −7 examples/auth/views/login.ejs
  30. +0 −31 examples/big-view/index.js
  31. +0 −12 examples/big-view/pets.jade
  32. +3 −1 examples/content-negotiation/db.js
  33. +2 −0 examples/content-negotiation/index.js
  34. +1 −0 examples/content-negotiation/users.js
  35. +6 −8 examples/cookie-sessions/index.js
  36. +4 −3 examples/cookies/index.js
  37. +3 −0 examples/downloads/files/notes/groceries.txt
  38. +15 −10 examples/downloads/index.js
  39. +8 −1 examples/ejs/index.js
  40. +4 −0 examples/ejs/public/stylesheets/style.css
  41. +3 −7 examples/ejs/views/header.html
  42. +2 −2 examples/ejs/views/users.html
  43. +17 −17 examples/error-pages/index.js
  44. +2 −2 examples/error-pages/views/404.ejs
  45. +2 −2 examples/error-pages/views/500.ejs
  46. +2 −0 examples/error-pages/views/error_header.ejs
  47. +2 −0 examples/error-pages/views/index.ejs
  48. +7 −2 examples/error/index.js
  49. +0 −64 examples/expose-data-to-client/index.js
  50. +0 −14 examples/expose-data-to-client/views/page.jade
  51. +3 −1 examples/hello-world/index.js
  52. +0 −51 examples/jade/index.js
  53. +0 −4 examples/jade/public/stylesheets/style.css
  54. +0 −3 examples/jade/views/header.jade
  55. +0 −5 examples/jade/views/layout.jade
  56. +0 −8 examples/jade/views/users/index.jade
  57. +0 −3 examples/jade/views/users/user.jade
  58. +11 −12 examples/markdown/index.js
  59. +2 −0 examples/multi-router/controllers/api_v1.js
  60. +2 −0 examples/multi-router/controllers/api_v2.js
  61. +3 −1 examples/multi-router/index.js
  62. +0 −60 examples/multipart/index.js
  63. +3 −1 examples/mvc/controllers/main/index.js
  64. +2 −0 examples/mvc/controllers/pet/index.js
  65. +2 −0 examples/mvc/controllers/pet/views/edit.ejs
  66. +2 −0 examples/mvc/controllers/pet/views/show.ejs
  67. +2 −0 examples/mvc/controllers/user-pet/index.js
  68. +4 −0 examples/mvc/controllers/user/index.js
  69. +27 −0 examples/mvc/controllers/user/views/edit.hbs
  70. +0 −11 examples/mvc/controllers/user/views/edit.jade
  71. +18 −0 examples/mvc/controllers/user/views/list.hbs
  72. +0 −7 examples/mvc/controllers/user/views/list.jade
  73. +31 −0 examples/mvc/controllers/user/views/show.hbs
  74. +0 −17 examples/mvc/controllers/user/views/show.jade
  75. +3 −1 examples/mvc/db.js
  76. +9 −9 examples/mvc/index.js
  77. +21 −15 examples/mvc/lib/boot.js
  78. +1 −1 examples/mvc/public/style.css
  79. +13 −0 examples/mvc/views/404.ejs
  80. +0 −3 examples/mvc/views/404.jade
  81. +13 −0 examples/mvc/views/5xx.ejs
  82. +0 −3 examples/mvc/views/5xx.jade
  83. +6 −1 examples/online/index.js
  84. +7 −12 examples/params/index.js
  85. +4 −2 examples/resource/index.js
  86. +7 −4 examples/route-map/index.js
  87. +5 −3 examples/route-middleware/index.js
  88. +7 −5 examples/route-separation/index.js
  89. +2 −0 examples/route-separation/post.js
  90. +3 −1 examples/route-separation/site.js
  91. +2 −0 examples/route-separation/user.js
  92. +2 −0 examples/route-separation/views/footer.ejs
  93. +9 −0 examples/route-separation/views/header.ejs
  94. +10 −0 examples/route-separation/views/index.ejs
  95. +0 −6 examples/route-separation/views/index.jade
  96. +0 −6 examples/route-separation/views/layout.jade
  97. +12 −0 examples/route-separation/views/posts/index.ejs
  98. +0 −8 examples/route-separation/views/posts/index.jade
  99. +23 −0 examples/route-separation/views/users/edit.ejs
  100. +0 −12 examples/route-separation/views/users/edit.jade
  101. +14 −0 examples/route-separation/views/users/index.ejs
  102. +0 −9 examples/route-separation/views/users/index.jade
  103. +9 −0 examples/route-separation/views/users/view.ejs
  104. +0 −6 examples/route-separation/views/users/view.jade
  105. +9 −12 examples/search/index.js
  106. +4 −2 examples/search/{ → public}/client.js
  107. +21 −0 examples/search/public/index.html
  108. +0 −15 examples/search/search.jade
  109. +6 −1 examples/session/index.js
  110. +2 −0 examples/session/redis.js
  111. +6 −3 examples/static-files/index.js
  112. +1 −1 examples/static-files/public/js/app.js
  113. +2 −0 examples/vhost/index.js
  114. +3 −1 examples/view-constructor/github-view.js
  115. +4 −3 examples/view-constructor/index.js
  116. +11 −8 examples/view-locals/index.js
  117. +0 −12 examples/view-locals/layout.jade
  118. +0 −8 examples/view-locals/user.jade
  119. +5 −0 examples/view-locals/user.js
  120. +20 −0 examples/view-locals/views/index.ejs
  121. +15 −10 examples/web-service/index.js
  122. +9 −0 index.js
  123. +148 −94 lib/application.js
  124. +30 −7 lib/express.js
  125. +19 −2 lib/middleware/init.js
  126. +19 −2 lib/middleware/query.js
  127. +120 −62 lib/request.js
  128. +304 −155 lib/response.js
  129. +103 −60 lib/router/index.js
  130. +54 −39 lib/router/layer.js
  131. +84 −37 lib/router/route.js
  132. +52 −42 lib/utils.js
  133. +67 −27 lib/view.js
  134. +52 −44 package.json
  135. +57 −21 test/Route.js
  136. +158 −23 test/Router.js
  137. +16 −1 test/acceptance/auth.js
  138. +4 −4 test/acceptance/cookie-sessions.js
  139. +7 −12 test/acceptance/cookies.js
  140. +19 −5 test/acceptance/downloads.js
  141. +2 −5 test/acceptance/error-pages.js
  142. +1 −1 test/acceptance/error.js
  143. +21 −0 test/acceptance/hello-world.js
  144. +1 −1 test/acceptance/multi-router.js
  145. +2 −2 test/acceptance/params.js
  146. +1 −1 test/acceptance/route-map.js
  147. +5 −5 test/acceptance/web-service.js
  148. +8 −5 test/app.all.js
  149. +1 −0 test/app.del.js
  150. +15 −12 test/app.engine.js
  151. +8 −10 test/app.head.js
  152. +40 −18 test/app.js
  153. +3 −8 test/app.listen.js
  154. +16 −18 test/app.locals.js
  155. +2 −1 test/app.options.js
  156. +82 −24 test/app.param.js
  157. +62 −50 test/app.render.js
  158. +120 −0 test/app.request.js
  159. +114 −15 test/app.response.js
  160. +2 −0 test/app.route.js
  161. +249 −52 test/app.router.js
  162. +25 −6 test/app.routes.error.js
  163. +33 −18 test/app.use.js
  164. +51 −6 test/config.js
  165. +37 −11 test/exports.js
  166. +790 −0 test/express.json.js
  167. +555 −0 test/express.raw.js
  168. +814 −0 test/express.static.js
  169. +605 −0 test/express.text.js
  170. +866 −0 test/express.urlencoded.js
  171. 0 test/fixtures/broken.send
  172. 0 test/fixtures/empty.txt
  173. +1 −0 test/fixtures/nums.txt
  174. +1 −0 test/fixtures/pets/names.txt
  175. 0 test/fixtures/snow ☃/.gitkeep
  176. +1 −0 test/fixtures/todo.html
  177. +1 −0 test/fixtures/todo.txt
  178. +1 −0 test/fixtures/users/index.html
  179. +1 −0 test/fixtures/users/tobi.txt
  180. +6 −8 test/middleware.basic.js
  181. +0 −3 test/mocha.opts
  182. +1 −0 test/regression.js
  183. +1 −0 test/req.accepts.js
  184. +3 −2 test/req.acceptsCharset.js
  185. +3 −2 test/req.acceptsCharsets.js
  186. +20 −17 test/req.acceptsEncoding.js
  187. +21 −18 test/req.acceptsEncodings.js
  188. +30 −26 test/req.acceptsLanguage.js
  189. +30 −26 test/req.acceptsLanguages.js
  190. +1 −0 test/req.baseUrl.js
  191. +2 −1 test/req.fresh.js
  192. +26 −1 test/req.get.js
  193. +1 −1 test/req.host.js
  194. +51 −1 test/req.hostname.js
  195. +19 −3 test/req.ip.js
  196. +1 −0 test/req.ips.js
  197. +140 −74 test/req.is.js
  198. +2 −2 test/req.param.js
  199. +1 −0 test/req.path.js
  200. +1 −0 test/req.protocol.js
  201. +36 −8 test/req.query.js
  202. +90 −24 test/req.range.js
  203. +7 −4 test/req.route.js
  204. +1 −0 test/req.secure.js
  205. +3 −6 test/req.signedCookies.js
  206. +2 −1 test/req.stale.js
  207. +1 −0 test/req.subdomains.js
  208. +23 −55 test/req.xhr.js
  209. +42 −30 test/res.append.js
  210. +3 −1 test/res.attachment.js
  211. +37 −10 test/res.clearCookie.js
  212. +164 −41 test/res.cookie.js
  213. +395 −10 test/res.download.js
  214. +56 −11 test/res.format.js
  215. +1 −0 test/res.get.js
  216. +39 −1 test/res.json.js
  217. +98 −58 test/res.jsonp.js
  218. +1 −0 test/res.links.js
  219. +5 −6 test/res.locals.js
  220. +344 −4 test/res.location.js
  221. +79 −48 test/res.redirect.js
  222. +61 −23 test/res.render.js
  223. +101 −59 test/res.send.js
  224. +844 −159 test/res.sendFile.js
  225. +1 −1 test/res.sendStatus.js
  226. +14 −0 test/res.set.js
  227. +194 −12 test/res.status.js
  228. +3 −1 test/res.type.js
  229. +4 −9 test/res.vary.js
  230. +1 −1 test/support/env.js
  231. +1 −0 test/support/tmpl.js
  232. +86 −0 test/support/utils.js
  233. +28 −20 test/utils.js
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# http://editorconfig.org
root = true

[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true

[{*.js,*.json,*.yml}]
indent_size = 2
indent_style = space
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
coverage
node_modules
8 changes: 8 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -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 }]
190 changes: 190 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
name: ci

on:
push:
branches:
- master
- develop
- '4.x'
- '5.x'
paths-ignore:
- '*.md'
pull_request:
paths-ignore:
- '*.md'

# Cancel in progress workflows
# in the scenario where we already had a run going for that PR/branch/tag but then triggered a new run
concurrency:
group: "${{ github.workflow }} ✨ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
cancel-in-progress: true

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js {{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
persist-credentials: false

- name: Install dependencies
run: npm install --ignore-scripts --only=dev

- name: Run lint
run: npm run lint

test:
name: Run tests
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
node-version:
- "0.10"
- "0.12"
- "4"
- "5"
- "6"
- "7"
- "8"
- "9"
- "10"
- "11"
- "12"
- "13"
- "14"
- "15"
- "16"
- "17"
- "18"
- "19"
- "20"
- "21"
- "22"
# Use supported versions of our testing tools under older versions of Node
# Install npm in some specific cases where we need to
include:
- node-version: "0.10"
npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0"
# Npm isn't being installed on windows w/ setup-node for
# 0.10 and 0.12, which will end up choking when npm uses es6
npm-version: "npm@2.15.1"

- node-version: "0.12"
npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0"
npm-version: "npm@2.15.11"

- node-version: "4"
npm-i: "mocha@5.2.0 nyc@11.9.0 supertest@3.4.2"

- node-version: "5"
npm-i: "mocha@5.2.0 nyc@11.9.0 supertest@3.4.2"
# fixes https://github.com/npm/cli/issues/681
npm-version: "npm@3.10.10"

- node-version: "6"
npm-i: "mocha@6.2.2 nyc@14.1.1 supertest@3.4.2"

- node-version: "7"
npm-i: "mocha@6.2.2 nyc@14.1.1 supertest@6.1.6"

- node-version: "8"
npm-i: "mocha@7.2.0 nyc@14.1.1"

- node-version: "9"
npm-i: "mocha@7.2.0 nyc@14.1.1"

- node-version: "10"
npm-i: "mocha@8.4.0"

- node-version: "11"
npm-i: "mocha@8.4.0"

- node-version: "12"
npm-i: "mocha@9.2.2"

- node-version: "13"
npm-i: "mocha@9.2.2"

runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}

- name: Npm version fixes
if: ${{matrix.npm-version != ''}}
run: npm install -g ${{ matrix.npm-version }}

- name: Configure npm loglevel
run: |
npm config set loglevel error
shell: bash

- name: Install dependencies
run: npm install

- name: Install Node version specific dev deps
if: ${{ matrix.npm-i != '' }}
run: npm install --save-dev ${{ matrix.npm-i }}

- name: Remove non-test dependencies
run: npm rm --silent --save-dev connect-redis

- name: Output Node and NPM versions
run: |
echo "Node.js version: $(node -v)"
echo "NPM version: $(npm -v)"
- name: Run tests
shell: bash
run: |
npm run test-ci
cp coverage/lcov.info "coverage/${{ matrix.node-version }}.lcov"
- name: Collect code coverage
run: |
mv ./coverage "./${{ matrix.node-version }}"
mkdir ./coverage
mv "./${{ matrix.node-version }}" "./coverage/${{ matrix.node-version }}"
- 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 }}
66 changes: 66 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: ["master"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["master"]
schedule:
- cron: "0 0 * * 1"

permissions:
contents: read

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7
with:
languages: javascript
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
# - name: Autobuild
# uses: github/codeql-action/autobuild@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7
with:
category: "/language:javascript"
69 changes: 69 additions & 0 deletions .github/workflows/iojs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: iojs-ci

on:
push:
branches:
- master
- '4.x'
paths-ignore:
- '*.md'
pull_request:
paths-ignore:
- '*.md'

concurrency:
group: "${{ github.workflow }} ✨ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: ["1.8", "2.5", "3.3"]
include:
- node-version: "1.8"
npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0"
- node-version: "2.5"
npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0"
- node-version: "3.3"
npm-i: "mocha@3.5.3 nyc@10.3.2 supertest@2.0.0"

steps:
- uses: actions/checkout@v4

- name: Install iojs ${{ 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
npm config set shrinkwrap false
- 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: 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

22 changes: 6 additions & 16 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
# OS X
.DS_Store*
Icon?
._*

# Windows
Thumbs.db
ehthumbs.db
Desktop.ini

# Linux
.directory
*~


# npm
node_modules
package-lock.json
npm-shrinkwrap.json
*.log
*.gz


# Coveralls
.nyc_output
coverage

# Benchmarking
benchmarks/graphs

# ignore additional files using core.excludesFile
# https://git-scm.com/docs/gitignore
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
10 changes: 0 additions & 10 deletions .travis.yml

This file was deleted.

92 changes: 92 additions & 0 deletions Charter.md
Original file line number Diff line number Diff line change
@@ -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 changes: 139 additions & 0 deletions Code-Of-Conduct.md
Original file line number Diff line number Diff line change
@@ -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.
51 changes: 51 additions & 0 deletions Collaborator-Guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Express Collaborator Guide

## Website Issues

Open issues for the expressjs.com website in https://github.com/expressjs/expressjs.com.

## PRs and Code contributions

* Tests must pass.
* Follow the [JavaScript Standard Style](http://standardjs.com/) and `npm run lint`.
* If you fix a bug, add a test.

## Branches

Use the `master` branch for bug fixes or minor work that is intended for the
current release stream.

Use the correspondingly named branch, e.g. `5.0`, for anything intended for
a future release of Express.

## Steps for contributing

1. [Create an issue](https://github.com/expressjs/express/issues/new) for the
bug you want to fix or the feature that you want to add.
2. Create your own [fork](https://github.com/expressjs/express) on GitHub, then
checkout your fork.
3. Write your code in your local copy. It's good practice to create a branch for
each new issue you work on, although not compulsory.
4. To run the test suite, first install the dependencies by running `npm install`,
then run `npm test`.
5. Ensure your code is linted by running `npm run lint` -- fix any issue you
see listed.
6. If the tests pass, you can commit your changes to your fork and then create
a pull request from there. Make sure to reference your issue from the pull
request comments by including the issue number e.g. `#123`.

## Issues which are questions

We will typically close any vague issues or questions that are specific to some
app you are writing. Please double check the docs and other references before
being trigger happy with posting a question issue.

Things that will help get your question issue looked at:

* Full and runnable JS code.
* Clear description of the problem or unexpected behavior.
* Clear description of the expected result.
* Steps you have taken to debug it yourself.

If you post a question and do not outline the above items or make it easy for
us to understand and reproduce your issue, it will be closed.
212 changes: 198 additions & 14 deletions Contributing.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,209 @@
# Express.js Community Contributing Guide 1.0

## Website Issues
The goal of this document is to create a contribution process that:

Issues for the expressjs.com website go here https://github.com/strongloop/expressjs.com
* Encourages new contributions.
* Encourages contributors to remain involved.
* Avoids unnecessary processes and bureaucracy whenever possible.
* Creates a transparent decision making process that makes it clear how
contributors can be involved in decision making.

## PRs and Code contributions
## Vocabulary

* Tests must pass.
* Follow existing coding style.
* If you fix a bug, add a test.
* A **Contributor** is any individual creating or commenting on an issue or pull request.
* A **Committer** is a subset of contributors who have been given write access to the repository.
* A **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

## Issues which are questions
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 disclosures which should be sent privately.

We will typically close any vague issues or questions that are specific to some app you are writing. Please double check the docs and other references before being trigger happy with posting a question issue.
Committers may direct you to another repository, ask for additional clarifications, and
add appropriate metadata before the issue is addressed.

Things that will help get your question issue looked at:
Please be courteous and respectful. Every participant is expected to follow the
project's Code of Conduct.

* Full and runnable JS code.
* Clear description of the problem or unexpected behavior.
* Clear description of the expected result.
* Steps you have taken to debug it yourself.
## Contributions

If you post a question and do not outline the above items or make it easy for us to understand and reproduce your issue, it will be closed.
Any change to resources in this repository must be through pull requests. This applies to all changes
to documentation, code, binary files, etc. Even long term committers and TC members must use
pull requests.

No pull request can be merged without being reviewed.

For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that
contributors in other timezones have time to review. Consideration should also be given to
weekends and other holiday periods to ensure active committers all have reasonable time to
become involved in the discussion and review process if they wish.

The default for each contribution is that it is accepted once no committer has an objection.
During 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.

In the case of an objection being raised in a pull request by another committer, all involved
committers should seek to arrive at a consensus by way of addressing concerns being expressed
by discussion, compromise on the proposed change, or withdrawal of the proposed change.

If a contribution is controversial and committers cannot agree about how to get it to land
or if it should land then it should be escalated to the TC. TC members should regularly
discuss pending contributions in order to find a resolution. It is expected that only a
small minority of issues be brought to the TC for resolution and that discussion and
compromise among committers be the default resolution mechanism.

## Becoming a Triager

Anyone can become a triager! Read more about the process of being a triager in
[the triage process document](Triager-Guide.md).

Currently, any existing [organization member](https://github.com/orgs/expressjs/people) can nominate
a new triager. If you are interested in becoming a triager, our best advice is to actively participate
in the community by helping triaging issues and pull requests. As well we recommend
to engage in other community activities like attending the TC meetings, and participating in the Slack
discussions.

You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people)
if you have questions or need guidance.

## Becoming a Committer

All contributors who land a non-trivial contribution should be on-boarded in a timely manner,
and added as a committer, and be given write access to the repository.

Committers are expected to follow this policy and continue to send pull requests, go through
proper review, and have other committers merge their pull requests.

## TC Process

The TC uses a "consensus seeking" process for issues that are escalated to the TC.
The group tries to find a resolution that has no open objections among TC members.
If a consensus cannot be reached that has no objections then a majority wins vote
is called. It is also expected that the majority of decisions made by the TC are via
a consensus seeking process and that voting is only used as a last-resort.

Resolution may involve returning the issue to 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 project captains.

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. 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.

### Active Projects and Captains

- `expressjs/badgeboard`: @wesleytodd
- `expressjs/basic-auth-connect`: N/A
- `expressjs/body-parser`: @wesleytodd, @jonchurch
- `expressjs/compression`: N/A
- `expressjs/connect-multiparty`: N/A
- `expressjs/cookie-parser`: @wesleytodd, @UlisesGascon
- `expressjs/cookie-session`: N/A
- `expressjs/cors`: @jonchurch
- `expressjs/discussions`: @wesleytodd
- `expressjs/errorhandler`: N/A
- `expressjs/express-paginate`: N/A
- `expressjs/express`: @wesleytodd
- `expressjs/expressjs.com`: @crandmck, @jonchurch
- `expressjs/flash`: N/A
- `expressjs/generator`: @wesleytodd
- `expressjs/method-override`: N/A
- `expressjs/morgan`: @jonchurch
- `expressjs/multer`: @LinusU
- `expressjs/response-time`: @blakeembrey
- `expressjs/serve-favicon`: N/A
- `expressjs/serve-index`: N/A
- `expressjs/serve-static`: N/A
- `expressjs/session`: N/A
- `expressjs/statusboard`: @wesleytodd
- `expressjs/timeout`: N/A
- `expressjs/vhost`: N/A
- `jshttp/accepts`: @blakeembrey
- `jshttp/basic-auth`: @blakeembrey
- `jshttp/compressible`: @blakeembrey
- `jshttp/content-disposition`: @blakeembrey
- `jshttp/content-type`: @blakeembrey
- `jshttp/cookie`: @wesleytodd
- `jshttp/etag`: @blakeembrey
- `jshttp/forwarded`: @blakeembrey
- `jshttp/fresh`: @blakeembrey
- `jshttp/http-assert`: @wesleytodd, @jonchurch
- `jshttp/http-errors`: @wesleytodd, @jonchurch
- `jshttp/media-typer`: @blakeembrey
- `jshttp/methods`: @blakeembrey
- `jshttp/mime-db`: @blakeembrey, @UlisesGascon
- `jshttp/mime-types`: @blakeembrey, @UlisesGascon
- `jshttp/negotiator`: @blakeembrey
- `jshttp/on-finished`: @wesleytodd
- `jshttp/on-headers`: @blakeembrey
- `jshttp/proxy-addr`: @wesleytodd
- `jshttp/range-parser`: @blakeembrey
- `jshttp/statuses`: @blakeembrey
- `jshttp/type-is`: @blakeembrey
- `jshttp/vary`: @blakeembrey
- `pillarjs/cookies`: @blakeembrey
- `pillarjs/csrf`: N/A
- `pillarjs/encodeurl`: @blakeembrey
- `pillarjs/finalhandler`: @wesleytodd
- `pillarjs/hbs`: N/A
- `pillarjs/multiparty`: @blakeembrey
- `pillarjs/parseurl`: @blakeembrey
- `pillarjs/path-to-regexp`: @blakeembrey
- `pillarjs/request`: @wesleytodd
- `pillarjs/resolve-path`: @blakeembrey
- `pillarjs/router`: @blakeembrey
- `pillarjs/send`: @blakeembrey
- `pillarjs/understanding-csrf`: N/A

### Current Initiative Captains

- Triage team [ref](https://github.com/expressjs/discussions/issues/227): @UlisesGascon
841 changes: 827 additions & 14 deletions History.md

Large diffs are not rendered by default.

125 changes: 125 additions & 0 deletions Readme-Guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# README guidelines

Every module in the expressjs, pillarjs, and jshttp organizations should have
a README file named `README.md`. The purpose of the README is to:

- Explain the purpose of the module and how to use it.
- Act as a landing page (both on GitHub and npmjs.com) for the module to help
people find it via search. Middleware module READMEs are also incorporated
into https://expressjs.com/en/resources/middleware.html.
- Encourage community contributions and participation.

Use the [README template](https://github.com/expressjs/express/wiki/README-template)
to quickly create a new README file.

## Top-level items

**Badges** (optional): At the very top (with no subheading), include any
applicable badges, such as npm version/downloads, build status, test coverage,
and so on. Badges should resolve properly (not display a broken image).

Possible badges include:
- npm version: `[![NPM Version][npm-image]][npm-url]`
- npm downloads: `[![NPM Downloads][downloads-image]][downloads-url]`
- Build status: `[![Build Status][travis-image]][travis-url]`
- Test coverage: `[![Test Coverage][coveralls-image]][coveralls-url]`
- Tips: `[![Gratipay][gratipay-image]][gratipay-url]`

**Summary**: Following badges, provide a one- or two-sentence description of
what the module does. This should be the same as the npmjs.org blurb (which
comes from the description property of `package.json`). Since npm doesn't
handle markdown for the blurb, avoid using markdown in the summary sentence.

**TOC** (Optional): For longer READMEs, provide a table of contents that has
a relative link to each section. A tool such as
[doctoc](https://www.npmjs.com/package/doctoc) makes it very easy to generate
a TOC.

## Overview

Optionally, include a section of one or two paragraphs with more high-level
information on what the module does, what problems it solves, why one would
use it and how. Don't just repeat what's in the summary.

## Installation

Required. This section is typically just:

```sh
$ npm install module-name
```

But include any other steps or requirements.

NOTE: Use the `sh` code block to make the shell command display properly on
the website.

## Basic use

- Provide a general description of how to use the module with code sample.
Include any important caveats or restrictions.
- Explain the most common use cases.
- Optional: a simple "hello world" type example (where applicable). This
example is in addition to the more comprehensive [example section](#examples)
later.

## API

Provide complete API documentation.

Formatting conventions: Each function is listed in a 3rd-level heading (`###`),
like this:

```
### Function_name(arg, options [, optional_arg] ... )
```

**Options objects**

For arguments that are objects (for example, options object), describe the
properties in a table, as follows. This matches the formatting used in the
[Express API docs](https://expressjs.com/en/4x/api.html).

|Property | Description | Type | Default|
|----------|-----------|------------|-------------|
|Name of the property in `monospace`. | Brief description | String, Number, Boolean, etc. | If applicable.|

If all the properties are required (i.e. there are no defaults), then you
can omit the default column.

Instead of very lengthy descriptions, link out to subsequent paragraphs for
more detailed explanation of specific cases (e.g. "When this property is set
to 'foobar', xyz happens; see <link to following section >.)

If there are options properties that are themselves options, use additional
tables. See [`trust proxy` and `etag` properties](https://expressjs.com/en/4x/api.html#app.settings.table).

## Examples

Every README should have at least one example; ideally more. For code samples,
be sure to use the `js` code block, for proper display in the website, e.g.:

```js
var csurf = require('csurf')
...
```

## Tests

What tests are included.

How to run them.

The convention for running tests is `npm test`. All our projects should follow
this convention.

## Contributors

Names of module "owners" (lead developers) and other developers who have
contributed.

## License

Link to the license, with a short description of what it is, e.g. "MIT" or
whatever. Ideally, avoid putting the license text directly in the README; link
to it instead.
210 changes: 166 additions & 44 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
[![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).**

**This project has a [Code of Conduct][].**

## Table of contents

* [Installation](#Installation)
* [Features](#Features)
* [Docs & Community](#docs--community)
* [Quick Start](#Quick-Start)
* [Running Tests](#Running-Tests)
* [Philosophy](#Philosophy)
* [Examples](#Examples)
* [Contributing to Express](#Contributing)
* [TC (Technical Committee)](#tc-technical-committee)
* [Triagers](#triagers)
* [License](#license)


[![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]
[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]

[![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]

```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 +38,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
@@ -37,48 +69,49 @@ $ npm install express

## Docs & Community

* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/strongloop/expressjs.com)]
* [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
* [Github Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/strongloop/express/wiki)
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
* [#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
* [Русскоязычная документация](http://jsman.ru/express/)
* [한국어 문서](http://expressjs.kr) - [[website repo](https://github.com/Hanul/expressjs.kr)]
* [Gitter](https://gitter.im/expressjs/express) for support and discussion

**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/strongloop/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/strongloop/express/wiki/New-features-in-4.x).
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x).

## 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
@@ -89,50 +122,139 @@ $ npm start

To view the examples, clone the Express repo and install the dependencies:

```bash
$ git clone git://github.com/strongloop/express.git --depth 1
```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

[![Linux Build][github-actions-ci-image]][github-actions-ci-url]
[![Windows Build][appveyor-image]][appveyor-url]
[![Test Coverage][coveralls-image]][coveralls-url]

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.

To run the test suite, first install the dependencies, then run `npm test`:
### Security Issues

```bash
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)

[List of all contributors](https://github.com/expressjs/express/graphs/contributors)

### TC (Technical Committee)

* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
* [jonchurch](https://github.com/jonchurch) - **Jon Church**
* [wesleytodd](https://github.com/wesleytodd) - **Wes Todd**
* [LinusU](https://github.com/LinusU) - **Linus Unnebäck**
* [blakeembrey](https://github.com/blakeembrey) - **Blake Embrey**
* [sheplu](https://github.com/sheplu) - **Jean Burellier**
* [crandmck](https://github.com/crandmck) - **Rand McKinney**
* [ctcpip](https://github.com/ctcpip) - **Chris de Almeida**

<details>
<summary>TC emeriti members</summary>

#### TC emeriti members

* [dougwilson](https://github.com/dougwilson) - **Douglas Wilson**
* [hacksparrow](https://github.com/hacksparrow) - **Hage Yaapa**
* [jonathanong](https://github.com/jonathanong) - **jongleberry**
* [niftylettuce](https://github.com/niftylettuce) - **niftylettuce**
* [troygoode](https://github.com/troygoode) - **Troy Goode**
</details>


### Triagers

* [aravindvnair99](https://github.com/aravindvnair99) - **Aravind Nair**
* [carpasse](https://github.com/carpasse) - **Carlos Serrano**
* [CBID2](https://github.com/CBID2) - **Christine Belzie**
* [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim**
* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
* [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin**
* [0ss](https://github.com/0ss) - **Salah**
* [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him)
* [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**
* [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him)
* [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego**
* [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him)
* [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**

<details>
<summary>Triagers emeriti members</summary>

#### Emeritus Triagers

* [AuggieH](https://github.com/AuggieH) - **Auggie Hudak**
* [G-Rath](https://github.com/G-Rath) - **Gareth Jones**
* [MohammadXroid](https://github.com/MohammadXroid) - **Mohammad Ayashi**
* [NawafSwe](https://github.com/NawafSwe) - **Nawaf Alsharqi**
* [NotMoni](https://github.com/NotMoni) - **Moni**
* [VigneshMurugan](https://github.com/VigneshMurugan) - **Vignesh Murugan**
* [davidmashe](https://github.com/davidmashe) - **David Ashe**
* [digitaIfabric](https://github.com/digitaIfabric) - **David**
* [e-l-i-s-e](https://github.com/e-l-i-s-e) - **Elise Bonner**
* [fed135](https://github.com/fed135) - **Frederic Charette**
* [firmanJS](https://github.com/firmanJS) - **Firman Abdul Hakim**
* [getspooky](https://github.com/getspooky) - **Yasser Ameur**
* [ghinks](https://github.com/ghinks) - **Glenn**
* [ghousemohamed](https://github.com/ghousemohamed) - **Ghouse Mohamed**
* [gireeshpunathil](https://github.com/gireeshpunathil) - **Gireesh Punathil**
* [jake32321](https://github.com/jake32321) - **Jake Reed**
* [jonchurch](https://github.com/jonchurch) - **Jon Church**
* [lekanikotun](https://github.com/lekanikotun) - **Troy Goode**
* [marsonya](https://github.com/marsonya) - **Lekan Ikotun**
* [mastermatt](https://github.com/mastermatt) - **Matt R. Wilson**
* [maxakuru](https://github.com/maxakuru) - **Max Edell**
* [mlrawlings](https://github.com/mlrawlings) - **Michael Rawlings**
* [rodion-arr](https://github.com/rodion-arr) - **Rodion Abdurakhimov**
* [sheplu](https://github.com/sheplu) - **Jean Burellier**
* [tarunyadav1](https://github.com/tarunyadav1) - **Tarun yadav**
* [tunniclm](https://github.com/tunniclm) - **Mike Tunnicliffe**
</details>

The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) [![Doug's Gratipay][gratipay-image-dougwilson]][gratipay-url-dougwilson]

[List of all contributors](https://github.com/strongloop/express/graphs/contributors)

## License

[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/strongloop/express/master.svg?label=linux
[travis-url]: https://travis-ci.org/strongloop/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/strongloop/express/master.svg
[coveralls-url]: https://coveralls.io/r/strongloop/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/
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master
[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
[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
[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge
[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/express
[Code of Conduct]: https://github.com/expressjs/express/blob/master/Code-Of-Conduct.md
199 changes: 199 additions & 0 deletions Release-Process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Express Release Process

This document contains the technical aspects of the Express release process. The
intended audience is those who have been authorized by the Express Technical
Committee (TC) to create, promote and sign official release builds for Express,
as npm packages hosted on https://npmjs.com/package/express.

## Who can make releases?

Release authorization is given by the Express TC. Once authorized, an individual
must have the following access permissions:

### 1. Github release access

The individual making the release will need to be a member of the
expressjs/express team with Write permission level so they are able to tag the
release commit and push changes to the expressjs/express repository
(see Steps 4 and 5).

### 2. npmjs.com release access

The individual making the release will need to be made an owner on the
`express` package on npmjs.com so they are able to publish the release
(see Step 6).

## How to publish a release

Before publishing, the following preconditions should be met:

- A release proposal issue or tracking pull request (see "Proposal branch"
below) will exist documenting:
- the proposed changes
- the type of release: patch, minor or major
- the version number (according to semantic versioning - http://semver.org)
- The proposed changes should be complete.

There are two main release flows: patch and non-patch.

The patch flow is for making **patch releases**. As per semantic versioning,
patch releases are for simple changes, eg: typo fixes, patch dependency updates,
and simple/low-risk bug fixes. Every other type of change is made via the
non-patch flow.

### Branch terminology

"Master branch"

- There is a branch in git used for the current major version of Express, named
`master`.
- This branch contains the completed commits for the next patch release of the
current major version.
- Releases for the current major version are published from this branch.

"Version branch"

- For any given major version of Express (current, previous or next) there is
a branch in git for that release named `<major-version>.x` (eg: `4.x`).
- This branch points to the commit of the latest tag for the given major version.

"Release branch"

- For any given major version of Express, there is a branch used for publishing
releases.
- For the current major version of Express, the release branch is the
"Master branch" named `master`.
- For all other major versions of Express, the release branch is the
"Version branch" named `<major-version>.x`.

"Proposal branch"

- A branch in git representing a proposed new release of Express. This can be a
minor or major release, named `<major-version>.0` for a major release,
`<major-version>.<minor-version>` for a minor release.
- A tracking pull request should exist to document the proposed release,
targeted at the appropriate release branch. Prior to opening the tracking
pull request the content of the release may have be discussed in an issue.
- This branch contains the commits accepted so far that implement the proposal
in the tracking pull request.

### Pre-release Versions

Alpha and Beta releases are made from a proposal branch. The version number should be
incremented to the next minor version with a `-beta` or `-alpha` suffix.
For example, if the next beta release is `5.0.1`, the beta release would be `5.0.1-beta.0`.
The pre-releases are unstable and not suitable for production use.

### Patch flow

In the patch flow, simple changes are committed to the release branch which
acts as an ever-present branch for the next patch release of the associated
major version of Express.

The release branch is usually kept in a state where it is ready to release.
Releases are made when sufficient time or change has been made to warrant it.
This is usually proposed and decided using a github issue.

### Non-patch flow

In the non-patch flow, changes are committed to a temporary proposal branch
created specifically for that release proposal. The branch is based on the
most recent release of the major version of Express that the release targets.

Releases are made when all the changes on a proposal branch are complete and
approved. This is done by merging the proposal branch into the release branch
(using a fast-forward merge), tagging it with the new version number and
publishing the release package to npmjs.com.

### Flow

Below is a detailed description of the steps to publish a release.

#### Step 1. Check the release is ready to publish

Check any relevant information to ensure the release is ready, eg: any
milestone, label, issue or tracking pull request for the release. The release
is ready when all proposed code, tests and documentation updates are complete
(either merged, closed or re-targeted to another release).

#### Step 2. (Non-patch flow only) Merge the proposal branch into the release branch

In the patch flow: skip this step.

In the non-patch flow:
```sh
$ git checkout <release-branch>
$ git merge --ff-only <proposal-branch>
```

<release-branch> - see "Release branch" of "Branches" above.
<proposal-branch> - see "Proposal branch" of "Non-patch flow" above.

**NOTE:** You may need to rebase the proposal branch to allow a fast-forward
merge. Using a fast-forward merge keeps the history clean as it does
not introduce merge commits.

### Step 3. Update the History.md and package.json to the new version number

The changes so far for the release should already be documented under the
"unreleased" section at the top of the History.md file, as per the usual
development practice. Change "unreleased" to the new release version / date.
Example diff fragment:

```diff
-unreleased
-==========
+4.13.3 / 2015-08-02
+===================
```

The version property in the package.json should already contain the version of
the previous release. Change it to the new release version.

Commit these changes together under a single commit with the message set to
the new release version (eg: `4.13.3`):

```sh
$ git checkout <release-branch>
<..edit files..>
$ git add History.md package.json
$ git commit -m '<version-number>'
```

### Step 4. Identify and tag the release commit with the new release version

Create a lightweight tag (rather than an annotated tag) named after the new
release version (eg: `4.13.3`).

```sh
$ git tag <version-number>
```

### Step 5. Push the release branch changes and tag to github

The branch and tag should be pushed directly to the main repository
(https://github.com/expressjs/express).

```sh
$ git push origin <release-branch>
$ git push origin <version-number>
```

### Step 6. Publish to npmjs.com

Ensure your local working copy is completely clean (no extra or changed files).
You can use `git status` for this purpose.

```sh
$ npm login <npm-username>
$ npm publish
```

**NOTE:** The version number to publish will be picked up automatically from
package.json.

### 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,
56 changes: 56 additions & 0 deletions Security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Security Policies and Procedures

This document outlines security procedures and general policies for the Express
project.

* [Reporting a Bug](#reporting-a-bug)
* [Disclosure Policy](#disclosure-policy)
* [Comments on this Policy](#comments-on-this-policy)

## Reporting a Bug

The Express team and community take all security bugs in Express seriously.
Thank you for improving the security of Express. We appreciate your efforts and
responsible disclosure and will make every effort to acknowledge your
contributions.

Report security bugs by emailing the lead maintainer in the Readme.md file.

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
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.

## Pre-release Versions

Alpha and Beta releases are unstable and **not suitable for production use**.
Vulnerabilities found in pre-releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section.
Due to the unstable nature of the branch it is not guaranteed that any fixes will be released in the next pre-release.

## Disclosure Policy

When the security team receives a security bug report, they will assign it to a
primary handler. This person will coordinate the fix and release process,
involving the following steps:

* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* Prepare fixes for all releases still under maintenance. These fixes will be
released as fast as possible to npm.

## The Express Threat Model

We are currently working on a new version of the security model, the most updated version can be found [here](https://github.com/expressjs/security-wg/blob/main/docs/ThreatModel.md)

## Comments on this Policy

If you have suggestions on how this process could be improved please submit a
pull request.
70 changes: 70 additions & 0 deletions Triager-Guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# 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.
* `bug`: Issues that present a reasonable conviction there is a reproducible bug.
* `enhancement`: Issues that are found to be a reasonable candidate feature additions.

If the issue is a question or discussion, it should be moved to GitHub Discussions.

### Moving Discussions and Questions to GitHub Discussions

For issues labeled with `question` or `discuss`, it is recommended to move them to GitHub Discussions instead:

* **Questions**: User questions that do not appear to be bugs or enhancements should be moved to GitHub Discussions.
* **Discussions**: Topics for discussion should be moved to GitHub Discussions. If the discussion leads to a new feature or bug identification, it can be moved back to Issues.

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.
107 changes: 102 additions & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -2,15 +2,112 @@ environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "1.0"
- nodejs_version: "1.8"
- nodejs_version: "2.5"
- nodejs_version: "3.3"
- nodejs_version: "4.9"
- nodejs_version: "5.12"
- 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"
- nodejs_version: "22.0"
cache:
- node_modules
install:
- ps: Install-Product node $env:nodejs_version
- npm rm --save-dev connect-redis
# Install Node.js
- ps: >-
try { Install-Product node $env:nodejs_version -ErrorAction Stop }
catch { Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) 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
version: "{build}"
20 changes: 12 additions & 8 deletions benchmarks/Makefile
Original file line number Diff line number Diff line change
@@ -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 changes: 34 additions & 0 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -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`.
7 changes: 2 additions & 5 deletions benchmarks/middleware.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

var http = require('http');
var express = require('..');
var app = express();

@@ -14,10 +13,8 @@ while (n--) {
});
}

var body = new Buffer('Hello World');

app.use(function(req, res, next){
res.send(body);
app.use(function(req, res){
res.send('Hello World')
});

app.listen(3333);
8 changes: 5 additions & 3 deletions benchmarks/run
Original file line number Diff line number Diff line change
@@ -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 changes: 29 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -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
23 changes: 13 additions & 10 deletions examples/auth/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
'use strict'

/**
* Module dependencies.
*/

var express = require('../..');
var hash = require('./pass').hash;
var bodyParser = require('body-parser');
var hash = require('pbkdf2-password')()
var path = require('path');
var session = require('express-session');

var app = module.exports = express();

// config

app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));

// middleware

app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: false }))
app.use(session({
resave: false, // don't save session if unmodified
saveUninitialized: false, // don't create session until something stored
@@ -45,7 +47,7 @@ var users = {
// when you create a user, generate a salt
// and hash the password ('foobar' is the pass here)

hash('foobar', function(err, salt, hash){
hash({ password: 'foobar' }, function (err, pass, salt, hash) {
if (err) throw err;
// store the salt & hash in the "db"
users.tj.salt = salt;
@@ -59,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(pass, user.salt, function(err, hash){
hash({ password: pass, salt: user.salt }, function (err, pass, salt, hash) {
if (err) return fn(err);
if (hash == user.hash) return fn(null, user);
fn(new Error('invalid password'));
if (hash === user.hash) return fn(null, user)
fn(null, null)
});
}

@@ -99,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
48 changes: 0 additions & 48 deletions examples/auth/pass.js

This file was deleted.

2 changes: 2 additions & 0 deletions examples/auth/views/head.ejs
Original file line number Diff line number Diff line change
@@ -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 {
13 changes: 6 additions & 7 deletions examples/auth/views/login.ejs
Original file line number Diff line number Diff line change
@@ -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') -%>
31 changes: 0 additions & 31 deletions examples/big-view/index.js

This file was deleted.

12 changes: 0 additions & 12 deletions examples/big-view/pets.jade

This file was deleted.

4 changes: 3 additions & 1 deletion examples/content-negotiation/db.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
'use strict'

var users = [];

users.push({ name: 'Tobi' });
users.push({ name: 'Loki' });
users.push({ name: 'Jane' });

module.exports = users;
module.exports = users;
2 changes: 2 additions & 0 deletions examples/content-negotiation/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

var express = require('../../');
var app = module.exports = express();
var users = require('./db');
1 change: 1 addition & 0 deletions examples/content-negotiation/users.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use strict'

var users = require('./db');

14 changes: 6 additions & 8 deletions examples/cookie-sessions/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

/**
* Module dependencies.
*/
@@ -11,14 +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) {
req.session.count = req.session.count || 0;
var n = req.session.count++;
res.send('viewed ' + n + ' times\n');
}
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) {
7 changes: 4 additions & 3 deletions examples/cookies/index.js
Original file line number Diff line number Diff line change
@@ -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) {
3 changes: 3 additions & 0 deletions examples/downloads/files/notes/groceries.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* milk
* eggs
* bread
25 changes: 15 additions & 10 deletions examples/downloads/index.js
Original file line number Diff line number Diff line change
@@ -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 file = req.params.file;
var path = __dirname + '/files/' + file;

res.download(path, 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!');
9 changes: 8 additions & 1 deletion examples/ejs/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
'use strict'

/**
* Module dependencies.
*/

var express = require('../../');
var path = require('path');

var app = module.exports = express();

@@ -21,7 +24,11 @@ app.engine('.html', require('ejs').__express);

// Optional since express defaults to CWD/views

app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));

// Path to our public directory

app.use(express.static(path.join(__dirname, 'public')));

// Without this you would need to
// supply the extension to res.render()
4 changes: 4 additions & 0 deletions examples/ejs/public/stylesheets/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
body {
padding: 50px 80px;
font: 14px "Helvetica Neue", "Lucida Grande", Arial, sans-serif;
}
10 changes: 3 additions & 7 deletions examples/ejs/views/header.html
Original file line number Diff line number Diff line change
@@ -2,12 +2,8 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title> <%= title %> </title>
<style type="text/css">
body {
padding: 50px;
font: 13px Helvetica, Arial, sans-serif;
}
</style>
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><%= title %></title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
4 changes: 2 additions & 2 deletions examples/ejs/views/users.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<% include header.html %>
<%- include('header.html') -%>

<h1>Users</h1>
<ul id="users">
@@ -7,4 +7,4 @@ <h1>Users</h1>
<% }) %>
</ul>

<% include footer.html %>
<%- include('footer.html') -%>
34 changes: 17 additions & 17 deletions examples/error-pages/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
'use strict'

/**
* Module dependencies.
*/

var express = require('../../');
var path = require('path');
var app = module.exports = express();
var logger = require('morgan');
var silent = 'test' == process.env.NODE_ENV;
var silent = process.env.NODE_ENV === 'test'

// general config
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// our custom "verbose errors" setting
@@ -18,7 +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'));

@@ -60,20 +63,17 @@ app.get('/500', function(req, res, next){
app.use(function(req, res, next){
res.status(404);

// respond with html page
if (req.accepts('html')) {
res.render('404', { url: req.url });
return;
}

// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}

// default to plain-text. send()
res.type('txt').send('Not found');
res.format({
html: function () {
res.render('404', { url: req.url })
},
json: function () {
res.json({ error: 'Not found' })
},
default: function () {
res.type('txt').send('Not found')
}
})
});

// error-handling middleware, take the same form
4 changes: 2 additions & 2 deletions examples/error-pages/views/404.ejs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<% include error_header %>
<%- include('error_header') -%>
<h2>Cannot find <%= url %></h2>
<% include footer %>
<%- include('footer') -%>
4 changes: 2 additions & 2 deletions examples/error-pages/views/500.ejs
Original file line number Diff line number Diff line change
@@ -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') -%>
2 changes: 2 additions & 0 deletions examples/error-pages/views/error_header.ejs
Original file line number Diff line number Diff line change
@@ -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>

2 changes: 2 additions & 0 deletions examples/error-pages/views/index.ejs
Original file line number Diff line number Diff line change
@@ -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>

9 changes: 7 additions & 2 deletions examples/error/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
'use strict'

/**
* Module dependencies.
*/

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,13 +26,16 @@ 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!');
});

app.get('/next', function(req, res, next){
// We can also pass exceptions to next()
// The reason for process.nextTick() is to show that
// next() can be called inside an async operation,
// in real life it can be a DB read or HTTP request.
process.nextTick(function(){
next(new Error('oh no!'));
});
64 changes: 0 additions & 64 deletions examples/expose-data-to-client/index.js

This file was deleted.

14 changes: 0 additions & 14 deletions examples/expose-data-to-client/views/page.jade

This file was deleted.

4 changes: 3 additions & 1 deletion examples/hello-world/index.js
Original file line number Diff line number Diff line change
@@ -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');
51 changes: 0 additions & 51 deletions examples/jade/index.js

This file was deleted.

4 changes: 0 additions & 4 deletions examples/jade/public/stylesheets/style.css

This file was deleted.

3 changes: 0 additions & 3 deletions examples/jade/views/header.jade

This file was deleted.

5 changes: 0 additions & 5 deletions examples/jade/views/layout.jade

This file was deleted.

8 changes: 0 additions & 8 deletions examples/jade/views/users/index.jade

This file was deleted.

3 changes: 0 additions & 3 deletions examples/jade/views/users/user.jade

This file was deleted.

23 changes: 11 additions & 12 deletions examples/markdown/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
'use strict'

/**
* Module dependencies.
*/

var escapeHtml = require('escape-html');
var express = require('../..');
var fs = require('fs');
var md = require('marked').parse;
var marked = require('marked');
var path = require('path');

var app = module.exports = express();

@@ -13,21 +17,16 @@ var app = module.exports = express();
app.engine('md', function(path, options, fn){
fs.readFile(path, 'utf8', function(err, str){
if (err) return fn(err);
try {
var html = md(str);
html = html.replace(/\{([^}]+)\}/g, function(_, name){
return options[name] || '';
});
fn(null, html);
} catch(err) {
fn(err);
}
var html = marked.parse(str).replace(/\{([^}]+)\}/g, function(_, name){
return escapeHtml(options[name] || '');
});
fn(null, html);
});
});

app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));

// make it the default so we dont need .md
// make it the default, so we don't need .md
app.set('view engine', 'md');

app.get('/', function(req, res){
2 changes: 2 additions & 0 deletions examples/multi-router/controllers/api_v1.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

var express = require('../../..');

var apiv1 = express.Router();
2 changes: 2 additions & 0 deletions examples/multi-router/controllers/api_v2.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

var express = require('../../..');

var apiv2 = express.Router();
4 changes: 3 additions & 1 deletion examples/multi-router/index.js
Original file line number Diff line number Diff line change
@@ -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 */
60 changes: 0 additions & 60 deletions examples/multipart/index.js

This file was deleted.

4 changes: 3 additions & 1 deletion examples/mvc/controllers/main/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

exports.index = function(req, res){
res.redirect('/users');
};
};
2 changes: 2 additions & 0 deletions examples/mvc/controllers/pet/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

/**
* Module dependencies.
*/
2 changes: 2 additions & 0 deletions examples/mvc/controllers/pet/views/edit.ejs
Original file line number Diff line number Diff line change
@@ -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>
2 changes: 2 additions & 0 deletions examples/mvc/controllers/pet/views/show.ejs
Original file line number Diff line number Diff line change
@@ -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>
2 changes: 2 additions & 0 deletions examples/mvc/controllers/user-pet/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

/**
* Module dependencies.
*/
4 changes: 4 additions & 0 deletions examples/mvc/controllers/user/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
'use strict'

/**
* Module dependencies.
*/

var db = require('../../db');

exports.engine = 'hbs';

exports.before = function(req, res, next){
var id = req.params.user_id;
if (!id) return next();
27 changes: 27 additions & 0 deletions examples/mvc/controllers/user/views/edit.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!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>
<body>
<h1>{{user.name}}</h1>
<form action="/user/{{user.id}}?_method=put" method="post">
<label for="user[name]">Name:
<input type="text" name="user[name]" value="{{user.name}}">
</label>

<input type="submit" name="submit" value="Update">
</form>

<form action="/user/{{user.id}}/pet" method="post">
<label for="pet[name]">Pet:
<input type="text" name="pet[name]" placeholder="Pet Name">
</label>

<input type="submit" name="submit" value="Add">
</form>
</body>
</html>
11 changes: 0 additions & 11 deletions examples/mvc/controllers/user/views/edit.jade

This file was deleted.

18 changes: 18 additions & 0 deletions examples/mvc/controllers/user/views/list.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!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>
<body>
<h1>Users</h1>
<p>Click a user below to view their pets.</p>
<ul>
{{#each users}}
<li><a href="/user/{{id}}">{{name}}</a></li>
{{/each}}
</ul>
</body>
</html>
7 changes: 0 additions & 7 deletions examples/mvc/controllers/user/views/list.jade

This file was deleted.

31 changes: 31 additions & 0 deletions examples/mvc/controllers/user/views/show.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!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>
<body>
<h1>{{user.name}} <a href="/user/{{user.id}}/edit">edit</a></h1>

{{#if hasMessages}}
<ul>
{{#each messages}}
<li>{{this}}</li>
{{/each}}
</ul>
{{/if}}

{{#if user.pets.length}}
<p>View {{user.name}}'s pets:</p>
<ul>
{{#each user.pets}}
<li><a href="/pet/{{id}}">{{name}}</a></li>
{{/each}}
</ul>
{{else}}
<p>No pets!</p>
{{/if}}
</body>
</html>
17 changes: 0 additions & 17 deletions examples/mvc/controllers/user/views/show.jade

This file was deleted.

4 changes: 3 additions & 1 deletion examples/mvc/db.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

// faux database

var pets = exports.pets = [];
@@ -11,4 +13,4 @@ var users = exports.users = [];

users.push({ name: 'TJ', pets: [pets[0], pets[1], pets[2]], id: 0 });
users.push({ name: 'Guillermo', pets: [pets[3]], id: 1 });
users.push({ name: 'Nathan', pets: [], id: 2 });
users.push({ name: 'Nathan', pets: [], id: 2 });
18 changes: 9 additions & 9 deletions examples/mvc/index.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
'use strict'

/**
* Module dependencies.
*/

var express = require('../..');
var logger = require('morgan');
var path = require('path');
var session = require('express-session');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');

var app = module.exports = express();

// settings

// set our default template engine to "jade"
// which prevents the need for extensions
app.set('view engine', 'jade');
// set our default template engine to "ejs"
// which prevents the need for using file extensions
app.set('view engine', 'ejs');

// set views for error and 404 pages
app.set('views', __dirname + '/views');
app.set('views', path.join(__dirname, 'views'));

// define a custom res.message() method
// which stores messages in the session
@@ -34,7 +34,7 @@ app.response.message = function(msg){
if (!module.parent) app.use(logger('dev'));

// serve static files
app.use(express.static(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));

// session support
app.use(session({
@@ -44,7 +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'));
36 changes: 21 additions & 15 deletions examples/mvc/lib/boot.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
'use strict'

/**
* Module dependencies.
*/

var express = require('../../..');
var fs = require('fs');
var path = require('path');

module.exports = function(parent, options){
var dir = path.join(__dirname, '..', 'controllers');
var verbose = options.verbose;
fs.readdirSync(__dirname + '/../controllers').forEach(function(name){
fs.readdirSync(dir).forEach(function(name){
var file = path.join(dir, name)
if (!fs.statSync(file).isDirectory()) return;
verbose && console.log('\n %s:', name);
var obj = require('./../controllers/' + name);
var obj = require(file);
var name = obj.name || name;
var prefix = obj.prefix || '';
var app = express();
var handler;
var method;
var path;
var url;

// allow specifying the view engine
if (obj.engine) app.set('view engine', obj.engine);
app.set('views', __dirname + '/../controllers/' + name + '/views');
app.set('views', path.join(__dirname, '..', 'controllers', name, 'views'));

// generate routes based
// on the exported methods
@@ -30,27 +36,27 @@ module.exports = function(parent, options){
switch (key) {
case 'show':
method = 'get';
path = '/' + name + '/:' + name + '_id';
url = '/' + name + '/:' + name + '_id';
break;
case 'list':
method = 'get';
path = '/' + name + 's';
url = '/' + name + 's';
break;
case 'edit':
method = 'get';
path = '/' + name + '/:' + name + '_id/edit';
url = '/' + name + '/:' + name + '_id/edit';
break;
case 'update':
method = 'put';
path = '/' + name + '/:' + name + '_id';
url = '/' + name + '/:' + name + '_id';
break;
case 'create':
method = 'post';
path = '/' + name;
url = '/' + name;
break;
case 'index':
method = 'get';
path = '/';
url = '/';
break;
default:
/* istanbul ignore next */
@@ -59,15 +65,15 @@ module.exports = function(parent, options){

// setup
handler = obj[key];
path = prefix + path;
url = prefix + url;

// before middleware support
if (obj.before) {
app[method](path, obj.before, handler);
verbose && console.log(' %s %s -> before -> %s', method.toUpperCase(), path, key);
app[method](url, obj.before, handler);
verbose && console.log(' %s %s -> before -> %s', method.toUpperCase(), url, key);
} else {
app[method](path, handler);
verbose && console.log(' %s %s -> %s', method.toUpperCase(), path, key);
app[method](url, handler);
verbose && console.log(' %s %s -> %s', method.toUpperCase(), url, key);
}
}

2 changes: 1 addition & 1 deletion examples/mvc/public/style.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
body {
padding: 50px;
font: 16px "Helvetica Neue", Helvetica, Arial;
font: 16px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
a {
color: #107aff;
13 changes: 13 additions & 0 deletions examples/mvc/views/404.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<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>
<body>
<h1>404: Not Found</h1>
<p>Sorry we can't find <%= url %></p>
</body>
</html>
3 changes: 0 additions & 3 deletions examples/mvc/views/404.jade

This file was deleted.

13 changes: 13 additions & 0 deletions examples/mvc/views/5xx.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<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>
<body>
<h1>500: Internal Server Error</h1>
<p>Looks like something blew up!</p>
</body>
</html>
3 changes: 0 additions & 3 deletions examples/mvc/views/5xx.jade

This file was deleted.

7 changes: 6 additions & 1 deletion examples/online/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
// first:
'use strict'

// install redis first:
// https://redis.io/

// then:
// $ npm install redis online
// $ redis-server

19 changes: 7 additions & 12 deletions examples/params/index.js
Original file line number Diff line number Diff line change
@@ -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,19 +51,19 @@ 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);
});

/**
* 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; });
res.send('users ' + names.slice(from, to).join(', '));
res.send('users ' + names.slice(from, to + 1).join(', '));
});

/* istanbul ignore next */
6 changes: 4 additions & 2 deletions examples/resource/index.js
Original file line number Diff line number Diff line change
@@ -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' }
@@ -75,7 +77,7 @@ app.resource('/users', User);

app.get('/', function(req, res){
res.send([
'<h1>Examples:</h1> <ul>'
'<h1>Examples:</h1> <ul>'
, '<li>GET /users</li>'
, '<li>GET /users/1</li>'
, '<li>GET /users/3</li>'
11 changes: 7 additions & 4 deletions examples/route-map/index.js
Original file line number Diff line number Diff line change
@@ -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))
}
};

8 changes: 5 additions & 3 deletions examples/route-middleware/index.js
Original file line number Diff line number Diff line change
@@ -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'));
12 changes: 7 additions & 5 deletions examples/route-separation/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
'use strict'

/**
* Module dependencies.
*/

var express = require('../..');
var path = require('path');
var app = express();
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var site = require('./site');
var post = require('./post');
@@ -16,8 +18,8 @@ module.exports = app;

// Config

app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

/* istanbul ignore next */
if (!module.parent) {
@@ -26,8 +28,8 @@ if (!module.parent) {

app.use(methodOverride('_method'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use(express.urlencoded({ extended: true }))
app.use(express.static(path.join(__dirname, 'public')));

// General

2 changes: 2 additions & 0 deletions examples/route-separation/post.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

// Fake posts database

var posts = [
4 changes: 3 additions & 1 deletion examples/route-separation/site.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

exports.index = function(req, res){
res.render('index', { title: 'Route Separation Example' });
};
};
2 changes: 2 additions & 0 deletions examples/route-separation/user.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict'

// Fake user database

var users = [
2 changes: 2 additions & 0 deletions examples/route-separation/views/footer.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
</body>
</html>
9 changes: 9 additions & 0 deletions examples/route-separation/views/header.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<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>
<body>
10 changes: 10 additions & 0 deletions examples/route-separation/views/index.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<%- include('header') -%>

<h1><%= title %></h1>

<ul>
<li>Visit the <a href="/users">users</a> page.</li>
<li>Visit the <a href="/posts">posts</a> page.</li>
</ul>

<%- include('footer') -%>
6 changes: 0 additions & 6 deletions examples/route-separation/views/index.jade

This file was deleted.

6 changes: 0 additions & 6 deletions examples/route-separation/views/layout.jade

This file was deleted.

12 changes: 12 additions & 0 deletions examples/route-separation/views/posts/index.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<%- include('../header') -%>

<h1>Posts</h1>

<dl id="posts">
<% posts.forEach(function(post) { %>
<dt><%= post.title %></dt>
<dd><%= post.body %></dd>
<% }) %>
</dl>

<%- include('../footer') -%>
8 changes: 0 additions & 8 deletions examples/route-separation/views/posts/index.jade

This file was deleted.

23 changes: 23 additions & 0 deletions examples/route-separation/views/users/edit.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<%- include('../header') -%>

<h1>Editing <%= user.name %></h1>

<div id="user">
<form action="?_method=put" method="post">
<p>
Name:
<input type="text" value="<%= user.name %>" name="user[name]" />
</p>

<p>
Email:
<input type="email" value="<%= user.email %>" name="user[email]" />
</p>

<p>
<input type="submit" value="Save" />
</p>
</form>
</div>

<%- include('../footer') -%>
Loading