diff --git a/.eslintrc.yml b/.eslintrc.yml
index 5b11e9fd844..587169c5330 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -3,6 +3,6 @@ root: true
rules:
eol-last: error
eqeqeq: [error, allow-null]
- indent: [error, 2, { SwitchCase: 1 }]
+ indent: [error, 2, { MemberExpression: "off", SwitchCase: 1 }]
no-trailing-spaces: error
no-unused-vars: [error, { vars: all, args: none, ignoreRestSiblings: true }]
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000000..b3ddd6b23ae
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -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 }}
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 00000000000..db4e01aff56
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -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"
diff --git a/.github/workflows/iojs.yml b/.github/workflows/iojs.yml
new file mode 100644
index 00000000000..c1268abd689
--- /dev/null
+++ b/.github/workflows/iojs.yml
@@ -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
+
diff --git a/.gitignore b/.gitignore
index 5fee6a2dc97..1bd5c02b28b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,27 +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
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 00000000000..43c97e719a5
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index c3ebc583d6b..00000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,66 +0,0 @@
-language: node_js
-node_js:
- - "0.10"
- - "0.12"
- - "1.8"
- - "2.5"
- - "3.3"
- - "4.9"
- - "5.12"
- - "6.17"
- - "7.10"
- - "8.16"
- - "9.11"
- - "10.15"
- - "11.15"
- - "12.3"
-matrix:
- include:
- - node_js: "13"
- env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly"
- allow_failures:
- # Allow the nightly installs to fail
- - env: "NVM_NODEJS_ORG_MIRROR=https://nodejs.org/download/nightly"
-sudo: false
-cache:
- directories:
- - node_modules
-before_install:
- # Configure npm
- - |
- # Skip updating shrinkwrap / lock
- npm config set shrinkwrap false
- # Remove all non-test dependencies
- - |
- # Remove example dependencies
- npm rm --silent --save-dev connect-redis
- # Setup Node.js version-specific dependencies
- - |
- # mocha for testing
- # - use 3.x for Node.js < 6
- if [[ "$(cut -d. -f1 <<< "$TRAVIS_NODE_VERSION")" -lt 6 ]]; then
- npm install --silent --save-dev mocha@3.5.3
- fi
- - |
- # supertest for http calls
- # - use 2.0.0 for Node.js < 4
- if [[ "$(cut -d. -f1 <<< "$TRAVIS_NODE_VERSION")" -lt 4 ]]; then
- npm install --silent --save-dev supertest@2.0.0
- fi
- # Update Node.js modules
- - |
- # Prune and rebuild node_modules
- if [[ -d node_modules ]]; then
- npm prune
- npm rebuild
- fi
-script:
- # Run test script
- - npm run test-ci
- # Run linting
- - npm run lint
-after_script:
- - |
- # Upload coverage to coveralls
- npm install --save-dev coveralls@2.12.0
- coveralls < ./coverage/lcov.info
diff --git a/Charter.md b/Charter.md
new file mode 100644
index 00000000000..a906e52909a
--- /dev/null
+++ b/Charter.md
@@ -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
diff --git a/Code-Of-Conduct.md b/Code-Of-Conduct.md
new file mode 100644
index 00000000000..ca4c6b31468
--- /dev/null
+++ b/Code-Of-Conduct.md
@@ -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.
diff --git a/Collaborator-Guide.md b/Collaborator-Guide.md
index 75d4e7c8f28..3c73307d61b 100644
--- a/Collaborator-Guide.md
+++ b/Collaborator-Guide.md
@@ -1,3 +1,4 @@
+# Express Collaborator Guide
## Website Issues
@@ -21,7 +22,7 @@ a future release of Express.
1. [Create an issue](https://github.com/expressjs/express/issues/new) for the
bug you want to fix or the feature that you want to add.
-2. Create your own [fork](https://github.com/expressjs/express) on github, then
+2. Create your own [fork](https://github.com/expressjs/express) on GitHub, then
checkout your fork.
3. Write your code in your local copy. It's good practice to create a branch for
each new issue you work on, although not compulsory.
diff --git a/Contributing.md b/Contributing.md
index f84c0138cb0..1654cee02f2 100644
--- a/Contributing.md
+++ b/Contributing.md
@@ -12,10 +12,12 @@ contributors can be involved in decision making.
* A **Contributor** is any individual creating or commenting on an issue or pull request.
* A **Committer** is a subset of contributors who have been given write access to the repository.
+* A **Project Captain** is the lead maintainer of a repository.
* A **TC (Technical Committee)** is a group of committers representing the required technical
expertise to resolve rare disputes.
+* A **Triager** is a subset of contributors who have been given triage access to the repository.
-# Logging Issues
+## Logging Issues
Log an issue for any question or problem you might have. When in doubt, log an issue, and
any additional policies about what to include will be provided in the responses. The only
@@ -27,7 +29,7 @@ add appropriate metadata before the issue is addressed.
Please be courteous and respectful. Every participant is expected to follow the
project's Code of Conduct.
-# Contributions
+## Contributions
Any change to resources in this repository must be through pull requests. This applies to all changes
to documentation, code, binary files, etc. Even long term committers and TC members must use
@@ -41,7 +43,7 @@ weekends and other holiday periods to ensure active committers all have reasonab
become involved in the discussion and review process if they wish.
The default for each contribution is that it is accepted once no committer has an objection.
-During review committers may also request that a specific contributor who is most versed in a
+During a review, committers may also request that a specific contributor who is most versed in a
particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off"
process for contributions to land. Once all issues brought by committers are addressed it can
be landed by any committer.
@@ -56,7 +58,21 @@ discuss pending contributions in order to find a resolution. It is expected that
small minority of issues be brought to the TC for resolution and that discussion and
compromise among committers be the default resolution mechanism.
-# Becoming a Committer
+## Becoming a Triager
+
+Anyone can become a triager! Read more about the process of being a triager in
+[the triage process document](Triager-Guide.md).
+
+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.
@@ -64,7 +80,7 @@ and added as a committer, and be given write access to the repository.
Committers are expected to follow this policy and continue to send pull requests, go through
proper review, and have other committers merge their pull requests.
-# TC Process
+## TC Process
The TC uses a "consensus seeking" process for issues that are escalated to the TC.
The group tries to find a resolution that has no open objections among TC members.
@@ -72,14 +88,122 @@ If a consensus cannot be reached that has no objections then a majority wins vot
is called. It is also expected that the majority of decisions made by the TC are via
a consensus seeking process and that voting is only used as a last-resort.
-Resolution may involve returning the issue to committers with suggestions on how to
-move forward towards a consensus. It is not expected that a meeting of the TC
+Resolution may involve returning the issue to project captains with suggestions on
+how to move forward towards a consensus. It is not expected that a meeting of the TC
will resolve all issues on its agenda during that meeting and may prefer to continue
-the discussion happening among the committers.
+the discussion happening among the project captains.
-Members can be added to the TC at any time. Any committer can nominate another committer
+Members can be added to the TC at any time. Any TC member can nominate another committer
to the TC and the TC uses its standard consensus seeking process to evaluate whether or
-not to add this new member. Members who do not participate consistently at the level of
-a majority of the other members are expected to resign.
-
-
+not to add this new member. The TC will consist of a minimum of 3 active members and a
+maximum of 10. If the TC should drop below 5 members the active TC members should nominate
+someone new. If a TC member is stepping down, they are encouraged (but not required) to
+nominate someone to take their place.
+
+TC members will be added as admin's on the Github orgs, npm orgs, and other resources as
+necessary to be effective in the role.
+
+To remain "active" a TC member should have participation within the last 12 months and miss
+no more than six consecutive TC meetings. Our goal is to increase participation, not punish
+people for any lack of participation, this guideline should be only be used as such
+(replace an inactive member with a new active one, for example). Members who do not meet this
+are expected to step down. If A TC member does not step down, an issue can be opened in the
+discussions repo to move them to inactive status. TC members who step down or are removed due
+to inactivity will be moved into inactive status.
+
+Inactive status members can become active members by self nomination if the TC is not already
+larger than the maximum of 10. They will also be given preference if, while at max size, an
+active member steps down.
+
+## Project Captains
+
+The Express TC can designate captains for individual projects/repos in the
+organizations. These captains are responsible for being the primary
+day-to-day maintainers of the repo on a technical and community front.
+Repo captains are empowered with repo ownership and package publication rights.
+When there are conflicts, especially on topics that effect the Express project
+at large, captains are responsible to raise it up to the TC and drive
+those conflicts to resolution. Captains are also responsible for making sure
+community members follow the community guidelines, maintaining the repo
+and the published package, as well as in providing user support.
+
+Like TC members, Repo captains are a subset of committers.
+
+To become a captain for a project the candidate is expected to participate in that
+project for at least 6 months as a committer prior to the request. They should have
+helped with code contributions as well as triaging issues. They are also required to
+have 2FA enabled on both their GitHub and npm accounts. Any TC member or existing
+captain on the repo can nominate another committer to the captain role, submit a PR to
+this doc, under `Current Project Captains` section (maintaining the sort order) with
+the project, their GitHub handle and npm username (if different). The PR will require
+at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or
+dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups.
+
+### 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
diff --git a/History.md b/History.md
index 6e62a6ddb85..c234f529cea 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,182 @@
+4.21.2 / 2024-11-06
+==========
+
+ * deps: path-to-regexp@0.1.12
+ - Fix backtracking protection
+ * deps: path-to-regexp@0.1.11
+ - Throws an error on invalid path values
+
+4.21.1 / 2024-10-08
+==========
+
+ * Backported a fix for [CVE-2024-47764](https://nvd.nist.gov/vuln/detail/CVE-2024-47764)
+
+
+4.21.0 / 2024-09-11
+==========
+
+ * Deprecate `res.location("back")` and `res.redirect("back")` magic string
+ * deps: serve-static@1.16.2
+ * includes send@0.19.0
+ * deps: finalhandler@1.3.1
+ * deps: qs@6.13.0
+
+4.20.0 / 2024-09-10
+==========
+ * deps: serve-static@0.16.0
+ * Remove link renderization in html while redirecting
+ * deps: send@0.19.0
+ * Remove link renderization in html while redirecting
+ * deps: body-parser@0.6.0
+ * add `depth` option to customize the depth level in the parser
+ * IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`)
+ * Remove link renderization in html while using `res.redirect`
+ * deps: path-to-regexp@0.1.10
+ - Adds support for named matching groups in the routes using a regex
+ - Adds backtracking protection to parameters without regexes defined
+ * deps: encodeurl@~2.0.0
+ - Removes encoding of `\`, `|`, and `^` to align better with URL spec
+ * Deprecate passing `options.maxAge` and `options.expires` to `res.clearCookie`
+ - Will be ignored in v5, clearCookie will set a cookie with an expires in the past to instruct clients to delete the cookie
+
+4.19.2 / 2024-03-25
+==========
+
+ * Improved fix for open redirect allow list bypass
+
+4.19.1 / 2024-03-20
+==========
+
+ * Allow passing non-strings to res.location with new encoding handling checks
+
+4.19.0 / 2024-03-20
+==========
+
+ * Prevent open redirect allow list bypass due to encodeurl
+ * deps: cookie@0.6.0
+
+4.18.3 / 2024-02-29
+==========
+
+ * Fix routing requests without method
+ * deps: body-parser@1.20.2
+ - Fix strict json error message on Node.js 19+
+ - deps: content-type@~1.0.5
+ - deps: raw-body@2.5.2
+ * deps: cookie@0.6.0
+ - Add `partitioned` option
+
+4.18.2 / 2022-10-08
+===================
+
+ * Fix regression routing a large stack in a single route
+ * deps: body-parser@1.20.1
+ - deps: qs@6.11.0
+ - perf: remove unnecessary object clone
+ * deps: qs@6.11.0
+
+4.18.1 / 2022-04-29
+===================
+
+ * Fix hanging on large stack of sync routes
+
+4.18.0 / 2022-04-25
+===================
+
+ * Add "root" option to `res.download`
+ * Allow `options` without `filename` in `res.download`
+ * Deprecate string and non-integer arguments to `res.status`
+ * Fix behavior of `null`/`undefined` as `maxAge` in `res.cookie`
+ * Fix handling very large stacks of sync middleware
+ * Ignore `Object.prototype` values in settings through `app.set`/`app.get`
+ * Invoke `default` with same arguments as types in `res.format`
+ * Support proper 205 responses using `res.send`
+ * Use `http-errors` for `res.format` error
+ * deps: body-parser@1.20.0
+ - Fix error message for json parse whitespace in `strict`
+ - Fix internal error when inflated body exceeds limit
+ - Prevent loss of async hooks context
+ - Prevent hanging when request already read
+ - deps: depd@2.0.0
+ - deps: http-errors@2.0.0
+ - deps: on-finished@2.4.1
+ - deps: qs@6.10.3
+ - deps: raw-body@2.5.1
+ * deps: cookie@0.5.0
+ - Add `priority` option
+ - Fix `expires` option to reject invalid dates
+ * deps: depd@2.0.0
+ - Replace internal `eval` usage with `Function` constructor
+ - Use instance methods on `process` to check for listeners
+ * deps: finalhandler@1.2.0
+ - Remove set content headers that break response
+ - deps: on-finished@2.4.1
+ - deps: statuses@2.0.1
+ * deps: on-finished@2.4.1
+ - Prevent loss of async hooks context
+ * deps: qs@6.10.3
+ * deps: send@0.18.0
+ - Fix emitted 416 error missing headers property
+ - Limit the headers removed for 304 response
+ - deps: depd@2.0.0
+ - deps: destroy@1.2.0
+ - deps: http-errors@2.0.0
+ - deps: on-finished@2.4.1
+ - deps: statuses@2.0.1
+ * deps: serve-static@1.15.0
+ - deps: send@0.18.0
+ * deps: statuses@2.0.1
+ - Remove code 306
+ - Rename `425 Unordered Collection` to standard `425 Too Early`
+
+4.17.3 / 2022-02-16
+===================
+
+ * deps: accepts@~1.3.8
+ - deps: mime-types@~2.1.34
+ - deps: negotiator@0.6.3
+ * deps: body-parser@1.19.2
+ - deps: bytes@3.1.2
+ - deps: qs@6.9.7
+ - deps: raw-body@2.4.3
+ * deps: cookie@0.4.2
+ * deps: qs@6.9.7
+ * Fix handling of `__proto__` keys
+ * pref: remove unnecessary regexp for trust proxy
+
+4.17.2 / 2021-12-16
+===================
+
+ * Fix handling of `undefined` in `res.jsonp`
+ * Fix handling of `undefined` when `"json escape"` is enabled
+ * Fix incorrect middleware execution with unanchored `RegExp`s
+ * Fix `res.jsonp(obj, status)` deprecation message
+ * Fix typo in `res.is` JSDoc
+ * deps: body-parser@1.19.1
+ - deps: bytes@3.1.1
+ - deps: http-errors@1.8.1
+ - deps: qs@6.9.6
+ - deps: raw-body@2.4.2
+ - deps: safe-buffer@5.2.1
+ - deps: type-is@~1.6.18
+ * deps: content-disposition@0.5.4
+ - deps: safe-buffer@5.2.1
+ * deps: cookie@0.4.1
+ - Fix `maxAge` option to reject invalid values
+ * deps: proxy-addr@~2.0.7
+ - Use `req.socket` over deprecated `req.connection`
+ - deps: forwarded@0.2.0
+ - deps: ipaddr.js@1.9.1
+ * deps: qs@6.9.6
+ * deps: safe-buffer@5.2.1
+ * deps: send@0.17.2
+ - deps: http-errors@1.8.1
+ - deps: ms@2.1.3
+ - pref: ignore empty http tokens
+ * deps: serve-static@1.14.2
+ - deps: send@0.17.2
+ * deps: setprototypeof@1.2.0
+
4.17.1 / 2019-05-25
===================
@@ -2000,7 +2179,7 @@
* deps: connect@2.21.0
- deprecate `connect(middleware)` -- use `app.use(middleware)` instead
- deprecate `connect.createServer()` -- use `connect()` instead
- - fix `res.setHeader()` patch to work with with get -> append -> set pattern
+ - fix `res.setHeader()` patch to work with get -> append -> set pattern
- deps: compression@~1.0.8
- deps: errorhandler@~1.1.1
- deps: express-session@~1.5.0
@@ -3211,8 +3390,8 @@ Shaw]
* Added node v0.1.97 compatibility
* Added support for deleting cookies via Request#cookie('key', null)
* Updated haml submodule
- * Fixed not-found page, now using using charset utf-8
- * Fixed show-exceptions page, now using using charset utf-8
+ * Fixed not-found page, now using charset utf-8
+ * Fixed show-exceptions page, now using charset utf-8
* Fixed view support due to fs.readFile Buffers
* Changed; mime.type() no longer accepts ".type" due to node extname() changes
@@ -3247,7 +3426,7 @@ Shaw]
==================
* Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s
- encoding is set to 'utf8' or 'utf-8'.
+ encoding is set to 'utf8' or 'utf-8').
* Added "encoding" option to Request#render(). Closes #299
* Added "dump exceptions" setting, which is enabled by default.
* Added simple ejs template engine support
@@ -3286,7 +3465,7 @@ Shaw]
* Added [haml.js](http://github.com/visionmedia/haml.js) submodule; removed haml-js
* Added callback function support to Request#halt() as 3rd/4th arg
* Added preprocessing of route param wildcards using param(). Closes #251
- * Added view partial support (with collections etc)
+ * Added view partial support (with collections etc.)
* Fixed bug preventing falsey params (such as ?page=0). Closes #286
* Fixed setting of multiple cookies. Closes #199
* Changed; view naming convention is now NAME.TYPE.ENGINE (for example page.html.haml)
diff --git a/Readme.md b/Readme.md
index 1f91297312b..bc108d55fc0 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,12 +1,29 @@
[](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
const express = require('express')
@@ -27,10 +44,13 @@ This is a [Node.js](https://nodejs.org/en/) module available through the
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):
-```bash
+```console
$ npm install express
```
@@ -50,7 +70,7 @@ for more information.
## Docs & Community
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
- * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
+ * [#express](https://web.libera.chat/#express) on [Libera Chat](https://libera.chat) IRC
* [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/expressjs/express/wiki)
* [Google Group](https://groups.google.com/group/express-js) for discussion
@@ -58,35 +78,31 @@ for more information.
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x).
-### Security Issues
-
-If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
-
## Quick Start
The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below:
Install the executable. The executable's major version will match Express's:
-```bash
+```console
$ npm install -g express-generator@4
```
Create the app:
-```bash
+```console
$ express /tmp/foo && cd /tmp/foo
```
Install dependencies:
-```bash
+```console
$ npm install
```
Start the server:
-```bash
+```console
$ npm start
```
@@ -95,7 +111,7 @@ $ npm start
## 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
@@ -106,50 +122,139 @@ $ npm start
To view the examples, clone the Express repo and install the dependencies:
-```bash
-$ git clone git://github.com/expressjs/express.git --depth 1
+```console
+$ git clone https://github.com/expressjs/express.git --depth 1
$ cd express
$ npm install
```
Then run whichever example you want:
-```bash
+```console
$ node examples/content-negotiation
```
-## Tests
+## Contributing
+
+ [![Linux Build][github-actions-ci-image]][github-actions-ci-url]
+ [![Windows Build][appveyor-image]][appveyor-url]
+ [![Test Coverage][coveralls-image]][coveralls-url]
- To run the test suite, first install the dependencies, then run `npm test`:
+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!
-```bash
+See the [Contributing Guide](Contributing.md) for more technical details on contributing.
+
+### Security Issues
+
+If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
+
+### Running Tests
+
+To run the test suite, first install the dependencies, then run `npm test`:
+
+```console
$ npm install
$ npm test
```
-## Contributing
-
-[Contributing Guide](Contributing.md)
-
## People
The original author of Express is [TJ Holowaychuk](https://github.com/tj)
-The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson)
-
[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**
+
+TC emeriti members
+
+#### 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**
+Triagers emeriti members
+
+#### 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**
+