Full Code of expressjs/express for AI

master 6c4249feec8a cached
213 files
689.9 KB
194.0k tokens
116 symbols
3 requests
Download .txt
Showing preview only (741K chars total). Download the full file or copy to clipboard to get everything.
Repository: expressjs/express
Branch: master
Commit: 6c4249feec8a
Files: 213
Total size: 689.9 KB

Directory structure:
gitextract_l4z7lniq/

├── .editorconfig
├── .eslintignore
├── .eslintrc.yml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── ci.yml
│       ├── codeql.yml
│       ├── legacy.yml
│       └── scorecard.yml
├── .gitignore
├── .npmrc
├── History.md
├── LICENSE
├── Readme.md
├── examples/
│   ├── README.md
│   ├── auth/
│   │   ├── index.js
│   │   └── views/
│   │       ├── foot.ejs
│   │       ├── head.ejs
│   │       └── login.ejs
│   ├── content-negotiation/
│   │   ├── db.js
│   │   ├── index.js
│   │   └── users.js
│   ├── cookie-sessions/
│   │   └── index.js
│   ├── cookies/
│   │   └── index.js
│   ├── downloads/
│   │   ├── files/
│   │   │   ├── CCTV大赛上海分赛区.txt
│   │   │   ├── amazing.txt
│   │   │   └── notes/
│   │   │       └── groceries.txt
│   │   └── index.js
│   ├── ejs/
│   │   ├── index.js
│   │   ├── public/
│   │   │   └── stylesheets/
│   │   │       └── style.css
│   │   └── views/
│   │       ├── footer.html
│   │       ├── header.html
│   │       └── users.html
│   ├── error/
│   │   └── index.js
│   ├── error-pages/
│   │   ├── index.js
│   │   └── views/
│   │       ├── 404.ejs
│   │       ├── 500.ejs
│   │       ├── error_header.ejs
│   │       ├── footer.ejs
│   │       └── index.ejs
│   ├── hello-world/
│   │   └── index.js
│   ├── markdown/
│   │   ├── index.js
│   │   └── views/
│   │       └── index.md
│   ├── multi-router/
│   │   ├── controllers/
│   │   │   ├── api_v1.js
│   │   │   └── api_v2.js
│   │   └── index.js
│   ├── mvc/
│   │   ├── controllers/
│   │   │   ├── main/
│   │   │   │   └── index.js
│   │   │   ├── pet/
│   │   │   │   ├── index.js
│   │   │   │   └── views/
│   │   │   │       ├── edit.ejs
│   │   │   │       └── show.ejs
│   │   │   ├── user/
│   │   │   │   ├── index.js
│   │   │   │   └── views/
│   │   │   │       ├── edit.hbs
│   │   │   │       ├── list.hbs
│   │   │   │       └── show.hbs
│   │   │   └── user-pet/
│   │   │       └── index.js
│   │   ├── db.js
│   │   ├── index.js
│   │   ├── lib/
│   │   │   └── boot.js
│   │   ├── public/
│   │   │   └── style.css
│   │   └── views/
│   │       ├── 404.ejs
│   │       └── 5xx.ejs
│   ├── online/
│   │   └── index.js
│   ├── params/
│   │   └── index.js
│   ├── resource/
│   │   └── index.js
│   ├── route-map/
│   │   └── index.js
│   ├── route-middleware/
│   │   └── index.js
│   ├── route-separation/
│   │   ├── index.js
│   │   ├── post.js
│   │   ├── public/
│   │   │   └── style.css
│   │   ├── site.js
│   │   ├── user.js
│   │   └── views/
│   │       ├── footer.ejs
│   │       ├── header.ejs
│   │       ├── index.ejs
│   │       ├── posts/
│   │       │   └── index.ejs
│   │       └── users/
│   │           ├── edit.ejs
│   │           ├── index.ejs
│   │           └── view.ejs
│   ├── search/
│   │   ├── index.js
│   │   └── public/
│   │       ├── client.js
│   │       └── index.html
│   ├── session/
│   │   ├── index.js
│   │   └── redis.js
│   ├── static-files/
│   │   ├── index.js
│   │   └── public/
│   │       ├── css/
│   │       │   └── style.css
│   │       ├── hello.txt
│   │       └── js/
│   │           └── app.js
│   ├── vhost/
│   │   └── index.js
│   ├── view-constructor/
│   │   ├── github-view.js
│   │   └── index.js
│   ├── view-locals/
│   │   ├── index.js
│   │   ├── user.js
│   │   └── views/
│   │       └── index.ejs
│   └── web-service/
│       └── index.js
├── index.js
├── lib/
│   ├── application.js
│   ├── express.js
│   ├── request.js
│   ├── response.js
│   ├── utils.js
│   └── view.js
├── package.json
└── test/
    ├── Route.js
    ├── Router.js
    ├── acceptance/
    │   ├── auth.js
    │   ├── content-negotiation.js
    │   ├── cookie-sessions.js
    │   ├── cookies.js
    │   ├── downloads.js
    │   ├── ejs.js
    │   ├── error-pages.js
    │   ├── error.js
    │   ├── hello-world.js
    │   ├── markdown.js
    │   ├── multi-router.js
    │   ├── mvc.js
    │   ├── params.js
    │   ├── resource.js
    │   ├── route-map.js
    │   ├── route-separation.js
    │   ├── vhost.js
    │   └── web-service.js
    ├── app.all.js
    ├── app.engine.js
    ├── app.head.js
    ├── app.js
    ├── app.listen.js
    ├── app.locals.js
    ├── app.options.js
    ├── app.param.js
    ├── app.render.js
    ├── app.request.js
    ├── app.response.js
    ├── app.route.js
    ├── app.router.js
    ├── app.routes.error.js
    ├── app.use.js
    ├── config.js
    ├── exports.js
    ├── express.json.js
    ├── express.raw.js
    ├── express.static.js
    ├── express.text.js
    ├── express.urlencoded.js
    ├── fixtures/
    │   ├── % of dogs.txt
    │   ├── .name
    │   ├── blog/
    │   │   ├── index.html
    │   │   └── post/
    │   │       └── index.tmpl
    │   ├── broken.send
    │   ├── default_layout/
    │   │   ├── name.tmpl
    │   │   └── user.tmpl
    │   ├── email.tmpl
    │   ├── empty.txt
    │   ├── local_layout/
    │   │   └── user.tmpl
    │   ├── name.tmpl
    │   ├── name.txt
    │   ├── nums.txt
    │   ├── pets/
    │   │   └── names.txt
    │   ├── snow ☃/
    │   │   └── .gitkeep
    │   ├── todo.html
    │   ├── todo.txt
    │   ├── user.html
    │   ├── user.tmpl
    │   └── users/
    │       ├── index.html
    │       └── tobi.txt
    ├── middleware.basic.js
    ├── regression.js
    ├── req.accepts.js
    ├── req.acceptsCharsets.js
    ├── req.acceptsEncodings.js
    ├── req.acceptsLanguages.js
    ├── req.baseUrl.js
    ├── req.fresh.js
    ├── req.get.js
    ├── req.host.js
    ├── req.hostname.js
    ├── req.ip.js
    ├── req.ips.js
    ├── req.is.js
    ├── req.path.js
    ├── req.protocol.js
    ├── req.query.js
    ├── req.range.js
    ├── req.route.js
    ├── req.secure.js
    ├── req.signedCookies.js
    ├── req.stale.js
    ├── req.subdomains.js
    ├── req.xhr.js
    ├── res.append.js
    ├── res.attachment.js
    ├── res.clearCookie.js
    ├── res.cookie.js
    ├── res.download.js
    ├── res.format.js
    ├── res.get.js
    ├── res.json.js
    ├── res.jsonp.js
    ├── res.links.js
    ├── res.locals.js
    ├── res.location.js
    ├── res.redirect.js
    ├── res.render.js
    ├── res.send.js
    ├── res.sendFile.js
    ├── res.sendStatus.js
    ├── res.set.js
    ├── res.status.js
    ├── res.type.js
    ├── res.vary.js
    ├── support/
    │   ├── env.js
    │   ├── tmpl.js
    │   └── utils.js
    └── utils.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# https://editorconfig.org
root = true

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

[{*.js,*.json,*.yml}]
indent_size = 2
indent_style = space


================================================
FILE: .eslintignore
================================================
coverage
node_modules


================================================
FILE: .eslintrc.yml
================================================
root: true
env:
  es2022: true
  node: 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 }]
  no-restricted-globals:
    - error
    - name: Buffer
      message: Use `import { Buffer } from "node:buffer"` instead of the global Buffer.


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: monthly

  - package-ecosystem: npm
    directory: /
    schedule:
      interval: monthly
      time: "23:00"
      timezone: Europe/London
    open-pull-requests-limit: 10
    ignore:
      - dependency-name: "*"
        update-types: ["version-update:semver-major"]

================================================
FILE: .github/workflows/ci.yml
================================================
name: ci

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

permissions:
  contents: read

# 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false
      - name: Setup Node.js
        uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
        with:
          node-version: 'lts/*'

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

      - name: Run lint
        run: npm run lint

  test:
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        node-version: [18, 19, 20, 21, 22, 23, 24, 25]
        # Node.js release schedule: https://nodejs.org/en/about/releases/

    name: Node.js ${{ matrix.node-version }} - ${{matrix.os}}

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

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
        with:
          node-version: ${{ matrix.node-version }}

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

      - name: Install dependencies
        run: npm install

      - 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

      - name: Upload code coverage
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }}
          path: ./coverage/lcov.info
          retention-days: 1

  coverage:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      checks: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Install lcov
        shell: bash
        run: sudo apt-get -y install lcov

      - name: Collect coverage reports
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          path: ./coverage
          pattern: coverage-node-*

      - name: Merge coverage reports
        shell: bash
        run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./lcov.info

      - name: Upload coverage report
        uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7
        with:
          file: ./lcov.info


================================================
FILE: .github/workflows/codeql.yml
================================================
# 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"
  workflow_dispatch:

permissions:
  contents: read

jobs:
  analyze:
    name: Analyze
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write
    strategy:
      fail-fast: false
      matrix:
        language: [javascript, actions]

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      # Initializes the CodeQL tools for scanning.
      - name: Initialize CodeQL
        uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
        with:
          languages: ${{ matrix.language }}
          config: |
            paths-ignore:
              - test
          # 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@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4


================================================
FILE: .github/workflows/legacy.yml
================================================
name: legacy

on:
  push:
    branches:
      - master
      - develop
      - '4.x'
      - '5.x'
      - '5.0'
    paths-ignore:
      - '*.md'
  pull_request:
    paths-ignore:
      - '*.md'
  workflow_dispatch:
  
permissions:
  contents: read

# 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:
  test:
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest]
        node-version: [16, 17]
        # Node.js release schedule: https://nodejs.org/en/about/releases/

    name: Node.js ${{ matrix.node-version }} - ${{matrix.os}}

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

      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
        with:
          node-version: ${{ matrix.node-version }}

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

      - name: Install dependencies
        run: npm install

      - 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

      - name: Upload code coverage
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }}
          path: ./coverage/lcov.info
          retention-days: 1

  coverage:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      checks: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: Install lcov
        shell: bash
        run: sudo apt-get -y install lcov

      - name: Collect coverage reports
        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
        with:
          path: ./coverage
          pattern: coverage-node-*

      - name: Merge coverage reports
        shell: bash
        run: find ./coverage -name lcov.info -exec printf '-a %q\n' {} \; | xargs lcov -o ./lcov.info

      - name: Upload coverage report
        uses: coverallsapp/github-action@5cbfd81b66ca5d10c19b062c04de0199c215fb6e # v2.3.7
        with:
          file: ./lcov.info


================================================
FILE: .github/workflows/scorecard.yml
================================================
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.

name: Scorecard supply-chain security
on:
  # For Branch-Protection check. Only the default branch is supported. See
  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
  branch_protection_rule:
  # To guarantee Maintained check is occasionally updated. See
  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
  schedule:
    - cron: '16 21 * * 1'
  push:
    branches: [ "master" ]

# Declare default permissions as read only.
permissions: read-all

jobs:
  analysis:
    name: Scorecard analysis
    runs-on: ubuntu-latest
    permissions:
      # Needed to upload the results to code-scanning dashboard.
      security-events: write
      # Needed to publish results and get a badge (see publish_results below).
      id-token: write
      # Uncomment the permissions below if installing in a private repository.
      # contents: read
      # actions: read

    steps:
      - name: "Checkout code"
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - name: "Run analysis"
        uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
        with:
          results_file: results.sarif
          results_format: sarif
          # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
          # - you want to enable the Branch-Protection check on a *public* repository, or
          # - you are installing Scorecard on a *private* repository
          # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
          # repo_token: ${{ secrets.SCORECARD_TOKEN }}

          # Public repositories:
          #   - Publish results to OpenSSF REST API for easy access by consumers
          #   - Allows the repository to include the Scorecard badge.
          #   - See https://github.com/ossf/scorecard-action#publishing-results.
          # For private repositories:
          #   - `publish_results` will always be set to `false`, regardless
          #     of the value entered here.
          publish_results: true

      # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
      # format to the repository Actions tab.
      - name: "Upload artifact"
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          name: SARIF file
          path: results.sarif
          retention-days: 5

      # Upload the results to GitHub's code scanning dashboard.
      - name: "Upload to code-scanning"
        uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
        with:
          sarif_file: results.sarif


================================================
FILE: .gitignore
================================================
# npm
node_modules
package-lock.json
npm-shrinkwrap.json
*.log
*.gz

# Yarn
yarn-error.log
yarn.lock

# Coveralls
.nyc_output
coverage

# Benchmarking
benchmarks/graphs

# ignore additional files using core.excludesFile
# https://git-scm.com/docs/gitignore


================================================
FILE: .npmrc
================================================
package-lock=false


================================================
FILE: History.md
================================================
# Unreleased Changes

## 🚀 Improvements

* Improve HTML structure in `res.redirect()` responses when HTML format is accepted by adding `<!DOCTYPE html>`, `<title>`, and `<body>` tags for better browser compatibility - by [@Bernice55231](https://github.com/Bernice55231) in [#5167](https://github.com/expressjs/express/pull/5167)

* When calling `app.render` with options set to null, the locals object is handled correctly, preventing unexpected errors and making the method behave the same as when options is omitted or an empty object is passed - by [AkaHarshit](https://github.com/AkaHarshit) in [#6903](https://github.com/expressjs/express/pull/6903)

    ```js
    app.render('index', null, callback); // now works as expected
    ```

## ⚡ Performance

* Avoid duplicate Content-Type header processing in `res.send()` when sending string responses without an explicit Content-Type header - by [@bjohansebas](https://github.com/bjohansebas) in [#6991](https://github.com/expressjs/express/pull/6991)

5.2.1 / 2025-12-01
=======================

* Revert security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6))
  * The prior release (5.2.0) included an erroneous breaking change related to the extended query parser. There is no actual security vulnerability associated with this behavior (CVE-2024-51999 has been rejected). The change has been fully reverted in this release.

5.2.0 / 2025-12-01
========================

* Security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6))
* deps: `body-parser@^2.2.1`
* A deprecation warning was added when using `res.redirect` with undefined arguments, Express now emits a warning to help detect calls that pass undefined as the status or URL and make them easier to fix.

5.1.0 / 2025-03-31
========================

* Add support for `Uint8Array` in `res.send()`
* Add support for ETag option in `res.sendFile()`
* Add support for multiple links with the same rel in `res.links()`
* Add funding field to package.json
* perf: use loop for acceptParams
* refactor: prefix built-in node module imports
* deps: remove `setprototypeof`
* deps: remove `safe-buffer`
* deps: remove `utils-merge`
* deps: remove `methods`
* deps: remove `depd`
* deps: `debug@^4.4.0`
* deps: `body-parser@^2.2.0`
* deps: `router@^2.2.0`
* deps: `content-type@^1.0.5`
* deps: `finalhandler@^2.1.0`
* deps: `qs@^6.14.0`
* deps: `server-static@2.2.0`
* deps: `type-is@2.0.1`

5.0.1 / 2024-10-08
==========

* Update `cookie` semver lock to address [CVE-2024-47764](https://nvd.nist.gov/vuln/detail/CVE-2024-47764)

5.0.0 / 2024-09-10
=========================
* remove:
  - `path-is-absolute` dependency - use `path.isAbsolute` instead
* breaking:
  * `res.status()` accepts only integers, and input must be greater than 99 and less than 1000
    * will throw a `RangeError: Invalid status code: ${code}. Status code must be greater than 99 and less than 1000.` for inputs outside this range
    * will throw a `TypeError: Invalid status code: ${code}. Status code must be an integer.` for non integer inputs
  * deps: send@1.0.0
  * `res.redirect('back')` and `res.location('back')` is no longer a supported magic string, explicitly use `req.get('Referrer') || '/'`.
* change:
  - `res.clearCookie` will ignore user provided `maxAge` and `expires` options
* deps: cookie-signature@^1.2.1
* deps: debug@4.3.6
* deps: merge-descriptors@^2.0.0
* deps: serve-static@^2.1.0
* deps: qs@6.13.0
* deps: accepts@^2.0.0
* deps: mime-types@^3.0.0
  - `application/javascript` => `text/javascript`
* deps: type-is@^2.0.0
* deps: content-disposition@^1.0.0
* deps: finalhandler@^2.0.0
* deps: fresh@^2.0.0
* deps: body-parser@^2.0.1
* deps: send@^1.1.0

5.0.0-beta.3 / 2024-03-25
=========================

This incorporates all changes after 4.19.1 up to 4.19.2.

5.0.0-beta.2 / 2024-03-20
=========================

This incorporates all changes after 4.17.2 up to 4.19.1.

5.0.0-beta.1 / 2022-02-14
=========================

This is the first Express 5.0 beta release, based off 4.17.2 and includes
changes from 5.0.0-alpha.8.

  * change:
    - Default "query parser" setting to `'simple'`
    - Requires Node.js 4+
    - Use `mime-types` for file to content type mapping
  * deps: array-flatten@3.0.0
  * deps: body-parser@2.0.0-beta.1
    - `req.body` is no longer always initialized to `{}`
    - `urlencoded` parser now defaults `extended` to `false`
    - Use `on-finished` to determine when body read
  * deps: router@2.0.0-beta.1
    - Add new `?`, `*`, and `+` parameter modifiers
    - Internalize private `router.process_params` method
    - Matching group expressions are only RegExp syntax
    - Named matching groups no longer available by position in `req.params`
    - Regular expressions can only be used in a matching group
    - Remove `debug` dependency
    - Special `*` path segment behavior removed
    - deps: array-flatten@3.0.0
    - deps: parseurl@~1.3.3
    - deps: path-to-regexp@3.2.0
    - deps: setprototypeof@1.2.0
  * deps: send@1.0.0-beta.1
    - Change `dotfiles` option default to `'ignore'`
    - Remove `hidden` option; use `dotfiles` option instead
    - Use `mime-types` for file to content type mapping
    - deps: debug@3.1.0
  * deps: serve-static@2.0.0-beta.1
    - Change `dotfiles` option default to `'ignore'`
    - Remove `hidden` option; use `dotfiles` option instead
    - Use `mime-types` for file to content type mapping
    - Remove `express.static.mime` export; use `mime-types` package instead
    - deps: send@1.0.0-beta.1

5.0.0-alpha.8 / 2020-03-25
==========================

This is the eighth Express 5.0 alpha release, based off 4.17.1 and includes
changes from 5.0.0-alpha.7.

5.0.0-alpha.7 / 2018-10-26
==========================

This is the seventh Express 5.0 alpha release, based off 4.16.4 and includes
changes from 5.0.0-alpha.6.

The major change with this alpha is the basic support for returned, rejected
Promises in the router.

  * remove:
    - `path-to-regexp` dependency
  * deps: debug@3.1.0
    - Add `DEBUG_HIDE_DATE` environment variable
    - Change timer to per-namespace instead of global
    - Change non-TTY date format
    - Remove `DEBUG_FD` environment variable support
    - Support 256 namespace colors
  * deps: router@2.0.0-alpha.1
    - Add basic support for returned, rejected Promises
    - Fix JSDoc for `Router` constructor
    - deps: debug@3.1.0
    - deps: parseurl@~1.3.2
    - deps: setprototypeof@1.1.0
    - deps: utils-merge@1.0.1

5.0.0-alpha.6 / 2017-09-24
==========================

This is the sixth Express 5.0 alpha release, based off 4.15.5 and includes
changes from 5.0.0-alpha.5.

  * remove:
    - `res.redirect(url, status)` signature - use `res.redirect(status, url)`
    - `res.send(status, body)` signature - use `res.status(status).send(body)`
  * deps: router@~1.3.1
    - deps: debug@2.6.8

5.0.0-alpha.5 / 2017-03-06
==========================

This is the fifth Express 5.0 alpha release, based off 4.15.2 and includes
changes from 5.0.0-alpha.4.

5.0.0-alpha.4 / 2017-03-01
==========================

This is the fourth Express 5.0 alpha release, based off 4.15.0 and includes
changes from 5.0.0-alpha.3.

  * remove:
    - Remove Express 3.x middleware error stubs
  * deps: router@~1.3.0
    - Add `next("router")` to exit from router
    - Fix case where `router.use` skipped requests routes did not
    - Skip routing when `req.url` is not set
    - Use `%o` in path debug to tell types apart
    - deps: debug@2.6.1
    - deps: setprototypeof@1.0.3
    - perf: add fast match path for `*` route

5.0.0-alpha.3 / 2017-01-28
==========================

This is the third Express 5.0 alpha release, based off 4.14.1 and includes
changes from 5.0.0-alpha.2.

  * remove:
    - `res.json(status, obj)` signature - use `res.status(status).json(obj)`
    - `res.jsonp(status, obj)` signature - use `res.status(status).jsonp(obj)`
    - `res.vary()` (no arguments) -- provide a field name as an argument
  * deps: array-flatten@2.1.1
  * deps: path-is-absolute@1.0.1
  * deps: router@~1.1.5
    - deps: array-flatten@2.0.1
    - deps: methods@~1.1.2
    - deps: parseurl@~1.3.1
    - deps: setprototypeof@1.0.2

5.0.0-alpha.2 / 2015-07-06
==========================

This is the second Express 5.0 alpha release, based off 4.13.1 and includes
changes from 5.0.0-alpha.1.

  * remove:
    - `app.param(fn)`
    - `req.param()` -- use `req.params`, `req.body`, or `req.query` instead
  * change:
    - `res.render` callback is always async, even for sync view engines
    - The leading `:` character in `name` for `app.param(name, fn)` is no longer removed
    - Use `router` module for routing
    - Use `path-is-absolute` module for absolute path detection

5.0.0-alpha.1 / 2014-11-06
==========================

This is the first Express 5.0 alpha release, based off 4.10.1.

  * remove:
    - `app.del` - use `app.delete`
    - `req.acceptsCharset` - use `req.acceptsCharsets`
    - `req.acceptsEncoding` - use `req.acceptsEncodings`
    - `req.acceptsLanguage` - use `req.acceptsLanguages`
    - `res.json(obj, status)` signature - use `res.json(status, obj)`
    - `res.jsonp(obj, status)` signature - use `res.jsonp(status, obj)`
    - `res.send(body, status)` signature - use `res.send(status, body)`
    - `res.send(status)` signature - use `res.sendStatus(status)`
    - `res.sendfile` - use `res.sendFile` instead
    - `express.query` middleware
  * change:
    - `req.host` now returns host (`hostname:port`) - use `req.hostname` for only hostname
    - `req.query` is now a getter instead of a plain property
  * add:
    - `app.router` is a reference to the base router

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

  * Revert "Improve error message for `null`/`undefined` to `res.status`"

4.17.0 / 2019-05-16
===================

  * Add `express.raw` to parse bodies into `Buffer`
  * Add `express.text` to parse bodies into string
  * Improve error message for non-strings to `res.sendFile`
  * Improve error message for `null`/`undefined` to `res.status`
  * Support multiple hosts in `X-Forwarded-Host`
  * deps: accepts@~1.3.7
  * deps: body-parser@1.19.0
    - Add encoding MIK
    - Add petabyte (`pb`) support
    - Fix parsing array brackets after index
    - deps: bytes@3.1.0
    - deps: http-errors@1.7.2
    - deps: iconv-lite@0.4.24
    - deps: qs@6.7.0
    - deps: raw-body@2.4.0
    - deps: type-is@~1.6.17
  * deps: content-disposition@0.5.3
  * deps: cookie@0.4.0
    - Add `SameSite=None` support
  * deps: finalhandler@~1.1.2
    - Set stricter `Content-Security-Policy` header
    - deps: parseurl@~1.3.3
    - deps: statuses@~1.5.0
  * deps: parseurl@~1.3.3
  * deps: proxy-addr@~2.0.5
    - deps: ipaddr.js@1.9.0
  * deps: qs@6.7.0
    - Fix parsing array brackets after index
  * deps: range-parser@~1.2.1
  * deps: send@0.17.1
    - Set stricter CSP header in redirect & error responses
    - deps: http-errors@~1.7.2
    - deps: mime@1.6.0
    - deps: ms@2.1.1
    - deps: range-parser@~1.2.1
    - deps: statuses@~1.5.0
    - perf: remove redundant `path.normalize` call
  * deps: serve-static@1.14.1
    - Set stricter CSP header in redirect response
    - deps: parseurl@~1.3.3
    - deps: send@0.17.1
  * deps: setprototypeof@1.1.1
  * deps: statuses@~1.5.0
    - Add `103 Early Hints`
  * deps: type-is@~1.6.18
    - deps: mime-types@~2.1.24
    - perf: prevent internal `throw` on invalid type

4.16.4 / 2018-10-10
===================

  * Fix issue where `"Request aborted"` may be logged in `res.sendfile`
  * Fix JSDoc for `Router` constructor
  * deps: body-parser@1.18.3
    - Fix deprecation warnings on Node.js 10+
    - Fix stack trace for strict json parse error
    - deps: depd@~1.1.2
    - deps: http-errors@~1.6.3
    - deps: iconv-lite@0.4.23
    - deps: qs@6.5.2
    - deps: raw-body@2.3.3
    - deps: type-is@~1.6.16
  * deps: proxy-addr@~2.0.4
    - deps: ipaddr.js@1.8.0
  * deps: qs@6.5.2
  * deps: safe-buffer@5.1.2

4.16.3 / 2018-03-12
===================

  * deps: accepts@~1.3.5
    - deps: mime-types@~2.1.18
  * deps: depd@~1.1.2
    - perf: remove argument reassignment
  * deps: encodeurl@~1.0.2
    - Fix encoding `%` as last character
  * deps: finalhandler@1.1.1
    - Fix 404 output for bad / missing pathnames
    - deps: encodeurl@~1.0.2
    - deps: statuses@~1.4.0
  * deps: proxy-addr@~2.0.3
    - deps: ipaddr.js@1.6.0
  * deps: send@0.16.2
    - Fix incorrect end tag in default error & redirects
    - deps: depd@~1.1.2
    - deps: encodeurl@~1.0.2
    - deps: statuses@~1.4.0
  * deps: serve-static@1.13.2
    - Fix incorrect end tag in redirects
    - deps: encodeurl@~1.0.2
    - deps: send@0.16.2
  * deps: statuses@~1.4.0
  * deps: type-is@~1.6.16
    - deps: mime-types@~2.1.18

4.16.2 / 2017-10-09
===================

  * Fix `TypeError` in `res.send` when given `Buffer` and `ETag` header set
  * perf: skip parsing of entire `X-Forwarded-Proto` header

4.16.1 / 2017-09-29
===================

  * deps: send@0.16.1
  * deps: serve-static@1.13.1
    - Fix regression when `root` is incorrectly set to a file
    - deps: send@0.16.1

4.16.0 / 2017-09-28
===================

  * Add `"json escape"` setting for `res.json` and `res.jsonp`
  * Add `express.json` and `express.urlencoded` to parse bodies
  * Add `options` argument to `res.download`
  * Improve error message when autoloading invalid view engine
  * Improve error messages when non-function provided as middleware
  * Skip `Buffer` encoding when not generating ETag for small response
  * Use `safe-buffer` for improved Buffer API
  * deps: accepts@~1.3.4
    - deps: mime-types@~2.1.16
  * deps: content-type@~1.0.4
    - perf: remove argument reassignment
    - perf: skip parameter parsing when no parameters
  * deps: etag@~1.8.1
    - perf: replace regular expression with substring
  * deps: finalhandler@1.1.0
    - Use `res.headersSent` when available
  * deps: parseurl@~1.3.2
    - perf: reduce overhead for full URLs
    - perf: unroll the "fast-path" `RegExp`
  * deps: proxy-addr@~2.0.2
    - Fix trimming leading / trailing OWS in `X-Forwarded-For`
    - deps: forwarded@~0.1.2
    - deps: ipaddr.js@1.5.2
    - perf: reduce overhead when no `X-Forwarded-For` header
  * deps: qs@6.5.1
    - Fix parsing & compacting very deep objects
  * deps: send@0.16.0
    - Add 70 new types for file extensions
    - Add `immutable` option
    - Fix missing `</html>` in default error & redirects
    - Set charset as "UTF-8" for .js and .json
    - Use instance methods on steam to check for listeners
    - deps: mime@1.4.1
    - perf: improve path validation speed
  * deps: serve-static@1.13.0
    - Add 70 new types for file extensions
    - Add `immutable` option
    - Set charset as "UTF-8" for .js and .json
    - deps: send@0.16.0
  * deps: setprototypeof@1.1.0
  * deps: utils-merge@1.0.1
  * deps: vary@~1.1.2
    - perf: improve header token parsing speed
  * perf: re-use options object when generating ETags
  * perf: remove dead `.charset` set in `res.jsonp`

4.15.5 / 2017-09-24
===================

  * deps: debug@2.6.9
  * deps: finalhandler@~1.0.6
    - deps: debug@2.6.9
    - deps: parseurl@~1.3.2
  * deps: fresh@0.5.2
    - Fix handling of modified headers with invalid dates
    - perf: improve ETag match loop
    - perf: improve `If-None-Match` token parsing
  * deps: send@0.15.6
    - Fix handling of modified headers with invalid dates
    - deps: debug@2.6.9
    - deps: etag@~1.8.1
    - deps: fresh@0.5.2
    - perf: improve `If-Match` token parsing
  * deps: serve-static@1.12.6
    - deps: parseurl@~1.3.2
    - deps: send@0.15.6
    - perf: improve slash collapsing

4.15.4 / 2017-08-06
===================

  * deps: debug@2.6.8
  * deps: depd@~1.1.1
    - Remove unnecessary `Buffer` loading
  * deps: finalhandler@~1.0.4
    - deps: debug@2.6.8
  * deps: proxy-addr@~1.1.5
    - Fix array argument being altered
    - deps: ipaddr.js@1.4.0
  * deps: qs@6.5.0
  * deps: send@0.15.4
    - deps: debug@2.6.8
    - deps: depd@~1.1.1
    - deps: http-errors@~1.6.2
  * deps: serve-static@1.12.4
    - deps: send@0.15.4

4.15.3 / 2017-05-16
===================

  * Fix error when `res.set` cannot add charset to `Content-Type`
  * deps: debug@2.6.7
    - Fix `DEBUG_MAX_ARRAY_LENGTH`
    - deps: ms@2.0.0
  * deps: finalhandler@~1.0.3
    - Fix missing `</html>` in HTML document
    - deps: debug@2.6.7
  * deps: proxy-addr@~1.1.4
    - deps: ipaddr.js@1.3.0
  * deps: send@0.15.3
    - deps: debug@2.6.7
    - deps: ms@2.0.0
  * deps: serve-static@1.12.3
    - deps: send@0.15.3
  * deps: type-is@~1.6.15
    - deps: mime-types@~2.1.15
  * deps: vary@~1.1.1
    - perf: hoist regular expression

4.15.2 / 2017-03-06
===================

  * deps: qs@6.4.0
    - Fix regression parsing keys starting with `[`

4.15.1 / 2017-03-05
===================

  * deps: send@0.15.1
    - Fix issue when `Date.parse` does not return `NaN` on invalid date
    - Fix strict violation in broken environments
  * deps: serve-static@1.12.1
    - Fix issue when `Date.parse` does not return `NaN` on invalid date
    - deps: send@0.15.1

4.15.0 / 2017-03-01
===================

  * Add debug message when loading view engine
  * Add `next("router")` to exit from router
  * Fix case where `router.use` skipped requests routes did not
  * Remove usage of `res._headers` private field
    - Improves compatibility with Node.js 8 nightly
  * Skip routing when `req.url` is not set
  * Use `%o` in path debug to tell types apart
  * Use `Object.create` to setup request & response prototypes
  * Use `setprototypeof` module to replace `__proto__` setting
  * Use `statuses` instead of `http` module for status messages
  * deps: debug@2.6.1
    - Allow colors in workers
    - Deprecated `DEBUG_FD` environment variable set to `3` or higher
    - Fix error when running under React Native
    - Use same color for same namespace
    - deps: ms@0.7.2
  * deps: etag@~1.8.0
    - Use SHA1 instead of MD5 for ETag hashing
    - Works with FIPS 140-2 OpenSSL configuration
  * deps: finalhandler@~1.0.0
    - Fix exception when `err` cannot be converted to a string
    - Fully URL-encode the pathname in the 404
    - Only include the pathname in the 404 message
    - Send complete HTML document
    - Set `Content-Security-Policy: default-src 'self'` header
    - deps: debug@2.6.1
  * deps: fresh@0.5.0
    - Fix false detection of `no-cache` request directive
    - Fix incorrect result when `If-None-Match` has both `*` and ETags
    - Fix weak `ETag` matching to match spec
    - perf: delay reading header values until needed
    - perf: enable strict mode
    - perf: hoist regular expressions
    - perf: remove duplicate conditional
    - perf: remove unnecessary boolean coercions
    - perf: skip checking modified time if ETag check failed
    - perf: skip parsing `If-None-Match` when no `ETag` header
    - perf: use `Date.parse` instead of `new Date`
  * deps: qs@6.3.1
    - Fix array parsing from skipping empty values
    - Fix compacting nested arrays
  * deps: send@0.15.0
    - Fix false detection of `no-cache` request directive
    - Fix incorrect result when `If-None-Match` has both `*` and ETags
    - Fix weak `ETag` matching to match spec
    - Remove usage of `res._headers` private field
    - Support `If-Match` and `If-Unmodified-Since` headers
    - Use `res.getHeaderNames()` when available
    - Use `res.headersSent` when available
    - deps: debug@2.6.1
    - deps: etag@~1.8.0
    - deps: fresh@0.5.0
    - deps: http-errors@~1.6.1
  * deps: serve-static@1.12.0
    - Fix false detection of `no-cache` request directive
    - Fix incorrect result when `If-None-Match` has both `*` and ETags
    - Fix weak `ETag` matching to match spec
    - Remove usage of `res._headers` private field
    - Send complete HTML document in redirect response
    - Set default CSP header in redirect response
    - Support `If-Match` and `If-Unmodified-Since` headers
    - Use `res.getHeaderNames()` when available
    - Use `res.headersSent` when available
    - deps: send@0.15.0
  * perf: add fast match path for `*` route
  * perf: improve `req.ips` performance

4.14.1 / 2017-01-28
===================

  * deps: content-disposition@0.5.2
  * deps: finalhandler@0.5.1
    - Fix exception when `err.headers` is not an object
    - deps: statuses@~1.3.1
    - perf: hoist regular expressions
    - perf: remove duplicate validation path
  * deps: proxy-addr@~1.1.3
    - deps: ipaddr.js@1.2.0
  * deps: send@0.14.2
    - deps: http-errors@~1.5.1
    - deps: ms@0.7.2
    - deps: statuses@~1.3.1
  * deps: serve-static@~1.11.2
    - deps: send@0.14.2
  * deps: type-is@~1.6.14
    - deps: mime-types@~2.1.13

4.14.0 / 2016-06-16
===================

  * Add `acceptRanges` option to `res.sendFile`/`res.sendfile`
  * Add `cacheControl` option to `res.sendFile`/`res.sendfile`
  * Add `options` argument to `req.range`
    - Includes the `combine` option
  * Encode URL in `res.location`/`res.redirect` if not already encoded
  * Fix some redirect handling in `res.sendFile`/`res.sendfile`
  * Fix Windows absolute path check using forward slashes
  * Improve error with invalid arguments to `req.get()`
  * Improve performance for `res.json`/`res.jsonp` in most cases
  * Improve `Range` header handling in `res.sendFile`/`res.sendfile`
  * deps: accepts@~1.3.3
    - Fix including type extensions in parameters in `Accept` parsing
    - Fix parsing `Accept` parameters with quoted equals
    - Fix parsing `Accept` parameters with quoted semicolons
    - Many performance improvements
    - deps: mime-types@~2.1.11
    - deps: negotiator@0.6.1
  * deps: content-type@~1.0.2
    - perf: enable strict mode
  * deps: cookie@0.3.1
    - Add `sameSite` option
    - Fix cookie `Max-Age` to never be a floating point number
    - Improve error message when `encode` is not a function
    - Improve error message when `expires` is not a `Date`
    - Throw better error for invalid argument to parse
    - Throw on invalid values provided to `serialize`
    - perf: enable strict mode
    - perf: hoist regular expression
    - perf: use for loop in parse
    - perf: use string concatenation for serialization
  * deps: finalhandler@0.5.0
    - Change invalid or non-numeric status code to 500
    - Overwrite status message to match set status code
    - Prefer `err.statusCode` if `err.status` is invalid
    - Set response headers from `err.headers` object
    - Use `statuses` instead of `http` module for status messages
  * deps: proxy-addr@~1.1.2
    - Fix accepting various invalid netmasks
    - Fix IPv6-mapped IPv4 validation edge cases
    - IPv4 netmasks must be contiguous
    - IPv6 addresses cannot be used as a netmask
    - deps: ipaddr.js@1.1.1
  * deps: qs@6.2.0
    - Add `decoder` option in `parse` function
  * deps: range-parser@~1.2.0
    - Add `combine` option to combine overlapping ranges
    - Fix incorrectly returning -1 when there is at least one valid range
    - perf: remove internal function
  * deps: send@0.14.1
    - Add `acceptRanges` option
    - Add `cacheControl` option
    - Attempt to combine multiple ranges into single range
    - Correctly inherit from `Stream` class
    - Fix `Content-Range` header in 416 responses when using `start`/`end` options
    - Fix `Content-Range` header missing from default 416 responses
    - Fix redirect error when `path` contains raw non-URL characters
    - Fix redirect when `path` starts with multiple forward slashes
    - Ignore non-byte `Range` headers
    - deps: http-errors@~1.5.0
    - deps: range-parser@~1.2.0
    - deps: statuses@~1.3.0
    - perf: remove argument reassignment
  * deps: serve-static@~1.11.1
    - Add `acceptRanges` option
    - Add `cacheControl` option
    - Attempt to combine multiple ranges into single range
    - Fix redirect error when `req.url` contains raw non-URL characters
    - Ignore non-byte `Range` headers
    - Use status code 301 for redirects
    - deps: send@0.14.1
  * deps: type-is@~1.6.13
    - Fix type error when given invalid type to match against
    - deps: mime-types@~2.1.11
  * deps: vary@~1.1.0
    - Only accept valid field names in the `field` argument
  * perf: use strict equality when possible

4.13.4 / 2016-01-21
===================

  * deps: content-disposition@0.5.1
    - perf: enable strict mode
  * deps: cookie@0.1.5
    - Throw on invalid values provided to `serialize`
  * deps: depd@~1.1.0
    - Support web browser loading
    - perf: enable strict mode
  * deps: escape-html@~1.0.3
    - perf: enable strict mode
    - perf: optimize string replacement
    - perf: use faster string coercion
  * deps: finalhandler@0.4.1
    - deps: escape-html@~1.0.3
  * deps: merge-descriptors@1.0.1
    - perf: enable strict mode
  * deps: methods@~1.1.2
    - perf: enable strict mode
  * deps: parseurl@~1.3.1
    - perf: enable strict mode
  * deps: proxy-addr@~1.0.10
    - deps: ipaddr.js@1.0.5
    - perf: enable strict mode
  * deps: range-parser@~1.0.3
    - perf: enable strict mode
  * deps: send@0.13.1
    - deps: depd@~1.1.0
    - deps: destroy@~1.0.4
    - deps: escape-html@~1.0.3
    - deps: range-parser@~1.0.3
  * deps: serve-static@~1.10.2
    - deps: escape-html@~1.0.3
    - deps: parseurl@~1.3.0
    - deps: send@0.13.1

4.13.3 / 2015-08-02
===================

  * Fix infinite loop condition using `mergeParams: true`
  * Fix inner numeric indices incorrectly altering parent `req.params`

4.13.2 / 2015-07-31
===================

  * deps: accepts@~1.2.12
    - deps: mime-types@~2.1.4
  * deps: array-flatten@1.1.1
    - perf: enable strict mode
  * deps: path-to-regexp@0.1.7
    - Fix regression with escaped round brackets and matching groups
  * deps: type-is@~1.6.6
    - deps: mime-types@~2.1.4

4.13.1 / 2015-07-05
===================

  * deps: accepts@~1.2.10
    - deps: mime-types@~2.1.2
  * deps: qs@4.0.0
    - Fix dropping parameters like `hasOwnProperty`
    - Fix various parsing edge cases
  * deps: type-is@~1.6.4
    - deps: mime-types@~2.1.2
    - perf: enable strict mode
    - perf: remove argument reassignment

4.13.0 / 2015-06-20
===================

  * Add settings to debug output
  * Fix `res.format` error when only `default` provided
  * Fix issue where `next('route')` in `app.param` would incorrectly skip values
  * Fix hiding platform issues with `decodeURIComponent`
    - Only `URIError`s are a 400
  * Fix using `*` before params in routes
  * Fix using capture groups before params in routes
  * Simplify `res.cookie` to call `res.append`
  * Use `array-flatten` module for flattening arrays
  * deps: accepts@~1.2.9
    - deps: mime-types@~2.1.1
    - perf: avoid argument reassignment & argument slice
    - perf: avoid negotiator recursive construction
    - perf: enable strict mode
    - perf: remove unnecessary bitwise operator
  * deps: cookie@0.1.3
    - perf: deduce the scope of try-catch deopt
    - perf: remove argument reassignments
  * deps: escape-html@1.0.2
  * deps: etag@~1.7.0
    - Always include entity length in ETags for hash length extensions
    - Generate non-Stats ETags using MD5 only (no longer CRC32)
    - Improve stat performance by removing hashing
    - Improve support for JXcore
    - Remove base64 padding in ETags to shorten
    - Support "fake" stats objects in environments without fs
    - Use MD5 instead of MD4 in weak ETags over 1KB
  * deps: finalhandler@0.4.0
    - Fix a false-positive when unpiping in Node.js 0.8
    - Support `statusCode` property on `Error` objects
    - Use `unpipe` module for unpiping requests
    - deps: escape-html@1.0.2
    - deps: on-finished@~2.3.0
    - perf: enable strict mode
    - perf: remove argument reassignment
  * deps: fresh@0.3.0
    - Add weak `ETag` matching support
  * deps: on-finished@~2.3.0
    - Add defined behavior for HTTP `CONNECT` requests
    - Add defined behavior for HTTP `Upgrade` requests
    - deps: ee-first@1.1.1
  * deps: path-to-regexp@0.1.6
  * deps: send@0.13.0
    - Allow Node.js HTTP server to set `Date` response header
    - Fix incorrectly removing `Content-Location` on 304 response
    - Improve the default redirect response headers
    - Send appropriate headers on default error response
    - Use `http-errors` for standard emitted errors
    - Use `statuses` instead of `http` module for status messages
    - deps: escape-html@1.0.2
    - deps: etag@~1.7.0
    - deps: fresh@0.3.0
    - deps: on-finished@~2.3.0
    - perf: enable strict mode
    - perf: remove unnecessary array allocations
  * deps: serve-static@~1.10.0
    - Add `fallthrough` option
    - Fix reading options from options prototype
    - Improve the default redirect response headers
    - Malformed URLs now `next()` instead of 400
    - deps: escape-html@1.0.2
    - deps: send@0.13.0
    - perf: enable strict mode
    - perf: remove argument reassignment
  * deps: type-is@~1.6.3
    - deps: mime-types@~2.1.1
    - perf: reduce try block size
    - perf: remove bitwise operations
  * perf: enable strict mode
  * perf: isolate `app.render` try block
  * perf: remove argument reassignments in application
  * perf: remove argument reassignments in request prototype
  * perf: remove argument reassignments in response prototype
  * perf: remove argument reassignments in routing
  * perf: remove argument reassignments in `View`
  * perf: skip attempting to decode zero length string
  * perf: use saved reference to `http.STATUS_CODES`

4.12.4 / 2015-05-17
===================

  * deps: accepts@~1.2.7
    - deps: mime-types@~2.0.11
    - deps: negotiator@0.5.3
  * deps: debug@~2.2.0
    - deps: ms@0.7.1
  * deps: depd@~1.0.1
  * deps: etag@~1.6.0
    - Improve support for JXcore
    - Support "fake" stats objects in environments without `fs`
  * deps: finalhandler@0.3.6
    - deps: debug@~2.2.0
    - deps: on-finished@~2.2.1
  * deps: on-finished@~2.2.1
    - Fix `isFinished(req)` when data buffered
  * deps: proxy-addr@~1.0.8
    - deps: ipaddr.js@1.0.1
  * deps: qs@2.4.2
   - Fix allowing parameters like `constructor`
  * deps: send@0.12.3
    - deps: debug@~2.2.0
    - deps: depd@~1.0.1
    - deps: etag@~1.6.0
    - deps: ms@0.7.1
    - deps: on-finished@~2.2.1
  * deps: serve-static@~1.9.3
    - deps: send@0.12.3
  * deps: type-is@~1.6.2
    - deps: mime-types@~2.0.11

4.12.3 / 2015-03-17
===================

  * deps: accepts@~1.2.5
    - deps: mime-types@~2.0.10
  * deps: debug@~2.1.3
    - Fix high intensity foreground color for bold
    - deps: ms@0.7.0
  * deps: finalhandler@0.3.4
    - deps: debug@~2.1.3
  * deps: proxy-addr@~1.0.7
    - deps: ipaddr.js@0.1.9
  * deps: qs@2.4.1
    - Fix error when parameter `hasOwnProperty` is present
  * deps: send@0.12.2
    - Throw errors early for invalid `extensions` or `index` options
    - deps: debug@~2.1.3
  * deps: serve-static@~1.9.2
    - deps: send@0.12.2
  * deps: type-is@~1.6.1
    - deps: mime-types@~2.0.10

4.12.2 / 2015-03-02
===================

  * Fix regression where `"Request aborted"` is logged using `res.sendFile`

4.12.1 / 2015-03-01
===================

  * Fix constructing application with non-configurable prototype properties
  * Fix `ECONNRESET` errors from `res.sendFile` usage
  * Fix `req.host` when using "trust proxy" hops count
  * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count
  * Fix wrong `code` on aborted connections from `res.sendFile`
  * deps: merge-descriptors@1.0.0

4.12.0 / 2015-02-23
===================

  * Fix `"trust proxy"` setting to inherit when app is mounted
  * Generate `ETag`s for all request responses
    - No longer restricted to only responses for `GET` and `HEAD` requests
  * Use `content-type` to parse `Content-Type` headers
  * deps: accepts@~1.2.4
    - Fix preference sorting to be stable for long acceptable lists
    - deps: mime-types@~2.0.9
    - deps: negotiator@0.5.1
  * deps: cookie-signature@1.0.6
  * deps: send@0.12.1
    - Always read the stat size from the file
    - Fix mutating passed-in `options`
    - deps: mime@1.3.4
  * deps: serve-static@~1.9.1
    - deps: send@0.12.1
  * deps: type-is@~1.6.0
    - fix argument reassignment
    - fix false-positives in `hasBody` `Transfer-Encoding` check
    - support wildcard for both type and subtype (`*/*`)
    - deps: mime-types@~2.0.9

4.11.2 / 2015-02-01
===================

  * Fix `res.redirect` double-calling `res.end` for `HEAD` requests
  * deps: accepts@~1.2.3
    - deps: mime-types@~2.0.8
  * deps: proxy-addr@~1.0.6
    - deps: ipaddr.js@0.1.8
  * deps: type-is@~1.5.6
    - deps: mime-types@~2.0.8

4.11.1 / 2015-01-20
===================

  * deps: send@0.11.1
    - Fix root path disclosure
  * deps: serve-static@~1.8.1
    - Fix redirect loop in Node.js 0.11.14
    - Fix root path disclosure
    - deps: send@0.11.1

4.11.0 / 2015-01-13
===================

  * Add `res.append(field, val)` to append headers
  * Deprecate leading `:` in `name` for `app.param(name, fn)`
  * Deprecate `req.param()` -- use `req.params`, `req.body`, or `req.query` instead
  * Deprecate `app.param(fn)`
  * Fix `OPTIONS` responses to include the `HEAD` method properly
  * Fix `res.sendFile` not always detecting aborted connection
  * Match routes iteratively to prevent stack overflows
  * deps: accepts@~1.2.2
    - deps: mime-types@~2.0.7
    - deps: negotiator@0.5.0
  * deps: send@0.11.0
    - deps: debug@~2.1.1
    - deps: etag@~1.5.1
    - deps: ms@0.7.0
    - deps: on-finished@~2.2.0
  * deps: serve-static@~1.8.0
    - deps: send@0.11.0

4.10.8 / 2015-01-13
===================

  * Fix crash from error within `OPTIONS` response handler
  * deps: proxy-addr@~1.0.5
    - deps: ipaddr.js@0.1.6

4.10.7 / 2015-01-04
===================

  * Fix `Allow` header for `OPTIONS` to not contain duplicate methods
  * Fix incorrect "Request aborted" for `res.sendFile` when `HEAD` or 304
  * deps: debug@~2.1.1
  * deps: finalhandler@0.3.3
    - deps: debug@~2.1.1
    - deps: on-finished@~2.2.0
  * deps: methods@~1.1.1
  * deps: on-finished@~2.2.0
  * deps: serve-static@~1.7.2
    - Fix potential open redirect when mounted at root
  * deps: type-is@~1.5.5
    - deps: mime-types@~2.0.7

4.10.6 / 2014-12-12
===================

  * Fix exception in `req.fresh`/`req.stale` without response headers

4.10.5 / 2014-12-10
===================

  * Fix `res.send` double-calling `res.end` for `HEAD` requests
  * deps: accepts@~1.1.4
    - deps: mime-types@~2.0.4
  * deps: type-is@~1.5.4
    - deps: mime-types@~2.0.4

4.10.4 / 2014-11-24
===================

  * Fix `res.sendfile` logging standard write errors

4.10.3 / 2014-11-23
===================

  * Fix `res.sendFile` logging standard write errors
  * deps: etag@~1.5.1
  * deps: proxy-addr@~1.0.4
    - deps: ipaddr.js@0.1.5
  * deps: qs@2.3.3
    - Fix `arrayLimit` behavior

4.10.2 / 2014-11-09
===================

  * Correctly invoke async router callback asynchronously
  * deps: accepts@~1.1.3
    - deps: mime-types@~2.0.3
  * deps: type-is@~1.5.3
    - deps: mime-types@~2.0.3

4.10.1 / 2014-10-28
===================

  * Fix handling of URLs containing `://` in the path
  * deps: qs@2.3.2
    - Fix parsing of mixed objects and values

4.10.0 / 2014-10-23
===================

  * Add support for `app.set('views', array)`
    - Views are looked up in sequence in array of directories
  * Fix `res.send(status)` to mention `res.sendStatus(status)`
  * Fix handling of invalid empty URLs
  * Use `content-disposition` module for `res.attachment`/`res.download`
    - Sends standards-compliant `Content-Disposition` header
    - Full Unicode support
  * Use `path.resolve` in view lookup
  * deps: debug@~2.1.0
    - Implement `DEBUG_FD` env variable support
  * deps: depd@~1.0.0
  * deps: etag@~1.5.0
    - Improve string performance
    - Slightly improve speed for weak ETags over 1KB
  * deps: finalhandler@0.3.2
    - Terminate in progress response only on error
    - Use `on-finished` to determine request status
    - deps: debug@~2.1.0
    - deps: on-finished@~2.1.1
  * deps: on-finished@~2.1.1
    - Fix handling of pipelined requests
  * deps: qs@2.3.0
    - Fix parsing of mixed implicit and explicit arrays
  * deps: send@0.10.1
    - deps: debug@~2.1.0
    - deps: depd@~1.0.0
    - deps: etag@~1.5.0
    - deps: on-finished@~2.1.1
  * deps: serve-static@~1.7.1
    - deps: send@0.10.1

4.9.8 / 2014-10-17
==================

  * Fix `res.redirect` body when redirect status specified
  * deps: accepts@~1.1.2
    - Fix error when media type has invalid parameter
    - deps: negotiator@0.4.9

4.9.7 / 2014-10-10
==================

  * Fix using same param name in array of paths

4.9.6 / 2014-10-08
==================

  * deps: accepts@~1.1.1
    - deps: mime-types@~2.0.2
    - deps: negotiator@0.4.8
  * deps: serve-static@~1.6.4
    - Fix redirect loop when index file serving disabled
  * deps: type-is@~1.5.2
    - deps: mime-types@~2.0.2

4.9.5 / 2014-09-24
==================

  * deps: etag@~1.4.0
  * deps: proxy-addr@~1.0.3
    - Use `forwarded` npm module
  * deps: send@0.9.3
    - deps: etag@~1.4.0
  * deps: serve-static@~1.6.3
    - deps: send@0.9.3

4.9.4 / 2014-09-19
==================

  * deps: qs@2.2.4
    - Fix issue with object keys starting with numbers truncated

4.9.3 / 2014-09-18
==================

  * deps: proxy-addr@~1.0.2
    - Fix a global leak when multiple subnets are trusted
    - deps: ipaddr.js@0.1.3

4.9.2 / 2014-09-17
==================

  * Fix regression for empty string `path` in `app.use`
  * Fix `router.use` to accept array of middleware without path
  * Improve error message for bad `app.use` arguments

4.9.1 / 2014-09-16
==================

  * Fix `app.use` to accept array of middleware without path
  * deps: depd@0.4.5
  * deps: etag@~1.3.1
  * deps: send@0.9.2
    - deps: depd@0.4.5
    - deps: etag@~1.3.1
    - deps: range-parser@~1.0.2
  * deps: serve-static@~1.6.2
    - deps: send@0.9.2

4.9.0 / 2014-09-08
==================

  * Add `res.sendStatus`
  * Invoke callback for sendfile when client aborts
    - Applies to `res.sendFile`, `res.sendfile`, and `res.download`
    - `err` will be populated with request aborted error
  * Support IP address host in `req.subdomains`
  * Use `etag` to generate `ETag` headers
  * deps: accepts@~1.1.0
    - update `mime-types`
  * deps: cookie-signature@1.0.5
  * deps: debug@~2.0.0
  * deps: finalhandler@0.2.0
    - Set `X-Content-Type-Options: nosniff` header
    - deps: debug@~2.0.0
  * deps: fresh@0.2.4
  * deps: media-typer@0.3.0
    - Throw error when parameter format invalid on parse
  * deps: qs@2.2.3
    - Fix issue where first empty value in array is discarded
  * deps: range-parser@~1.0.2
  * deps: send@0.9.1
    - Add `lastModified` option
    - Use `etag` to generate `ETag` header
    - deps: debug@~2.0.0
    - deps: fresh@0.2.4
  * deps: serve-static@~1.6.1
    - Add `lastModified` option
    - deps: send@0.9.1
  * deps: type-is@~1.5.1
    - fix `hasbody` to be true for `content-length: 0`
    - deps: media-typer@0.3.0
    - deps: mime-types@~2.0.1
  * deps: vary@~1.0.0
    - Accept valid `Vary` header string as `field`

4.8.8 / 2014-09-04
==================

  * deps: send@0.8.5
    - Fix a path traversal issue when using `root`
    - Fix malicious path detection for empty string path
  * deps: serve-static@~1.5.4
    - deps: send@0.8.5

4.8.7 / 2014-08-29
==================

  * deps: qs@2.2.2
    - Remove unnecessary cloning

4.8.6 / 2014-08-27
==================

  * deps: qs@2.2.0
    - Array parsing fix
    - Performance improvements

4.8.5 / 2014-08-18
==================

  * deps: send@0.8.3
    - deps: destroy@1.0.3
    - deps: on-finished@2.1.0
  * deps: serve-static@~1.5.3
    - deps: send@0.8.3

4.8.4 / 2014-08-14
==================

  * deps: qs@1.2.2
  * deps: send@0.8.2
    - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream`
  * deps: serve-static@~1.5.2
    - deps: send@0.8.2

4.8.3 / 2014-08-10
==================

  * deps: parseurl@~1.3.0
  * deps: qs@1.2.1
  * deps: serve-static@~1.5.1
    - Fix parsing of weird `req.originalUrl` values
    - deps: parseurl@~1.3.0
    - deps: utils-merge@1.0.0

4.8.2 / 2014-08-07
==================

  * deps: qs@1.2.0
    - Fix parsing array of objects

4.8.1 / 2014-08-06
==================

  * fix incorrect deprecation warnings on `res.download`
  * deps: qs@1.1.0
    - Accept urlencoded square brackets
    - Accept empty values in implicit array notation

4.8.0 / 2014-08-05
==================

  * add `res.sendFile`
    - accepts a file system path instead of a URL
    - requires an absolute path or `root` option specified
  * deprecate `res.sendfile` -- use `res.sendFile` instead
  * support mounted app as any argument to `app.use()`
  * deps: qs@1.0.2
    - Complete rewrite
    - Limits array length to 20
    - Limits object depth to 5
    - Limits parameters to 1,000
  * deps: send@0.8.1
    - Add `extensions` option
  * deps: serve-static@~1.5.0
    - Add `extensions` option
    - deps: send@0.8.1

4.7.4 / 2014-08-04
==================

  * fix `res.sendfile` regression for serving directory index files
  * deps: send@0.7.4
    - Fix incorrect 403 on Windows and Node.js 0.11
    - Fix serving index files without root dir
  * deps: serve-static@~1.4.4
    - deps: send@0.7.4

4.7.3 / 2014-08-04
==================

  * deps: send@0.7.3
    - Fix incorrect 403 on Windows and Node.js 0.11
  * deps: serve-static@~1.4.3
    - Fix incorrect 403 on Windows and Node.js 0.11
    - deps: send@0.7.3

4.7.2 / 2014-07-27
==================

  * deps: depd@0.4.4
    - Work-around v8 generating empty stack traces
  * deps: send@0.7.2
    - deps: depd@0.4.4
  * deps: serve-static@~1.4.2

4.7.1 / 2014-07-26
==================

  * deps: depd@0.4.3
    - Fix exception when global `Error.stackTraceLimit` is too low
  * deps: send@0.7.1
    - deps: depd@0.4.3
  * deps: serve-static@~1.4.1

4.7.0 / 2014-07-25
==================

  * fix `req.protocol` for proxy-direct connections
  * configurable query parser with `app.set('query parser', parser)`
    - `app.set('query parser', 'extended')` parse with "qs" module
    - `app.set('query parser', 'simple')` parse with "querystring" core module
    - `app.set('query parser', false)` disable query string parsing
    - `app.set('query parser', true)` enable simple parsing
  * deprecate `res.json(status, obj)` -- use `res.status(status).json(obj)` instead
  * deprecate `res.jsonp(status, obj)` -- use `res.status(status).jsonp(obj)` instead
  * deprecate `res.send(status, body)` -- use `res.status(status).send(body)` instead
  * deps: debug@1.0.4
  * deps: depd@0.4.2
    - Add `TRACE_DEPRECATION` environment variable
    - Remove non-standard grey color from color output
    - Support `--no-deprecation` argument
    - Support `--trace-deprecation` argument
  * deps: finalhandler@0.1.0
    - Respond after request fully read
    - deps: debug@1.0.4
  * deps: parseurl@~1.2.0
    - Cache URLs based on original value
    - Remove no-longer-needed URL mis-parse work-around
    - Simplify the "fast-path" `RegExp`
  * deps: send@0.7.0
    - Add `dotfiles` option
    - Cap `maxAge` value to 1 year
    - deps: debug@1.0.4
    - deps: depd@0.4.2
  * deps: serve-static@~1.4.0
    - deps: parseurl@~1.2.0
    - deps: send@0.7.0
  * perf: prevent multiple `Buffer` creation in `res.send`

4.6.1 / 2014-07-12
==================

  * fix `subapp.mountpath` regression for `app.use(subapp)`

4.6.0 / 2014-07-11
==================

  * accept multiple callbacks to `app.use()`
  * add explicit "Rosetta Flash JSONP abuse" protection
    - previous versions are not vulnerable; this is just explicit protection
  * catch errors in multiple `req.param(name, fn)` handlers
  * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead
  * fix `res.send(status, num)` to send `num` as json (not error)
  * remove unnecessary escaping when `res.jsonp` returns JSON response
  * support non-string `path` in `app.use(path, fn)`
    - supports array of paths
    - supports `RegExp`
  * router: fix optimization on router exit
  * router: refactor location of `try` blocks
  * router: speed up standard `app.use(fn)`
  * deps: debug@1.0.3
    - Add support for multiple wildcards in namespaces
  * deps: finalhandler@0.0.3
    - deps: debug@1.0.3
  * deps: methods@1.1.0
    - add `CONNECT`
  * deps: parseurl@~1.1.3
    - faster parsing of href-only URLs
  * deps: path-to-regexp@0.1.3
  * deps: send@0.6.0
    - deps: debug@1.0.3
  * deps: serve-static@~1.3.2
    - deps: parseurl@~1.1.3
    - deps: send@0.6.0
  * perf: fix arguments reassign deopt in some `res` methods

4.5.1 / 2014-07-06
==================

 * fix routing regression when altering `req.method`

4.5.0 / 2014-07-04
==================

 * add deprecation message to non-plural `req.accepts*`
 * add deprecation message to `res.send(body, status)`
 * add deprecation message to `res.vary()`
 * add `headers` option to `res.sendfile`
   - use to set headers on successful file transfer
 * add `mergeParams` option to `Router`
   - merges `req.params` from parent routes
 * add `req.hostname` -- correct name for what `req.host` returns
 * deprecate things with `depd` module
 * deprecate `req.host` -- use `req.hostname` instead
 * fix behavior when handling request without routes
 * fix handling when `route.all` is only route
 * invoke `router.param()` only when route matches
 * restore `req.params` after invoking router
 * use `finalhandler` for final response handling
 * use `media-typer` to alter content-type charset
 * deps: accepts@~1.0.7
 * deps: send@0.5.0
   - Accept string for `maxage` (converted by `ms`)
   - Include link in default redirect response
 * deps: serve-static@~1.3.0
   - Accept string for `maxAge` (converted by `ms`)
   - Add `setHeaders` option
   - Include HTML link in redirect response
   - deps: send@0.5.0
 * deps: type-is@~1.3.2

4.4.5 / 2014-06-26
==================

 * deps: cookie-signature@1.0.4
   - fix for timing attacks

4.4.4 / 2014-06-20
==================

 * fix `res.attachment` Unicode filenames in Safari
 * fix "trim prefix" debug message in `express:router`
 * deps: accepts@~1.0.5
 * deps: buffer-crc32@0.2.3

4.4.3 / 2014-06-11
==================

 * fix persistence of modified `req.params[name]` from `app.param()`
 * deps: accepts@1.0.3
   - deps: negotiator@0.4.6
 * deps: debug@1.0.2
 * deps: send@0.4.3
   - Do not throw uncatchable error on file open race condition
   - Use `escape-html` for HTML escaping
   - deps: debug@1.0.2
   - deps: finished@1.2.2
   - deps: fresh@0.2.2
 * deps: serve-static@1.2.3
   - Do not throw uncatchable error on file open race condition
   - deps: send@0.4.3

4.4.2 / 2014-06-09
==================

 * fix catching errors from top-level handlers
 * use `vary` module for `res.vary`
 * deps: debug@1.0.1
 * deps: proxy-addr@1.0.1
 * deps: send@0.4.2
   - fix "event emitter leak" warnings
   - deps: debug@1.0.1
   - deps: finished@1.2.1
 * deps: serve-static@1.2.2
   - fix "event emitter leak" warnings
   - deps: send@0.4.2
 * deps: type-is@1.2.1

4.4.1 / 2014-06-02
==================

 * deps: methods@1.0.1
 * deps: send@0.4.1
   - Send `max-age` in `Cache-Control` in correct format
 * deps: serve-static@1.2.1
   - use `escape-html` for escaping
   - deps: send@0.4.1

4.4.0 / 2014-05-30
==================

 * custom etag control with `app.set('etag', val)`
   - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation
   - `app.set('etag', 'weak')` weak tag
   - `app.set('etag', 'strong')` strong etag
   - `app.set('etag', false)` turn off
   - `app.set('etag', true)` standard etag
 * mark `res.send` ETag as weak and reduce collisions
 * update accepts to 1.0.2
   - Fix interpretation when header not in request
 * update send to 0.4.0
   - Calculate ETag with md5 for reduced collisions
   - Ignore stream errors after request ends
   - deps: debug@0.8.1
 * update serve-static to 1.2.0
   - Calculate ETag with md5 for reduced collisions
   - Ignore stream errors after request ends
   - deps: send@0.4.0

4.3.2 / 2014-05-28
==================

 * fix handling of errors from `router.param()` callbacks

4.3.1 / 2014-05-23
==================

 * revert "fix behavior of multiple `app.VERB` for the same path"
   - this caused a regression in the order of route execution

4.3.0 / 2014-05-21
==================

 * add `req.baseUrl` to access the path stripped from `req.url` in routes
 * fix behavior of multiple `app.VERB` for the same path
 * fix issue routing requests among sub routers
 * invoke `router.param()` only when necessary instead of every match
 * proper proxy trust with `app.set('trust proxy', trust)`
   - `app.set('trust proxy', 1)` trust first hop
   - `app.set('trust proxy', 'loopback')` trust loopback addresses
   - `app.set('trust proxy', '10.0.0.1')` trust single IP
   - `app.set('trust proxy', '10.0.0.1/16')` trust subnet
   - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list
   - `app.set('trust proxy', false)` turn off
   - `app.set('trust proxy', true)` trust everything
 * set proper `charset` in `Content-Type` for `res.send`
 * update type-is to 1.2.0
   - support suffix matching

4.2.0 / 2014-05-11
==================

 * deprecate `app.del()` -- use `app.delete()` instead
 * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead
   - the edge-case `res.json(status, num)` requires `res.status(status).json(num)`
 * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead
   - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)`
 * fix `req.next` when inside router instance
 * include `ETag` header in `HEAD` requests
 * keep previous `Content-Type` for `res.jsonp`
 * support PURGE method
   - add `app.purge`
   - add `router.purge`
   - include PURGE in `app.all`
 * update debug to 0.8.0
   - add `enable()` method
   - change from stderr to stdout
 * update methods to 1.0.0
   - add PURGE

4.1.2 / 2014-05-08
==================

 * fix `req.host` for IPv6 literals
 * fix `res.jsonp` error if callback param is object

4.1.1 / 2014-04-27
==================

 * fix package.json to reflect supported node version

4.1.0 / 2014-04-24
==================

 * pass options from `res.sendfile` to `send`
 * preserve casing of headers in `res.header` and `res.set`
 * support unicode file names in `res.attachment` and `res.download`
 * update accepts to 1.0.1
   - deps: negotiator@0.4.0
 * update cookie to 0.1.2
   - Fix for maxAge == 0
   - made compat with expires field
 * update send to 0.3.0
   - Accept API options in options object
   - Coerce option types
   - Control whether to generate etags
   - Default directory access to 403 when index disabled
   - Fix sending files with dots without root set
   - Include file path in etag
   - Make "Can't set headers after they are sent." catchable
   - Send full entity-body for multi range requests
   - Set etags to "weak"
   - Support "If-Range" header
   - Support multiple index paths
   - deps: mime@1.2.11
 * update serve-static to 1.1.0
   - Accept options directly to `send` module
   - Resolve relative paths at middleware setup
   - Use parseurl to parse the URL from request
   - deps: send@0.3.0
 * update type-is to 1.1.0
   - add non-array values support
   - add `multipart` as a shorthand

4.0.0 / 2014-04-09
==================

 * remove:
   - node 0.8 support
   - connect and connect's patches except for charset handling
   - express(1) - moved to [express-generator](https://github.com/expressjs/generator)
   - `express.createServer()` - it has been deprecated for a long time. Use `express()`
   - `app.configure` - use logic in your own app code
   - `app.router` - is removed
   - `req.auth` - use `basic-auth` instead
   - `req.accepted*` - use `req.accepts*()` instead
   - `res.location` - relative URL resolution is removed
   - `res.charset` - include the charset in the content type when using `res.set()`
   - all bundled middleware except `static`
 * change:
   - `app.route` -> `app.mountpath` when mounting an express app in another express app
   - `json spaces` no longer enabled by default in development
   - `req.accepts*` -> `req.accepts*s` - i.e. `req.acceptsEncoding` -> `req.acceptsEncodings`
   - `req.params` is now an object instead of an array
   - `res.locals` is no longer a function. It is a plain js object. Treat it as such.
   - `res.headerSent` -> `res.headersSent` to match node.js ServerResponse object
 * refactor:
   - `req.accepts*` with [accepts](https://github.com/expressjs/accepts)
   - `req.is` with [type-is](https://github.com/expressjs/type-is)
   - [path-to-regexp](https://github.com/component/path-to-regexp)
 * add:
   - `app.router()` - returns the app Router instance
   - `app.route()` - Proxy to the app's `Router#route()` method to create a new route
   - Router & Route - public API

3.21.2 / 2015-07-31
===================

  * deps: connect@2.30.2
    - deps: body-parser@~1.13.3
    - deps: compression@~1.5.2
    - deps: errorhandler@~1.4.2
    - deps: method-override@~2.3.5
    - deps: serve-index@~1.7.2
    - deps: type-is@~1.6.6
    - deps: vhost@~3.0.1
  * deps: vary@~1.0.1
    - Fix setting empty header from empty `field`
    - perf: enable strict mode
    - perf: remove argument reassignments

3.21.1 / 2015-07-05
===================

  * deps: basic-auth@~1.0.3
  * deps: connect@2.30.1
    - deps: body-parser@~1.13.2
    - deps: compression@~1.5.1
    - deps: errorhandler@~1.4.1
    - deps: morgan@~1.6.1
    - deps: pause@0.1.0
    - deps: qs@4.0.0
    - deps: serve-index@~1.7.1
    - deps: type-is@~1.6.4

3.21.0 / 2015-06-18
===================

  * deps: basic-auth@1.0.2
    - perf: enable strict mode
    - perf: hoist regular expression
    - perf: parse with regular expressions
    - perf: remove argument reassignment
  * deps: connect@2.30.0
    - deps: body-parser@~1.13.1
    - deps: bytes@2.1.0
    - deps: compression@~1.5.0
    - deps: cookie@0.1.3
    - deps: cookie-parser@~1.3.5
    - deps: csurf@~1.8.3
    - deps: errorhandler@~1.4.0
    - deps: express-session@~1.11.3
    - deps: finalhandler@0.4.0
    - deps: fresh@0.3.0
    - deps: morgan@~1.6.0
    - deps: serve-favicon@~2.3.0
    - deps: serve-index@~1.7.0
    - deps: serve-static@~1.10.0
    - deps: type-is@~1.6.3
  * deps: cookie@0.1.3
    - perf: deduce the scope of try-catch deopt
    - perf: remove argument reassignments
  * deps: escape-html@1.0.2
  * deps: etag@~1.7.0
    - Always include entity length in ETags for hash length extensions
    - Generate non-Stats ETags using MD5 only (no longer CRC32)
    - Improve stat performance by removing hashing
    - Improve support for JXcore
    - Remove base64 padding in ETags to shorten
    - Support "fake" stats objects in environments without fs
    - Use MD5 instead of MD4 in weak ETags over 1KB
  * deps: fresh@0.3.0
    - Add weak `ETag` matching support
  * deps: mkdirp@0.5.1
    - Work in global strict mode
  * deps: send@0.13.0
    - Allow Node.js HTTP server to set `Date` response header
    - Fix incorrectly removing `Content-Location` on 304 response
    - Improve the default redirect response headers
    - Send appropriate headers on default error response
    - Use `http-errors` for standard emitted errors
    - Use `statuses` instead of `http` module for status messages
    - deps: escape-html@1.0.2
    - deps: etag@~1.7.0
    - deps: fresh@0.3.0
    - deps: on-finished@~2.3.0
    - perf: enable strict mode
    - perf: remove unnecessary array allocations

3.20.3 / 2015-05-17
===================

  * deps: connect@2.29.2
    - deps: body-parser@~1.12.4
    - deps: compression@~1.4.4
    - deps: connect-timeout@~1.6.2
    - deps: debug@~2.2.0
    - deps: depd@~1.0.1
    - deps: errorhandler@~1.3.6
    - deps: finalhandler@0.3.6
    - deps: method-override@~2.3.3
    - deps: morgan@~1.5.3
    - deps: qs@2.4.2
    - deps: response-time@~2.3.1
    - deps: serve-favicon@~2.2.1
    - deps: serve-index@~1.6.4
    - deps: serve-static@~1.9.3
    - deps: type-is@~1.6.2
  * deps: debug@~2.2.0
    - deps: ms@0.7.1
  * deps: depd@~1.0.1
  * deps: proxy-addr@~1.0.8
    - deps: ipaddr.js@1.0.1
  * deps: send@0.12.3
    - deps: debug@~2.2.0
    - deps: depd@~1.0.1
    - deps: etag@~1.6.0
    - deps: ms@0.7.1
    - deps: on-finished@~2.2.1

3.20.2 / 2015-03-16
===================

  * deps: connect@2.29.1
    - deps: body-parser@~1.12.2
    - deps: compression@~1.4.3
    - deps: connect-timeout@~1.6.1
    - deps: debug@~2.1.3
    - deps: errorhandler@~1.3.5
    - deps: express-session@~1.10.4
    - deps: finalhandler@0.3.4
    - deps: method-override@~2.3.2
    - deps: morgan@~1.5.2
    - deps: qs@2.4.1
    - deps: serve-index@~1.6.3
    - deps: serve-static@~1.9.2
    - deps: type-is@~1.6.1
  * deps: debug@~2.1.3
    - Fix high intensity foreground color for bold
    - deps: ms@0.7.0
  * deps: merge-descriptors@1.0.0
  * deps: proxy-addr@~1.0.7
    - deps: ipaddr.js@0.1.9
  * deps: send@0.12.2
    - Throw errors early for invalid `extensions` or `index` options
    - deps: debug@~2.1.3

3.20.1 / 2015-02-28
===================

  * Fix `req.host` when using "trust proxy" hops count
  * Fix `req.protocol`/`req.secure` when using "trust proxy" hops count

3.20.0 / 2015-02-18
===================

  * Fix `"trust proxy"` setting to inherit when app is mounted
  * Generate `ETag`s for all request responses
    - No longer restricted to only responses for `GET` and `HEAD` requests
  * Use `content-type` to parse `Content-Type` headers
  * deps: connect@2.29.0
    - Use `content-type` to parse `Content-Type` headers
    - deps: body-parser@~1.12.0
    - deps: compression@~1.4.1
    - deps: connect-timeout@~1.6.0
    - deps: cookie-parser@~1.3.4
    - deps: cookie-signature@1.0.6
    - deps: csurf@~1.7.0
    - deps: errorhandler@~1.3.4
    - deps: express-session@~1.10.3
    - deps: http-errors@~1.3.1
    - deps: response-time@~2.3.0
    - deps: serve-index@~1.6.2
    - deps: serve-static@~1.9.1
    - deps: type-is@~1.6.0
  * deps: cookie-signature@1.0.6
  * deps: send@0.12.1
    - Always read the stat size from the file
    - Fix mutating passed-in `options`
    - deps: mime@1.3.4

3.19.2 / 2015-02-01
===================

  * deps: connect@2.28.3
    - deps: compression@~1.3.1
    - deps: csurf@~1.6.6
    - deps: errorhandler@~1.3.3
    - deps: express-session@~1.10.2
    - deps: serve-index@~1.6.1
    - deps: type-is@~1.5.6
  * deps: proxy-addr@~1.0.6
    - deps: ipaddr.js@0.1.8

3.19.1 / 2015-01-20
===================

  * deps: connect@2.28.2
    - deps: body-parser@~1.10.2
    - deps: serve-static@~1.8.1
  * deps: send@0.11.1
    - Fix root path disclosure

3.19.0 / 2015-01-09
===================

  * Fix `OPTIONS` responses to include the `HEAD` method property
  * Use `readline` for prompt in `express(1)`
  * deps: commander@2.6.0
  * deps: connect@2.28.1
    - deps: body-parser@~1.10.1
    - deps: compression@~1.3.0
    - deps: connect-timeout@~1.5.0
    - deps: csurf@~1.6.4
    - deps: debug@~2.1.1
    - deps: errorhandler@~1.3.2
    - deps: express-session@~1.10.1
    - deps: finalhandler@0.3.3
    - deps: method-override@~2.3.1
    - deps: morgan@~1.5.1
    - deps: serve-favicon@~2.2.0
    - deps: serve-index@~1.6.0
    - deps: serve-static@~1.8.0
    - deps: type-is@~1.5.5
  * deps: debug@~2.1.1
  * deps: methods@~1.1.1
  * deps: proxy-addr@~1.0.5
    - deps: ipaddr.js@0.1.6
  * deps: send@0.11.0
    - deps: debug@~2.1.1
    - deps: etag@~1.5.1
    - deps: ms@0.7.0
    - deps: on-finished@~2.2.0

3.18.6 / 2014-12-12
===================

  * Fix exception in `req.fresh`/`req.stale` without response headers

3.18.5 / 2014-12-11
===================

  * deps: connect@2.27.6
    - deps: compression@~1.2.2
    - deps: express-session@~1.9.3
    - deps: http-errors@~1.2.8
    - deps: serve-index@~1.5.3
    - deps: type-is@~1.5.4

3.18.4 / 2014-11-23
===================

  * deps: connect@2.27.4
    - deps: body-parser@~1.9.3
    - deps: compression@~1.2.1
    - deps: errorhandler@~1.2.3
    - deps: express-session@~1.9.2
    - deps: qs@2.3.3
    - deps: serve-favicon@~2.1.7
    - deps: serve-static@~1.5.1
    - deps: type-is@~1.5.3
  * deps: etag@~1.5.1
  * deps: proxy-addr@~1.0.4
    - deps: ipaddr.js@0.1.5

3.18.3 / 2014-11-09
===================

  * deps: connect@2.27.3
    - Correctly invoke async callback asynchronously
    - deps: csurf@~1.6.3

3.18.2 / 2014-10-28
===================

  * deps: connect@2.27.2
    - Fix handling of URLs containing `://` in the path
    - deps: body-parser@~1.9.2
    - deps: qs@2.3.2

3.18.1 / 2014-10-22
===================

  * Fix internal `utils.merge` deprecation warnings
  * deps: connect@2.27.1
    - deps: body-parser@~1.9.1
    - deps: express-session@~1.9.1
    - deps: finalhandler@0.3.2
    - deps: morgan@~1.4.1
    - deps: qs@2.3.0
    - deps: serve-static@~1.7.1
  * deps: send@0.10.1
    - deps: on-finished@~2.1.1

3.18.0 / 2014-10-17
===================

  * Use `content-disposition` module for `res.attachment`/`res.download`
    - Sends standards-compliant `Content-Disposition` header
    - Full Unicode support
  * Use `etag` module to generate `ETag` headers
  * deps: connect@2.27.0
    - Use `http-errors` module for creating errors
    - Use `utils-merge` module for merging objects
    - deps: body-parser@~1.9.0
    - deps: compression@~1.2.0
    - deps: connect-timeout@~1.4.0
    - deps: debug@~2.1.0
    - deps: depd@~1.0.0
    - deps: express-session@~1.9.0
    - deps: finalhandler@0.3.1
    - deps: method-override@~2.3.0
    - deps: morgan@~1.4.0
    - deps: response-time@~2.2.0
    - deps: serve-favicon@~2.1.6
    - deps: serve-index@~1.5.0
    - deps: serve-static@~1.7.0
  * deps: debug@~2.1.0
    - Implement `DEBUG_FD` env variable support
  * deps: depd@~1.0.0
  * deps: send@0.10.0
    - deps: debug@~2.1.0
    - deps: depd@~1.0.0
    - deps: etag@~1.5.0

3.17.8 / 2014-10-15
===================

  * deps: connect@2.26.6
    - deps: compression@~1.1.2
    - deps: csurf@~1.6.2
    - deps: errorhandler@~1.2.2

3.17.7 / 2014-10-08
===================

  * deps: connect@2.26.5
    - Fix accepting non-object arguments to `logger`
    - deps: serve-static@~1.6.4

3.17.6 / 2014-10-02
===================

  * deps: connect@2.26.4
    - deps: morgan@~1.3.2
    - deps: type-is@~1.5.2

3.17.5 / 2014-09-24
===================

  * deps: connect@2.26.3
    - deps: body-parser@~1.8.4
    - deps: serve-favicon@~2.1.5
    - deps: serve-static@~1.6.3
  * deps: proxy-addr@~1.0.3
    - Use `forwarded` npm module
  * deps: send@0.9.3
    - deps: etag@~1.4.0

3.17.4 / 2014-09-19
===================

  * deps: connect@2.26.2
    - deps: body-parser@~1.8.3
    - deps: qs@2.2.4

3.17.3 / 2014-09-18
===================

  * deps: proxy-addr@~1.0.2
    - Fix a global leak when multiple subnets are trusted
    - deps: ipaddr.js@0.1.3

3.17.2 / 2014-09-15
===================

  * Use `crc` instead of `buffer-crc32` for speed
  * deps: connect@2.26.1
    - deps: body-parser@~1.8.2
    - deps: depd@0.4.5
    - deps: express-session@~1.8.2
    - deps: morgan@~1.3.1
    - deps: serve-favicon@~2.1.3
    - deps: serve-static@~1.6.2
  * deps: depd@0.4.5
  * deps: send@0.9.2
    - deps: depd@0.4.5
    - deps: etag@~1.3.1
    - deps: range-parser@~1.0.2

3.17.1 / 2014-09-08
===================

  * Fix error in `req.subdomains` on empty host

3.17.0 / 2014-09-08
===================

  * Support `X-Forwarded-Host` in `req.subdomains`
  * Support IP address host in `req.subdomains`
  * deps: connect@2.26.0
    - deps: body-parser@~1.8.1
    - deps: compression@~1.1.0
    - deps: connect-timeout@~1.3.0
    - deps: cookie-parser@~1.3.3
    - deps: cookie-signature@1.0.5
    - deps: csurf@~1.6.1
    - deps: debug@~2.0.0
    - deps: errorhandler@~1.2.0
    - deps: express-session@~1.8.1
    - deps: finalhandler@0.2.0
    - deps: fresh@0.2.4
    - deps: media-typer@0.3.0
    - deps: method-override@~2.2.0
    - deps: morgan@~1.3.0
    - deps: qs@2.2.3
    - deps: serve-favicon@~2.1.3
    - deps: serve-index@~1.2.1
    - deps: serve-static@~1.6.1
    - deps: type-is@~1.5.1
    - deps: vhost@~3.0.0
  * deps: cookie-signature@1.0.5
  * deps: debug@~2.0.0
  * deps: fresh@0.2.4
  * deps: media-typer@0.3.0
    - Throw error when parameter format invalid on parse
  * deps: range-parser@~1.0.2
  * deps: send@0.9.1
    - Add `lastModified` option
    - Use `etag` to generate `ETag` header
    - deps: debug@~2.0.0
    - deps: fresh@0.2.4
  * deps: vary@~1.0.0
    - Accept valid `Vary` header string as `field`

3.16.10 / 2014-09-04
====================

  * deps: connect@2.25.10
    - deps: serve-static@~1.5.4
  * deps: send@0.8.5
    - Fix a path traversal issue when using `root`
    - Fix malicious path detection for empty string path

3.16.9 / 2014-08-29
===================

  * deps: connect@2.25.9
    - deps: body-parser@~1.6.7
    - deps: qs@2.2.2

3.16.8 / 2014-08-27
===================

  * deps: connect@2.25.8
    - deps: body-parser@~1.6.6
    - deps: csurf@~1.4.1
    - deps: qs@2.2.0

3.16.7 / 2014-08-18
===================

  * deps: connect@2.25.7
    - deps: body-parser@~1.6.5
    - deps: express-session@~1.7.6
    - deps: morgan@~1.2.3
    - deps: serve-static@~1.5.3
  * deps: send@0.8.3
    - deps: destroy@1.0.3
    - deps: on-finished@2.1.0

3.16.6 / 2014-08-14
===================

  * deps: connect@2.25.6
    - deps: body-parser@~1.6.4
    - deps: qs@1.2.2
    - deps: serve-static@~1.5.2
  * deps: send@0.8.2
    - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream`

3.16.5 / 2014-08-11
===================

  * deps: connect@2.25.5
    - Fix backwards compatibility in `logger`

3.16.4 / 2014-08-10
===================

  * Fix original URL parsing in `res.location`
  * deps: connect@2.25.4
    - Fix `query` middleware breaking with argument
    - deps: body-parser@~1.6.3
    - deps: compression@~1.0.11
    - deps: connect-timeout@~1.2.2
    - deps: express-session@~1.7.5
    - deps: method-override@~2.1.3
    - deps: on-headers@~1.0.0
    - deps: parseurl@~1.3.0
    - deps: qs@1.2.1
    - deps: response-time@~2.0.1
    - deps: serve-index@~1.1.6
    - deps: serve-static@~1.5.1
  * deps: parseurl@~1.3.0

3.16.3 / 2014-08-07
===================

  * deps: connect@2.25.3
    - deps: multiparty@3.3.2

3.16.2 / 2014-08-07
===================

  * deps: connect@2.25.2
    - deps: body-parser@~1.6.2
    - deps: qs@1.2.0

3.16.1 / 2014-08-06
===================

  * deps: connect@2.25.1
    - deps: body-parser@~1.6.1
    - deps: qs@1.1.0

3.16.0 / 2014-08-05
===================

  * deps: connect@2.25.0
    - deps: body-parser@~1.6.0
    - deps: compression@~1.0.10
    - deps: csurf@~1.4.0
    - deps: express-session@~1.7.4
    - deps: qs@1.0.2
    - deps: serve-static@~1.5.0
  * deps: send@0.8.1
    - Add `extensions` option

3.15.3 / 2014-08-04
===================

  * fix `res.sendfile` regression for serving directory index files
  * deps: connect@2.24.3
    - deps: serve-index@~1.1.5
    - deps: serve-static@~1.4.4
  * deps: send@0.7.4
    - Fix incorrect 403 on Windows and Node.js 0.11
    - Fix serving index files without root dir

3.15.2 / 2014-07-27
===================

  * deps: connect@2.24.2
    - deps: body-parser@~1.5.2
    - deps: depd@0.4.4
    - deps: express-session@~1.7.2
    - deps: morgan@~1.2.2
    - deps: serve-static@~1.4.2
  * deps: depd@0.4.4
    - Work-around v8 generating empty stack traces
  * deps: send@0.7.2
    - deps: depd@0.4.4

3.15.1 / 2014-07-26
===================

  * deps: connect@2.24.1
    - deps: body-parser@~1.5.1
    - deps: depd@0.4.3
    - deps: express-session@~1.7.1
    - deps: morgan@~1.2.1
    - deps: serve-index@~1.1.4
    - deps: serve-static@~1.4.1
  * deps: depd@0.4.3
    - Fix exception when global `Error.stackTraceLimit` is too low
  * deps: send@0.7.1
    - deps: depd@0.4.3

3.15.0 / 2014-07-22
===================

  * Fix `req.protocol` for proxy-direct connections
  * Pass options from `res.sendfile` to `send`
  * deps: connect@2.24.0
    - deps: body-parser@~1.5.0
    - deps: compression@~1.0.9
    - deps: connect-timeout@~1.2.1
    - deps: debug@1.0.4
    - deps: depd@0.4.2
    - deps: express-session@~1.7.0
    - deps: finalhandler@0.1.0
    - deps: method-override@~2.1.2
    - deps: morgan@~1.2.0
    - deps: multiparty@3.3.1
    - deps: parseurl@~1.2.0
    - deps: serve-static@~1.4.0
  * deps: debug@1.0.4
  * deps: depd@0.4.2
    - Add `TRACE_DEPRECATION` environment variable
    - Remove non-standard grey color from color output
    - Support `--no-deprecation` argument
    - Support `--trace-deprecation` argument
  * deps: parseurl@~1.2.0
    - Cache URLs based on original value
    - Remove no-longer-needed URL mis-parse work-around
    - Simplify the "fast-path" `RegExp`
  * deps: send@0.7.0
    - Add `dotfiles` option
    - Cap `maxAge` value to 1 year
    - deps: debug@1.0.4
    - deps: depd@0.4.2

3.14.0 / 2014-07-11
===================

 * add explicit "Rosetta Flash JSONP abuse" protection
   - previous versions are not vulnerable; this is just explicit protection
 * deprecate `res.redirect(url, status)` -- use `res.redirect(status, url)` instead
 * fix `res.send(status, num)` to send `num` as json (not error)
 * remove unnecessary escaping when `res.jsonp` returns JSON response
 * deps: basic-auth@1.0.0
   - support empty password
   - support empty username
 * deps: connect@2.23.0
   - deps: debug@1.0.3
   - deps: express-session@~1.6.4
   - deps: method-override@~2.1.0
   - deps: parseurl@~1.1.3
   - deps: serve-static@~1.3.1
  * deps: debug@1.0.3
    - Add support for multiple wildcards in namespaces
  * deps: methods@1.1.0
    - add `CONNECT`
  * deps: parseurl@~1.1.3
    - faster parsing of href-only URLs

3.13.0 / 2014-07-03
===================

 * add deprecation message to `app.configure`
 * add deprecation message to `req.auth`
 * use `basic-auth` to parse `Authorization` header
 * deps: connect@2.22.0
   - deps: csurf@~1.3.0
   - deps: express-session@~1.6.1
   - deps: multiparty@3.3.0
   - deps: serve-static@~1.3.0
 * deps: send@0.5.0
   - Accept string for `maxage` (converted by `ms`)
   - Include link in default redirect response

3.12.1 / 2014-06-26
===================

 * deps: connect@2.21.1
   - deps: cookie-parser@1.3.2
   - deps: cookie-signature@1.0.4
   - deps: express-session@~1.5.2
   - deps: type-is@~1.3.2
 * deps: cookie-signature@1.0.4
   - fix for timing attacks

3.12.0 / 2014-06-21
===================

 * use `media-typer` to alter content-type charset
 * 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 get -> append -> set pattern
   - deps: compression@~1.0.8
   - deps: errorhandler@~1.1.1
   - deps: express-session@~1.5.0
   - deps: serve-index@~1.1.3

3.11.0 / 2014-06-19
===================

 * deprecate things with `depd` module
 * deps: buffer-crc32@0.2.3
 * deps: connect@2.20.2
   - deprecate `verify` option to `json` -- use `body-parser` npm module instead
   - deprecate `verify` option to `urlencoded` -- use `body-parser` npm module instead
   - deprecate things with `depd` module
   - use `finalhandler` for final response handling
   - use `media-typer` to parse `content-type` for charset
   - deps: body-parser@1.4.3
   - deps: connect-timeout@1.1.1
   - deps: cookie-parser@1.3.1
   - deps: csurf@1.2.2
   - deps: errorhandler@1.1.0
   - deps: express-session@1.4.0
   - deps: multiparty@3.2.9
   - deps: serve-index@1.1.2
   - deps: type-is@1.3.1
   - deps: vhost@2.0.0

3.10.5 / 2014-06-11
===================

 * deps: connect@2.19.6
   - deps: body-parser@1.3.1
   - deps: compression@1.0.7
   - deps: debug@1.0.2
   - deps: serve-index@1.1.1
   - deps: serve-static@1.2.3
 * deps: debug@1.0.2
 * deps: send@0.4.3
   - Do not throw uncatchable error on file open race condition
   - Use `escape-html` for HTML escaping
   - deps: debug@1.0.2
   - deps: finished@1.2.2
   - deps: fresh@0.2.2

3.10.4 / 2014-06-09
===================

 * deps: connect@2.19.5
   - fix "event emitter leak" warnings
   - deps: csurf@1.2.1
   - deps: debug@1.0.1
   - deps: serve-static@1.2.2
   - deps: type-is@1.2.1
 * deps: debug@1.0.1
 * deps: send@0.4.2
   - fix "event emitter leak" warnings
   - deps: finished@1.2.1
   - deps: debug@1.0.1

3.10.3 / 2014-06-05
===================

 * use `vary` module for `res.vary`
 * deps: connect@2.19.4
   - deps: errorhandler@1.0.2
   - deps: method-override@2.0.2
   - deps: serve-favicon@2.0.1
 * deps: debug@1.0.0

3.10.2 / 2014-06-03
===================

 * deps: connect@2.19.3
   - deps: compression@1.0.6

3.10.1 / 2014-06-03
===================

 * deps: connect@2.19.2
   - deps: compression@1.0.4
 * deps: proxy-addr@1.0.1

3.10.0 / 2014-06-02
===================

 * deps: connect@2.19.1
   - deprecate `methodOverride()` -- use `method-override` npm module instead
   - deps: body-parser@1.3.0
   - deps: method-override@2.0.1
   - deps: multiparty@3.2.8
   - deps: response-time@2.0.0
   - deps: serve-static@1.2.1
 * deps: methods@1.0.1
 * deps: send@0.4.1
   - Send `max-age` in `Cache-Control` in correct format

3.9.0 / 2014-05-30
==================

 * custom etag control with `app.set('etag', val)`
   - `app.set('etag', function(body, encoding){ return '"etag"' })` custom etag generation
   - `app.set('etag', 'weak')` weak tag
   - `app.set('etag', 'strong')` strong etag
   - `app.set('etag', false)` turn off
   - `app.set('etag', true)` standard etag
 * Include ETag in HEAD requests
 * mark `res.send` ETag as weak and reduce collisions
 * update connect to 2.18.0
   - deps: compression@1.0.3
   - deps: serve-index@1.1.0
   - deps: serve-static@1.2.0
 * update send to 0.4.0
   - Calculate ETag with md5 for reduced collisions
   - Ignore stream errors after request ends
   - deps: debug@0.8.1

3.8.1 / 2014-05-27
==================

 * update connect to 2.17.3
   - deps: body-parser@1.2.2
   - deps: express-session@1.2.1
   - deps: method-override@1.0.2

3.8.0 / 2014-05-21
==================

 * keep previous `Content-Type` for `res.jsonp`
 * set proper `charset` in `Content-Type` for `res.send`
 * update connect to 2.17.1
   - fix `res.charset` appending charset when `content-type` has one
   - deps: express-session@1.2.0
   - deps: morgan@1.1.1
   - deps: serve-index@1.0.3

3.7.0 / 2014-05-18
==================

 * proper proxy trust with `app.set('trust proxy', trust)`
   - `app.set('trust proxy', 1)` trust first hop
   - `app.set('trust proxy', 'loopback')` trust loopback addresses
   - `app.set('trust proxy', '10.0.0.1')` trust single IP
   - `app.set('trust proxy', '10.0.0.1/16')` trust subnet
   - `app.set('trust proxy', '10.0.0.1, 10.0.0.2')` trust list
   - `app.set('trust proxy', false)` turn off
   - `app.set('trust proxy', true)` trust everything
 * update connect to 2.16.2
   - deprecate `res.headerSent` -- use `res.headersSent`
   - deprecate `res.on("header")` -- use on-headers module instead
   - fix edge-case in `res.appendHeader` that would append in wrong order
   - json: use body-parser
   - urlencoded: use body-parser
   - dep: bytes@1.0.0
   - dep: cookie-parser@1.1.0
   - dep: csurf@1.2.0
   - dep: express-session@1.1.0
   - dep: method-override@1.0.1

3.6.0 / 2014-05-09
==================

 * deprecate `app.del()` -- use `app.delete()` instead
 * deprecate `res.json(obj, status)` -- use `res.json(status, obj)` instead
   - the edge-case `res.json(status, num)` requires `res.status(status).json(num)`
 * deprecate `res.jsonp(obj, status)` -- use `res.jsonp(status, obj)` instead
   - the edge-case `res.jsonp(status, num)` requires `res.status(status).jsonp(num)`
 * support PURGE method
   - add `app.purge`
   - add `router.purge`
   - include PURGE in `app.all`
 * update connect to 2.15.0
   * Add `res.appendHeader`
   * Call error stack even when response has been sent
   * Patch `res.headerSent` to return Boolean
   * Patch `res.headersSent` for node.js 0.8
   * Prevent default 404 handler after response sent
   * dep: compression@1.0.2
   * dep: connect-timeout@1.1.0
   * dep: debug@^0.8.0
   * dep: errorhandler@1.0.1
   * dep: express-session@1.0.4
   * dep: morgan@1.0.1
   * dep: serve-favicon@2.0.0
   * dep: serve-index@1.0.2
 * update debug to 0.8.0
   * add `enable()` method
   * change from stderr to stdout
 * update methods to 1.0.0
   - add PURGE
 * update mkdirp to 0.5.0

3.5.3 / 2014-05-08
==================

 * fix `req.host` for IPv6 literals
 * fix `res.jsonp` error if callback param is object

3.5.2 / 2014-04-24
==================

 * update connect to 2.14.5
 * update cookie to 0.1.2
 * update mkdirp to 0.4.0
 * update send to 0.3.0

3.5.1 / 2014-03-25
==================

 * pin less-middleware in generated app

3.5.0 / 2014-03-06
==================

 * bump deps

3.4.8 / 2014-01-13
==================

 * prevent incorrect automatic OPTIONS responses #1868 @dpatti
 * update binary and examples for jade 1.0 #1876 @yossi, #1877 @reqshark, #1892 @matheusazzi
 * throw 400 in case of malformed paths @rlidwka

3.4.7 / 2013-12-10
==================

 * update connect

3.4.6 / 2013-12-01
==================

 * update connect (raw-body)

3.4.5 / 2013-11-27
==================

 * update connect
 * res.location: remove leading ./ #1802 @kapouer
 * res.redirect: fix `res.redirect('toString') #1829 @michaelficarra
 * res.send: always send ETag when content-length > 0
 * router: add Router.all() method

3.4.4 / 2013-10-29
==================

 * update connect
 * update supertest
 * update methods
 * express(1): replace bodyParser() with urlencoded() and json() #1795 @chirag04

3.4.3 / 2013-10-23
==================

 * update connect

3.4.2 / 2013-10-18
==================

 * update connect
 * downgrade commander

3.4.1 / 2013-10-15
==================

 * update connect
 * update commander
 * jsonp: check if callback is a function
 * router: wrap encodeURIComponent in a try/catch #1735 (@lxe)
 * res.format: now includes charset @1747 (@sorribas)
 * res.links: allow multiple calls @1746 (@sorribas)

3.4.0 / 2013-09-07
==================

 * add res.vary(). Closes #1682
 * update connect

3.3.8 / 2013-09-02
==================

 * update connect

3.3.7 / 2013-08-28
==================

 * update connect

3.3.6 / 2013-08-27
==================

 * Revert "remove charset from json responses. Closes #1631" (causes issues in some clients)
 * add: req.accepts take an argument list

3.3.4 / 2013-07-08
==================

 * update send and connect

3.3.3 / 2013-07-04
==================

 * update connect

3.3.2 / 2013-07-03
==================

 * update connect
 * update send
 * remove .version export

3.3.1 / 2013-06-27
==================

 * update connect

3.3.0 / 2013-06-26
==================

 * update connect
 * add support for multiple X-Forwarded-Proto values. Closes #1646
 * change: remove charset from json responses. Closes #1631
 * change: return actual booleans from req.accept* functions
 * fix jsonp callback array throw

3.2.6 / 2013-06-02
==================

 * update connect

3.2.5 / 2013-05-21
==================

 * update connect
 * update node-cookie
 * add: throw a meaningful error when there is no default engine
 * change generation of ETags with res.send() to GET requests only. Closes #1619

3.2.4 / 2013-05-09
==================

  * fix `req.subdomains` when no Host is present
  * fix `req.host` when no Host is present, return undefined

3.2.3 / 2013-05-07
==================

  * update connect / qs

3.2.2 / 2013-05-03
==================

  * update qs

3.2.1 / 2013-04-29
==================

  * add app.VERB() paths array deprecation warning
  * update connect
  * update qs and remove all ~ semver crap
  * fix: accept number as value of Signed Cookie

3.2.0 / 2013-04-15
==================

  * add "view" constructor setting to override view behaviour
  * add req.acceptsEncoding(name)
  * add req.acceptedEncodings
  * revert cookie signature change causing session race conditions
  * fix sorting of Accept values of the same quality

3.1.2 / 2013-04-12
==================

  * add support for custom Accept parameters
  * update cookie-signature

3.1.1 / 2013-04-01
==================

  * add X-Forwarded-Host support to `req.host`
  * fix relative redirects
  * update mkdirp
  * update buffer-crc32
  * remove legacy app.configure() method from app template.

3.1.0 / 2013-01-25
==================

  * add support for leading "." in "view engine" setting
  * add array support to `res.set()`
  * add node 0.8.x to travis.yml
  * add "subdomain offset" setting for tweaking `req.subdomains`
  * add `res.location(url)` implementing `res.redirect()`-like setting of Location
  * use app.get() for x-powered-by setting for inheritance
  * fix colons in passwords for `req.auth`

3.0.6 / 2013-01-04
==================

  * add http verb methods to Router
  * update connect
  * fix mangling of the `res.cookie()` options object
  * fix jsonp whitespace escape. Closes #1132

3.0.5 / 2012-12-19
==================

  * add throwing when a non-function is passed to a route
  * fix: explicitly remove Transfer-Encoding header from 204 and 304 responses
  * revert "add 'etag' option"

3.0.4 / 2012-12-05
==================

  * add 'etag' option to disable `res.send()` Etags
  * add escaping of urls in text/plain in `res.redirect()`
    for old browsers interpreting as html
  * change crc32 module for a more liberal license
  * update connect

3.0.3 / 2012-11-13
==================

  * update connect
  * update cookie module
  * fix cookie max-age

3.0.2 / 2012-11-08
==================

  * add OPTIONS to cors example. Closes #1398
  * fix route chaining regression. Closes #1397

3.0.1 / 2012-11-01
==================

  * update connect

3.0.0 / 2012-10-23
==================

  * add `make clean`
  * add "Basic" check to req.auth
  * add `req.auth` test coverage
  * add cb && cb(payload) to `res.jsonp()`. Closes #1374
  * add backwards compat for `res.redirect()` status. Closes #1336
  * add support for `res.json()` to retain previously defined Content-Types. Closes #1349
  * update connect
  * change `res.redirect()` to utilize a pathname-relative Location again. Closes #1382
  * remove non-primitive string support for `res.send()`
  * fix view-locals example. Closes #1370
  * fix route-separation example

3.0.0rc5 / 2012-09-18
==================

  * update connect
  * add redis search example
  * add static-files example
  * add "x-powered-by" setting (`app.disable('x-powered-by')`)
  * add "application/octet-stream" redirect Accept test case. Closes #1317

3.0.0rc4 / 2012-08-30
==================

  * add `res.jsonp()`. Closes #1307
  * add "verbose errors" option to error-pages example
  * add another route example to express(1) so people are not so confused
  * add redis online user activity tracking example
  * update connect dep
  * fix etag quoting. Closes #1310
  * fix error-pages 404 status
  * fix jsonp callback char restrictions
  * remove old OPTIONS default response

3.0.0rc3 / 2012-08-13
==================

  * update connect dep
  * fix signed cookies to work with `connect.cookieParser()` ("s:" prefix was missing) [tnydwrds]
  * fix `res.render()` clobbering of "locals"

3.0.0rc2 / 2012-08-03
==================

  * add CORS example
  * update connect dep
  * deprecate `.createServer()` & remove old stale examples
  * fix: escape `res.redirect()` link
  * fix vhost example

3.0.0rc1 / 2012-07-24
==================

  * add more examples to view-locals
  * add scheme-relative redirects (`res.redirect("//foo.com")`) support
  * update cookie dep
  * update connect dep
  * update send dep
  * fix `express(1)` -h flag, use -H for hogan. Closes #1245
  * fix `res.sendfile()` socket error handling regression

3.0.0beta7 / 2012-07-16
==================

  * update connect dep for `send()` root normalization regression

3.0.0beta6 / 2012-07-13
==================

  * add `err.view` property for view errors. Closes #1226
  * add "jsonp callback name" setting
  * add support for "/foo/:bar*" non-greedy matches
  * change `res.sendfile()` to use `send()` module
  * change `res.send` to use "response-send" module
  * remove `app.locals.use` and `res.locals.use`, use regular middleware

3.0.0beta5 / 2012-07-03
==================

  * add "make check" support
  * add route-map example
  * add `res.json(obj, status)` support back for BC
  * add "methods" dep, remove internal methods module
  * update connect dep
  * update auth example to utilize cores pbkdf2
  * updated tests to use "supertest"

3.0.0beta4 / 2012-06-25
==================

  * Added `req.auth`
  * Added `req.range(size)`
  * Added `res.links(obj)`
  * Added `res.send(body, status)` support back for backwards compat
  * Added `.default()` support to `res.format()`
  * Added 2xx / 304 check to `req.fresh`
  * Revert "Added + support to the router"
  * Fixed `res.send()` freshness check, respect res.statusCode

3.0.0beta3 / 2012-06-15
==================

  * Added hogan `--hjs` to express(1) [nullfirm]
  * Added another example to content-negotiation
  * Added `fresh` dep
  * Changed: `res.send()` always checks freshness
  * Fixed: expose connects mime module. Closes #1165

3.0.0beta2 / 2012-06-06
==================

  * Added `+` support to the router
  * Added `req.host`
  * Changed `req.param()` to check route first
  * Update connect dep

3.0.0beta1 / 2012-06-01
==================

  * Added `res.format()` callback to override default 406 behaviour
  * Fixed `res.redirect()` 406. Closes #1154

3.0.0alpha5 / 2012-05-30
==================

  * Added `req.ip`
  * Added `{ signed: true }` option to `res.cookie()`
  * Removed `res.signedCookie()`
  * Changed: dont reverse `req.ips`
  * Fixed "trust proxy" setting check for `req.ips`

3.0.0alpha4 / 2012-05-09
==================

  * Added: allow `[]` in jsonp callback. Closes #1128
  * Added `PORT` env var support in generated template. Closes #1118 [benatkin]
  * Updated: connect 2.2.2

3.0.0alpha3 / 2012-05-04
==================

  * Added public `app.routes`. Closes #887
  * Added _view-locals_ example
  * Added _mvc_ example
  * Added `res.locals.use()`. Closes #1120
  * Added conditional-GET support to `res.send()`
  * Added: coerce `res.set()` values to strings
  * Changed: moved `static()` in generated apps below router
  * Changed: `res.send()` only set ETag when not previously set
  * Changed connect 2.2.1 dep
  * Changed: `make test` now runs unit / acceptance tests
  * Fixed req/res proto inheritance

3.0.0alpha2 / 2012-04-26
==================

  * Added `make benchmark` back
  * Added `res.send()` support for `String` objects
  * Added client-side data exposing example
  * Added `res.header()` and `req.header()` aliases for BC
  * Added `express.createServer()` for BC
  * Perf: memoize parsed urls
  * Perf: connect 2.2.0 dep
  * Changed: make `expressInit()` middleware self-aware
  * Fixed: use app.get() for all core settings
  * Fixed redis session example
  * Fixed session example. Closes #1105
  * Fixed generated express dep. Closes #1078

3.0.0alpha1 / 2012-04-15
==================

  * Added `app.locals.use(callback)`
  * Added `app.locals` object
  * Added `app.locals(obj)`
  * Added `res.locals` object
  * Added `res.locals(obj)`
  * Added `res.format()` for content-negotiation
  * Added `app.engine()`
  * Added `res.cookie()` JSON cookie support
  * Added "trust proxy" setting
  * Added `req.subdomains`
  * Added `req.protocol`
  * Added `req.secure`
  * Added `req.path`
  * Added `req.ips`
  * Added `req.fresh`
  * Added `req.stale`
  * Added comma-delimited / array support for `req.accepts()`
  * Added debug instrumentation
  * Added `res.set(obj)`
  * Added `res.set(field, value)`
  * Added `res.get(field)`
  * Added `app.get(setting)`. Closes #842
  * Added `req.acceptsLanguage()`
  * Added `req.acceptsCharset()`
  * Added `req.accepted`
  * Added `req.acceptedLanguages`
  * Added `req.acceptedCharsets`
  * Added "json replacer" setting
  * Added "json spaces" setting
  * Added X-Forwarded-Proto support to `res.redirect()`. Closes #92
  * Added `--less` support to express(1)
  * Added `express.response` prototype
  * Added `express.request` prototype
  * Added `express.application` prototype
  * Added `app.path()`
  * Added `app.render()`
  * Added `res.type()` to replace `res.contentType()`
  * Changed: `res.redirect()` to add relative support
  * Changed: enable "jsonp callback" by default
  * Changed: renamed "case sensitive routes" to "case sensitive routing"
  * Rewrite of all tests with mocha
  * Removed "root" setting
  * Removed `res.redirect('home')` support
  * Removed `req.notify()`
  * Removed `app.register()`
  * Removed `app.redirect()`
  * Removed `app.is()`
  * Removed `app.helpers()`
  * Removed `app.dynamicHelpers()`
  * Fixed `res.sendfile()` with non-GET. Closes #723
  * Fixed express(1) public dir for windows. Closes #866

2.5.9/ 2012-04-02
==================

  * Added support for PURGE request method [pbuyle]
  * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki]

2.5.8 / 2012-02-08
==================

  * Update mkdirp dep. Closes #991

2.5.7 / 2012-02-06
==================

  * Fixed `app.all` duplicate DELETE requests [mscdex]

2.5.6 / 2012-01-13
==================

  * Updated hamljs dev dep. Closes #953

2.5.5 / 2012-01-08
==================

  * Fixed: set `filename` on cached templates [matthewleon]

2.5.4 / 2012-01-02
==================

  * Fixed `express(1)` eol on 0.4.x. Closes #947

2.5.3 / 2011-12-30
==================

  * Fixed `req.is()` when a charset is present

2.5.2 / 2011-12-10
==================

  * Fixed: express(1) LF -> CRLF for windows

2.5.1 / 2011-11-17
==================

  * Changed: updated connect to 1.8.x
  * Removed sass.js support from express(1)

2.5.0 / 2011-10-24
==================

  * Added ./routes dir for generated app by default
  * Added npm install reminder to express(1) app gen
  * Added 0.5.x support
  * Removed `make test-cov` since it wont work with node 0.5.x
  * Fixed express(1) public dir for windows. Closes #866

2.4.7 / 2011-10-05
==================

  * Added mkdirp to express(1). Closes #795
  * Added simple _json-config_ example
  * Added  shorthand for the parsed request's pathname via `req.path`
  * Changed connect dep to 1.7.x to fix npm issue...
  * Fixed `res.redirect()` __HEAD__ support. [reported by xerox]
  * Fixed `req.flash()`, only escape args
  * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]

2.4.6 / 2011-08-22
==================

  * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]

2.4.5 / 2011-08-19
==================

  * Added support for routes to handle errors. Closes #809
  * Added `app.routes.all()`. Closes #803
  * Added "basepath" setting to work in conjunction with reverse proxies etc.
  * Refactored `Route` to use a single array of callbacks
  * Added support for multiple callbacks for `app.param()`. Closes #801
Closes #805
  * Changed: removed .call(self) for route callbacks
  * Dependency: `qs >= 0.3.1`
  * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808

2.4.4 / 2011-08-05
==================

  * Fixed `res.header()` intention of a set, even when `undefined`
  * Fixed `*`, value no longer required
  * Fixed `res.send(204)` support. Closes #771

2.4.3 / 2011-07-14
==================

  * Added docs for `status` option special-case. Closes #739
  * Fixed `options.filename`, exposing the view path to template engines

2.4.2. / 2011-07-06
==================

  * Revert "removed jsonp stripping" for XSS

2.4.1 / 2011-07-06
==================

  * Added `res.json()` JSONP support. Closes #737
  * Added _extending-templates_ example. Closes #730
  * Added "strict routing" setting for trailing slashes
  * Added support for multiple envs in `app.configure()` calls. Closes #735
  * Changed: `res.send()` using `res.json()`
  * Changed: when cookie `path === null` don't default it
  * Changed; default cookie path to "home" setting. Closes #731
  * Removed _pids/logs_ creation from express(1)

2.4.0 / 2011-06-28
==================

  * Added chainable `res.status(code)`
  * Added `res.json()`, an explicit version of `res.send(obj)`
  * Added simple web-service example

2.3.12 / 2011-06-22
==================

  * \#express is now on freenode! come join!
  * Added `req.get(field, param)`
  * Added links to Japanese documentation, thanks @hideyukisaito!
  * Added; the `express(1)` generated app outputs the env
  * Added `content-negotiation` example
  * Dependency: connect >= 1.5.1 < 2.0.0
  * Fixed view layout bug. Closes #720
  * Fixed; ignore body on 304. Closes #701

2.3.11 / 2011-06-04
==================

  * Added `npm test`
  * Removed generation of dummy test file from `express(1)`
  * Fixed; `express(1)` adds express as a dep
  * Fixed; prune on `prepublish`

2.3.10 / 2011-05-27
==================

  * Added `req.route`, exposing the current route
  * Added _package.json_ generation support to `express(1)`
  * Fixed call to `app.param()` function for optional params. Closes #682

2.3.9 / 2011-05-25
==================

  * Fixed bug-ish with `../' in `res.partial()` calls

2.3.8 / 2011-05-24
==================

  * Fixed `app.options()`

2.3.7 / 2011-05-23
==================

  * Added route `Collection`, ex: `app.get('/user/:id').remove();`
  * Added support for `app.param(fn)` to define param logic
  * Removed `app.param()` support for callback with return value
  * Removed module.parent check from express(1) generated app. Closes #670
  * Refactored router. Closes #639

2.3.6 / 2011-05-20
==================

  * Changed; using devDependencies instead of git submodules
  * Fixed redis session example
  * Fixed markdown example
  * Fixed view caching, should not be enabled in development

2.3.5 / 2011-05-20
==================

  * Added export `.view` as alias for `.View`

2.3.4 / 2011-05-08
==================

  * Added `./examples/say`
  * Fixed `res.sendfile()` bug preventing the transfer of files with spaces

2.3.3 / 2011-05-03
==================

  * Added "case sensitive routes" option.
  * Changed; split methods supported per rfc [slaskis]
  * Fixed route-specific middleware when using the same callback function several times

2.3.2 / 2011-04-27
==================

  * Fixed view hints

2.3.1 / 2011-04-26
==================

  * Added `app.match()` as `app.match.all()`
  * Added `app.lookup()` as `app.lookup.all()`
  * Added `app.remove()` for `app.remove.all()`
  * Added `app.remove.VERB()`
  * Fixed template caching collision issue. Closes #644
  * Moved router over from connect and started refactor

2.3.0 / 2011-04-25
==================

  * Added options support to `res.clearCookie()`
  * Added `res.helpers()` as alias of `res.locals()`
  * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel   * Dependency `connect >= 1.4.0`
  * Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
  * Renamed "cache views" to "view cache". Closes #628
  * Fixed caching of views when using several apps. Closes #637
  * Fixed gotcha invoking `app.param()` callbacks once per route middleware.
Closes #638
  * Fixed partial lookup precedence. Closes #631
Shaw]

2.2.2 / 2011-04-12
==================

  * Added second callback support for `res.download()` connection errors
  * Fixed `filename` option passing to template engine

2.2.1 / 2011-04-04
==================

  * Added `layout(path)` helper to change the layout within a view. Closes #610
  * Fixed `partial()` collection object support.
    Previously only anything with `.length` would work.
    When `.length` is present one must still be aware of holes,
    however now `{ collection: {foo: 'bar'}}` is valid, exposes
    `keyInCollection` and `keysInCollection`.

  * Performance improved with better view caching
  * Removed `request` and `response` locals
  * Changed; errorHandler page title is now `Express` instead of `Connect`

2.2.0 / 2011-03-30
==================

  * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606
  * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606
  * Added `app.VERB(path)` as alias of `app.lookup.VERB()`.
  * Dependency `connect >= 1.2.0`

2.1.1 / 2011-03-29
==================

  * Added; expose `err.view` object when failing to locate a view
  * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann]
  * Fixed; `res.send(undefined)` responds with 204 [aheckmann]

2.1.0 / 2011-03-24
==================

  * Added `<root>/_?<name>` partial lookup support. Closes #447
  * Added `request`, `response`, and `app` local variables
  * Added `settings` local variable, containing the app's settings
  * Added `req.flash()` exception if `req.session` is not available
  * Added `res.send(bool)` support (json response)
  * Fixed stylus example for latest version
  * Fixed; wrap try/catch around `res.render()`

2.0.0 / 2011-03-17
==================

  * Fixed up index view path alternative.
  * Changed; `res.locals()` without object returns the locals

2.0.0rc3 / 2011-03-17
==================

  * Added `res.locals(obj)` to compliment `res.local(key, val)`
  * Added `res.partial()` callback support
  * Fixed recursive error reporting issue in `res.render()`

2.0.0rc2 / 2011-03-17
==================

  * Changed; `partial()` "locals" are now optional
  * Fixed `SlowBuffer` support. Closes #584 [reported by tyrda01]
  * Fixed .filename view engine option [reported by drudge]
  * Fixed blog example
  * Fixed `{req,res}.app` reference when mounting [Ben Weaver]

2.0.0rc / 2011-03-14
==================

  * Fixed; expose `HTTPSServer` constructor
  * Fixed express(1) default test charset. Closes #579 [reported by secoif]
  * Fixed; default charset to utf-8 instead of utf8 for lame IE [reported by NickP]

2.0.0beta3 / 2011-03-09
==================

  * Added support for `res.contentType()` literal
    The original `res.contentType('.json')`,
    `res.contentType('application/json')`, and `res.contentType('json')`
    will work now.
  * Added `res.render()` status option support back
  * Added charset option for `res.render()`
  * Added `.charset` support (via connect 1.0.4)
  * Added view resolution hints when in development and a lookup fails
  * Added layout lookup support relative to the page view.
    For example while rendering `./views/user/index.jade` if you create
    `./views/user/layout.jade` it will be used in favour of the root layout.
  * Fixed `res.redirect()`. RFC states absolute url [reported by unlink]
  * Fixed; default `res.send()` string charset to utf8
  * Removed `Partial` constructor (not currently used)

2.0.0beta2 / 2011-03-07
==================

  * Added res.render() `.locals` support back to aid in migration process
  * Fixed flash example

2.0.0beta / 2011-03-03
==================

  * Added HTTPS support
  * Added `res.cookie()` maxAge support
  * Added `req.header()` _Referrer_ / _Referer_ special-case, either works
  * Added mount support for `res.redirect()`, now respects the mount-point
  * Added `union()` util, taking place of `merge(clone())` combo
  * Added stylus support to express(1) generated app
  * Added secret to session middleware used in examples and generated app
  * Added `res.local(name, val)` for progressive view locals
  * Added default param support to `req.param(name, default)`
  * Added `app.disabled()` and `app.enabled()`
  * Added `app.register()` support for omitting leading ".", either works
  * Added `res.partial()`, using the same interface as `partial()` within a view. Closes #539
  * Added `app.param()` to map route params to async/sync logic
  * Added; aliased `app.helpers()` as `app.locals()`. Closes #481
  * Added extname with no leading "." support to `res.contentType()`
  * Added `cache views` setting, defaulting to enabled in "production" env
  * Added index file partial resolution, eg: partial('user') may try _views/user/index.jade_.
  * Added `req.accepts()` support for extensions
  * Changed; `res.download()` and `res.sendfile()` now utilize Connect's
    static file server `connect.static.send()`.
  * Changed; replaced `connect.utils.mime()` with npm _mime_ module
  * Changed; allow `req.query` to be pre-defined (via middleware or other parent
  * Changed view partial resolution, now relative to parent view
  * Changed view engine signature. no longer `engine.render(str, options, callback)`, now `engine.compile(str, options) -> Function`, the returned function accepts `fn(locals)`.
  * Fixed `req.param()` bug returning Array.prototype methods. Closes #552
  * Fixed; using `Stream#pipe()` instead of `sys.pump()` in `res.sendfile()`
  * Fixed; using _qs_ module instead of _querystring_
  * Fixed; strip unsafe chars from jsonp callbacks
  * Removed "stream threshold" setting

1.0.8 / 2011-03-01
==================

  * Allow `req.query` to be pre-defined (via middleware or other parent app)
  * "connect": ">= 0.5.0 < 1.0.0". Closes #547
  * Removed the long deprecated __EXPRESS_ENV__ support

1.0.7 / 2011-02-07
==================

  * Fixed `render()` setting inheritance.
    Mounted apps would not inherit "view engine"

1.0.6 / 2011-02-07
==================

  * Fixed `view engine` setting bug when period is in dirname

1.0.5 / 2011-02-05
==================

  * Added secret to generated app `session()` call

1.0.4 / 2011-02-05
==================

  * Added `qs` dependency to _package.json_
  * Fixed namespaced `require()`s for latest connect support

1.0.3 / 2011-01-13
==================

  * Remove unsafe characters from JSONP callback names [Ryan Grove]

1.0.2 / 2011-01-10
==================

  * Removed nested require, using `connect.router`

1.0.1 / 2010-12-29
==================

  * Fixed for middleware stacked via `createServer()`
    previously the `foo` middleware passed to `createServer(foo)`
    would not have access to Express methods such as `res.send()`
    or props like `req.query` etc.

1.0.0 / 2010-11-16
==================

  * Added; deduce partial object names from the last segment.
    For example by default `partial('forum/post', postObject)` will
    give you the _post_ object, providing a meaningful default.
  * Added http status code string representation to `res.redirect()` body
  * Added; `res.redirect()` supporting _text/plain_ and _text/html_ via __Accept__.
  * Added `req.is()` to aid in content negotiation
  * Added partial local inheritance [suggested by masylum]. Closes #102
    providing access to parent template locals.
  * Added _-s, --session[s]_ flag to express(1) to add session related middleware
  * Added _--template_ flag to express(1) to specify the
    template engine to use.
  * Added _--css_ flag to express(1) to specify the
    stylesheet engine to use (or just plain css by default).
  * Added `app.all()` support [thanks aheckmann]
  * Added partial direct object support.
    You may now `partial('user', user)` providing the "user" local,
    vs previously `partial('user', { object: user })`.
  * Added _route-separation_ example since many people question ways
    to do this with CommonJS modules. Also view the _blog_ example for
    an alternative.
  * Performance; caching view path derived partial object names
  * Fixed partial local inheritance precedence. [reported by Nick Poulden] Closes #454
  * Fixed jsonp support; _text/javascript_ as per mailinglist discussion

1.0.0rc4 / 2010-10-14
==================

  * Added _NODE_ENV_ support, _EXPRESS_ENV_ is deprecated and will be removed in 1.0.0
  * Added route-middleware support (very helpful, see the [docs](http://expressjs.com/guide.html#Route-Middleware))
  * Added _jsonp callback_ setting to enable/disable jsonp autowrapping [Dav Glass]
  * Added callback query check on response.send to autowrap JSON objects for simple webservice implementations [Dav Glass]
  * Added `partial()` support for array-like collections. Closes #434
  * Added support for swappable querystring parsers
  * Added session usage docs. Closes #443
  * Added dynamic helper caching. Closes #439 [suggested by maritz]
  * Added authentication example
  * Added basic Range support to `res.sendfile()` (and `res.download()` etc)
  * Changed; `express(1)` generated app using 2 spaces instead of 4
  * Default env to "development" again [aheckmann]
  * Removed _context_ option is no more, use "scope"
  * Fixed; exposing _./support_ libs to examples so they can run without installs
  * Fixed mvc example

1.0.0rc3 / 2010-09-20
==================

  * Added confirmation for `express(1)` app generation. Closes #391
  * Added extending of flash formatters via `app.flashFormatters`
  * Added flash formatter support. Closes #411
  * Added streaming support to `res.sendfile()` using `sys.pump()` when >= "stream threshold"
  * Added _stream threshold_ setting for `res.sendfile()`
  * Added `res.send()` __HEAD__ support
  * Added `res.clearCookie()`
  * Added `res.cookie()`
  * Added `res.render()` headers option
  * Added `res.redirect()` response bodies
  * Added `res.render()` status option support. Closes #425 [thanks aheckmann]
  * Fixed `res.sendfile()` responding with 403 on malicious path
  * Fixed `res.download()` bug; when an error occurs remove _Content-Disposition_
  * Fixed; mounted apps settings now inherit from parent app [aheckmann]
  * Fixed; stripping Content-Length / Content-Type when 204
  * Fixed `res.send()` 204. Closes #419
  * Fixed multiple _Set-Cookie_ headers via `res.header()`. Closes #402
  * Fixed bug messing with error handlers when `listenFD()` is called instead of `listen()`. [thanks guillermo]


1.0.0rc2 / 2010-08-17
==================

  * Added `app.register()` for template engine mapping. Closes #390
  * Added `res.render()` callback support as second argument (no options)
  * Added callback support to `res.download()`
  * Added callback support for `res.sendfile()`
  * Added support for middleware access via `express.middlewareName()` vs `connect.middlewareName()`
  * Added "partials" setting to docs
  * Added default expresso tests to `express(1)` generated app. Closes #384
  * Fixed `res.sendfile()` error handling, defer via `next()`
  * Fixed `res.render()` callback when a layout is used [thanks guillermo]
  * Fixed; `make install` creating ~/.node_libraries when not present
  * Fixed issue preventing error handlers from being defined anywhere. Closes #387

1.0.0rc / 2010-07-28
==================

  * Added mounted hook. Closes #369
  * Added connect dependency to _package.json_

  * Removed "reload views" setting and support code
    development env never caches, production always caches.

  * Removed _param_ in route callbacks, signature is now
    simply (req, res, next), previously (req, res, params, next).
    Use _req.params_ for path captures, _req.query_ for GET params.

  * Fixed "home" setting
  * Fixed middleware/router precedence issue. Closes #366
  * Fixed; _configure()_ callbacks called immediately. Closes #368

1.0.0beta2 / 2010-07-23
==================

  * Added more examples
  * Added; exporting `Server` constructor
  * Added `Server#helpers()` for view locals
  * Added `Server#dynamicHelpers()` for dynamic view locals. Closes #349
  * Added support for absolute view paths
  * Added; _home_ setting defaults to `Server#route` for mounted apps. Closes #363
  * Added Guillermo Rauch to the contributor list
  * Added support for "as" for non-collection partials. Closes #341
  * Fixed _install.sh_, ensuring _~/.node_libraries_ exists. Closes #362 [thanks jf]
  * Fixed `res.render()` exceptions, now passed to `next()` when no callback is given [thanks guillermo]
  * Fixed instanceof `Array` checks, now `Array.isArray()`
  * Fixed express(1) expansion of public dirs. Closes #348
  * Fixed middleware precedence. Closes #345
  * Fixed view watcher, now async [thanks aheckmann]

1.0.0beta / 2010-07-15
==================

  * Re-write
    - much faster
    - much lighter
    - Check [ExpressJS.com](http://expressjs.com) for migration guide and updated docs

0.14.0 / 2010-06-15
==================

  * Utilize relative requires
  * Added Static bufferSize option [aheckmann]
  * Fixed caching of view and partial subdirectories [aheckmann]
  * Fixed mime.type() comments now that ".ext" is not supported
  * Updated haml submodule
  * Updated class submodule
  * Removed bin/express

0.13.0 / 2010-06-01
==================

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

0.12.0 / 2010-05-22
==================

  * Added node v0.1.96 compatibility
  * Added view `helpers` export which act as additional local variables
  * Updated haml submodule
  * Changed ETag; removed inode, modified time only
  * Fixed LF to CRLF for setting multiple cookies
  * Fixed cookie compilation; values are now urlencoded
  * Fixed cookies parsing; accepts quoted values and url escaped cookies

0.11.0 / 2010-05-06
==================

  * Added support for layouts using different engines
    - this.render('page.html.haml', { layout: 'super-cool-layout.html.ejs' })
    - this.render('page.html.haml', { layout: 'foo' }) // assumes 'foo.html.haml'
    - this.render('page.html.haml', { layout: false }) // no layout
  * Updated ext submodule
  * Updated haml submodule
  * Fixed EJS partial support by passing along the context. Issue #307

0.10.1 / 2010-05-03
==================

  * Fixed binary uploads.

0.10.0 / 2010-04-30
==================

  * Added charset support via Request#charset (automatically assigned to 'UTF-8' when respond()'s
    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
  * Added error response support for text/plain, application/json. Closes #297
  * Added callback function param to Request#error()
  * Added Request#sendHead()
  * Added Request#stream()
  * Added support for Request#respond(304, null) for empty response bodies
  * Added ETag support to Request#sendfile()
  * Added options to Request#sendfile(), passed to fs.createReadStream()
  * Added filename arg to Request#download()
  * Performance enhanced due to pre-reversing plugins so that plugins.reverse() is not called on each request
  * Performance enhanced by preventing several calls to toLowerCase() in Router#match()
  * Changed; Request#sendfile() now streams
  * Changed; Renamed Request#halt() to Request#respond(). Closes #289
  * Changed; Using sys.inspect() instead of JSON.encode() for error output
  * Changed; run() returns the http.Server instance. Closes #298
  * Changed; Defaulting Server#host to null (INADDR_ANY)
  * Changed; Logger "common" format scale of 0.4f
  * Removed Logger "request" format
  * Fixed; Catching ENOENT in view caching, preventing error when "views/partials" is not found
  * Fixed several issues with http client
  * Fixed Logger Content-Length output
  * Fixed bug preventing Opera from retaining the generated session id. Closes #292

0.9.0 / 2010-04-14
==================

  * Added DSL level error() route support
  * Added DSL level notFound() route support
  * Added Request#error()
  * Added Request#notFound()
  * Added Request#render() callback function. Closes #258
  * Added "max upload size" setting
  * Added "magic" variables to collection partials (\_\_index\_\_, \_\_length\_\_, \_\_isFirst\_\_, \_\_isLast\_\_). Closes #254
  * 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.)
  * 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)
  * Changed; session cookie is now httpOnly
  * Changed; Request is no longer global
  * Changed; Event is no longer global
  * Changed; "sys" module is no longer global
  * Changed; moved Request#download to Static plugin where it belongs
  * Changed; Request instance created before body parsing. Closes #262
  * Changed; Pre-caching views in memory when "cache view contents" is enabled. Closes #253
  * Changed; Pre-caching view partials in memory when "cache view partials" is enabled
  * Updated support to node --version 0.1.90
  * Updated dependencies
  * Removed set("session cookie") in favour of use(Session, { cookie: { ... }})
  * Removed utils.mixin(); use Object#mergeDeep()

0.8.0 / 2010-03-19
==================

  * Added coffeescript example app. Closes #242
  * Changed; cache api now async friendly. Closes #240
  * Removed deprecated 'express/static' support. Use 'express/plugins/static'

0.7.6 / 2010-03-19
==================

  * Added Request#isXHR. Closes #229
  * Added `make install` (for the executable)
  * Added `express` executable for setting up simple app templates
  * Added "GET /public/*" to Static plugin, defaulting to <root>/public
  * Added Static plugin
  * Fixed; Request#render() only calls cache.get() once
  * Fixed; Namespacing View caches with "view:"
  * Fixed; Namespacing Static caches with "static:"
  * Fixed; Both example apps now use the Static plugin
  * Fixed set("views"). Closes #239
  * Fixed missing space for combined log format
  * Deprecated Request#sendfile() and 'express/static'
  * Removed Server#running

0.7.5 / 2010-03-16
==================

  * Added Request#flash() support without args, now returns all flashes
  * Updated ext submodule

0.7.4 / 2010-03-16
==================

  * Fixed session reaper
  * Changed; class.js replacing js-oo Class implementation (quite a bit faster, no browser cruft)

0.7.3 / 2010-03-16
==================

  * Added package.json
  * Fixed requiring of haml / sass due to kiwi removal

0.7.2 / 2010-03-16
==================

  * Fixed GIT submodules (HAH!)

0.7.1 / 2010-03-16
==================

  * Changed; Express now using submodules again until a PM is adopted
  * Changed; chat example using millisecond conversions from ext

0.7.0 / 2010-03-15
==================

  * Added Request#pass() support (finds the next matching route, or the given path)
  * Added Logger plugin (default "common" format replaces CommonLogger)
  * Removed Profiler plugin
  * Removed CommonLogger plugin

0.6.0 / 2010-03-11
==================

  * Added seed.yml for kiwi package management support
  * Added HTTP client query string support when method is GET. Closes #205

  * Added support for arbitrary view engines.
    For example "foo.engine.html" will now require('engine'),
    the exports from this module are cached after the first require().

  * Added async plugin support

  * Removed usage of RESTful route funcs as http client
    get() etc, use http.get() and friends

  * Removed custom exceptions

0.5.0 / 2010-03-10
==================

  * Added ext dependency (library of js extensions)
  * Removed extname() / basename() utils. Use path module
  * Removed toArray() util. Use arguments.values
  * Removed escapeRegexp() util. Use RegExp.escape()
  * Removed process.mixin() dependency. Use utils.mixin()
  * Removed Collection
  * Removed ElementCollection
  * Shameless self promotion of ebook "Advanced JavaScript" (http://dev-mag.com)  ;)

0.4.0 / 2010-02-11
==================

  * Added flash() example to sample upload app
  * Added high level restful http client module (express/http)
  * Changed; RESTful route functions double as HTTP clients. Closes #69
  * Changed; throwing error when routes are added at runtime
  * Changed; defaulting render() context to the current Request. Closes #197
  * Updated haml submodule

0.3.0 / 2010-02-11
==================

  * Updated haml / sass submodules. Closes #200
  * Added flash message support. Closes #64
  * Added accepts() now allows multiple args. fixes #117
  * Added support for plugins to halt. Closes #189
  * Added alternate layout support. Closes #119
  * Removed Route#run(). Closes #188
  * Fixed broken specs due to use(Cookie) missing

0.2.1 / 2010-02-05
==================

  * Added "plot" format option for Profiler (for gnuplot processing)
  * Added request number to Profiler plugin
  * Fixed binary encoding for multipart file uploads, was previously defaulting to UTF8
  * Fixed issue with routes not firing when not files are present. Closes #184
  * Fixed process.Promise -> events.Promise

0.2.0 / 2010-02-03
==================

  * Added parseParam() support for name[] etc. (allows for file inputs with "multiple" attr) Closes #180
  * Added Both Cache and Session option "reapInterval" may be "reapEvery". Closes #174
  * Added expiration support to cache api with reaper. Closes #133
  * Added cache Store.Memory#reap()
  * Added Cache; cache api now uses first class Cache instances
  * Added abstract session Store. Closes #172
  * Changed; cache Memory.Store#get() utilizing Collection
  * Renamed MemoryStore -> Store.Memory
  * Fixed use() of the same plugin several time will always use latest options. Closes #176

0.1.0 / 2010-02-03
==================

  * Changed; Hooks (before / after) pass request as arg as well as evaluated in their context
  * Updated node support to 0.1.27 Closes #169
  * Updated dirname(__filename) -> __dirname
  * Updated libxmljs support to v0.2.0
  * Added session support with memory store / reaping
  * Added quick uid() helper
  * Added multi-part upload support
  * Added Sass.js support / submodule
  * Added production env caching view contents and static files
  * Added static file caching. Closes #136
  * Added cache plugin with memory stores
  * Added support to StaticFile so that it works with non-textual files.
  * Removed dirname() helper
  * Removed several globals (now their modules must be required)

0.0.2 / 2010-01-10
==================

  * Added view benchmarks; currently haml vs ejs
  * Added Request#attachment() specs. Closes #116
  * Added use of node's parseQuery() util. Closes #123
  * Added `make init` for submodules
  * Updated Haml
  * Updated sample chat app to show messages on load
  * Updated libxmljs parseString -> parseHtmlString
  * Fixed `make init` to work with older versions of git
  * Fixed specs can now run independent specs for those who can't build deps. Closes #127
  * Fixed issues introduced by the node url module changes. Closes 126.
  * Fixed two assertions failing due to Collection#keys() returning strings
  * Fixed faulty Collection#toArray() spec due to keys() returning strings
  * Fixed `make test` now builds libxmljs.node before testing

0.0.1 / 2010-01-03
==================

  * Initial release


================================================
FILE: LICENSE
================================================
(The MIT License)

Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2013-2014 Roman Shtylman <shtylman+expressjs@gmail.com>
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: Readme.md
================================================
[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](https://expressjs.com/)

**Fast, unopinionated, minimalist web framework for [Node.js](https://nodejs.org).**

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

## Table of contents

- [Table of contents](#table-of-contents)
- [Installation](#installation)
- [Features](#features)
- [Docs \& Community](#docs--community)
- [Quick Start](#quick-start)
- [Philosophy](#philosophy)
- [Examples](#examples)
- [Contributing](#contributing)
  - [Security Issues](#security-issues)
  - [Running Tests](#running-tests)
- [Current project team members](#current-project-team-members)
  - [TC (Technical Committee)](#tc-technical-committee)
    - [TC emeriti members](#tc-emeriti-members)
  - [Triagers](#triagers)
    - [Emeritus Triagers](#emeritus-triagers)
- [License](#license)


[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-downloads-url]
[![Linux Build][github-actions-ci-image]][github-actions-ci-url]
[![Test Coverage][coveralls-image]][coveralls-url]
[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer]


```js
import express from 'express'

const app = express()

app.get('/', (req, res) => {
  res.send('Hello World')
})

app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000')
})
```

## Installation

This is a [Node.js](https://nodejs.org/en/) module available through the
[npm registry](https://www.npmjs.com/).

Before installing, [download and install Node.js](https://nodejs.org/en/download/).
Node.js 18 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
npm install express
```

Follow [our installing guide](https://expressjs.com/en/starter/installing.html)
for more information.

## Features

  * Robust routing
  * Focus on high performance
  * Super-high test coverage
  * HTTP helpers (redirection, caching, etc)
  * View system supporting 14+ template engines
  * Content negotiation
  * Executable for generating applications quickly

## Docs & Community

  * [Website and Documentation](https://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
  * [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules
  * [Github Discussions](https://github.com/expressjs/discussions) for discussion on the development and usage of Express

**PROTIP** Be sure to read the [migration guide to v5](https://expressjs.com/en/guide/migrating-5)

## 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
npm install -g express-generator@4
```

  Create the app:

```bash
express /tmp/foo && cd /tmp/foo
```

  Install dependencies:

```bash
npm install
```

  Start the server:

```bash
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, websites, hybrids, or public
  HTTP APIs.

  Express does not force you to use any specific ORM or template engine. With support for over
  14 template engines via [@ladjs/consolidate](https://github.com/ladjs/consolidate),
  you can quickly craft your perfect framework.

## Examples

  To view the examples, clone the Express repository:

```bash
git clone https://github.com/expressjs/express.git --depth 1 && cd express
```

  Then install the dependencies:

```bash
npm install
```

  Then run whichever example you want:

```bash
node examples/content-negotiation
```

## Contributing

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] for more technical details on contributing.

### Security Issues

If you discover a security vulnerability in Express, please see [Security Policies and Procedures](https://github.com/expressjs/express/security/policy).

### Running Tests

To run the test suite, first install the dependencies:

```bash
npm install
```

Then run `npm test`:

```bash
npm test
```

## Current project team members

For information about the governance of the express.js project, see [GOVERNANCE.md](https://github.com/expressjs/discussions/blob/HEAD/docs/GOVERNANCE.md).

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**
* [bjohansebas](https://github.com/bjohansebas) - **Sebastian Beltran**
* [carpasse](https://github.com/carpasse) - **Carlos Serrano**
* [CBID2](https://github.com/CBID2) - **Christine Belzie**
* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
* [IamLizu](https://github.com/IamLizu) - **S M Mahmudul Hasan** (he/him)
* [Phillip9587](https://github.com/Phillip9587) - **Phillip Barta**
* [efekrskl](https://github.com/efekrskl) - **Efe Karasakal**
* [rxmarbles](https://github.com/rxmarbles) - **Rick Markins** (he/him)
* [krzysdz](https://github.com/krzysdz)
* [GroophyLifefor](https://github.com/GroophyLifefor) - **Murat Kirazkaya**

<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**
  * [enyoghasim](https://github.com/enyoghasim) - **David Enyoghasim**
  * [0ss](https://github.com/0ss) - **Salah**
  * [import-brain](https://github.com/import-brain) - **Eric Cheng** (he/him)
  * [dakshkhetan](https://github.com/dakshkhetan) - **Daksh Khetan** (he/him)
  * [lucasraziel](https://github.com/lucasraziel) - **Lucas Soares Do Rego**
  * [mertcanaltin](https://github.com/mertcanaltin) - **Mert Can Altin**
  * [dpopp07](https://github.com/dpopp07) - **Dustin Popp**
  * [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**
  * [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**

</details>


## License

  [MIT](LICENSE)

[coveralls-image]: https://img.shields.io/coverallsCoverage/github/expressjs/express?branch=master
[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/express/ci.yml?branch=master&label=ci
[github-actions-ci-url]: https://github.com/expressjs/express/actions/workflows/ci.yml
[npm-downloads-image]: https://img.shields.io/npm/dm/express
[npm-downloads-url]: https://npmcharts.com/compare/express?minimal=true
[npm-url]: https://npmjs.org/package/express
[npm-version-image]: https://img.shields.io/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/.github/blob/HEAD/CODE_OF_CONDUCT.md
[Contributing Guide]: https://github.com/expressjs/.github/blob/HEAD/CONTRIBUTING.md


================================================
FILE: examples/README.md
================================================
# 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


================================================
FILE: examples/auth/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var express = require('../..');
var hash = require('pbkdf2-password')()
var path = require('node:path');
var session = require('express-session');

var app = module.exports = express();

// config

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

// middleware

app.use(express.urlencoded())
app.use(session({
  resave: false, // don't save session if unmodified
  saveUninitialized: false, // don't create session until something stored
  secret: 'shhhh, very secret'
}));

// Session-persisted message middleware

app.use(function(req, res, next){
  var err = req.session.error;
  var msg = req.session.success;
  delete req.session.error;
  delete req.session.success;
  res.locals.message = '';
  if (err) res.locals.message = '<p class="msg error">' + err + '</p>';
  if (msg) res.locals.message = '<p class="msg success">' + msg + '</p>';
  next();
});

// placeholder database

var users = {
  tj: { name: 'tj' }
};

// when you create a user, generate a salt
// and hash the password ('foobar' is the pass here)

hash({ password: 'foobar' }, function (err, pass, salt, hash) {
  if (err) throw err;
  // store the salt & hash in the "db"
  users.tj.salt = salt;
  users.tj.hash = hash;
});


// Authenticate using our plain-object database of doom!

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(null, null)
  // apply the same algorithm to the POSTed password, applying
  // the hash against the pass / salt, if there is a match we
  // found the user
  hash({ password: pass, salt: user.salt }, function (err, pass, salt, hash) {
    if (err) return fn(err);
    if (hash === user.hash) return fn(null, user)
    fn(null, null)
  });
}

function restrict(req, res, next) {
  if (req.session.user) {
    next();
  } else {
    req.session.error = 'Access denied!';
    res.redirect('/login');
  }
}

app.get('/', function(req, res){
  res.redirect('/login');
});

app.get('/restricted', restrict, function(req, res){
  res.send('Wahoo! restricted area, click to <a href="/logout">logout</a>');
});

app.get('/logout', function(req, res){
  // destroy the user's session to log them out
  // will be re-created next request
  req.session.destroy(function(){
    res.redirect('/');
  });
});

app.get('/login', function(req, res){
  res.render('login');
});

app.post('/login', function (req, res, next) {
  if (!req.body) return res.sendStatus(400)
  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
      req.session.regenerate(function(){
        // Store the user's primary key
        // in the session store to be retrieved,
        // or in this case the entire user object
        req.session.user = user;
        req.session.success = 'Authenticated as ' + user.name
          + ' click to <a href="/logout">logout</a>. '
          + ' You may now access <a href="/restricted">/restricted</a>.';
        res.redirect(req.get('Referrer') || '/');
      });
    } else {
      req.session.error = 'Authentication failed, please check your '
        + ' username and password.'
        + ' (use "tj" and "foobar")';
      res.redirect('/login');
    }
  });
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/auth/views/foot.ejs
================================================
  </body>
</html>


================================================
FILE: examples/auth/views/head.ejs
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title><%= title %></title>
    <style>
      body {
        padding: 50px;
        font: 13px Helvetica, Arial, sans-serif;
      }
      .error {
          color: red;
      }
      .success {
          color: green;
      }
    </style>
  </head>
  <body>


================================================
FILE: examples/auth/views/login.ejs
================================================

<%- 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 for="username">Username:</label>
    <input type="text" name="username" id="username">
  </p>
  <p>
    <label for="password">Password:</label>
    <input type="text" name="password" id="password">
  </p>
  <p>
    <input type="submit" value="Login">
  </p>
</form>

<%- include('foot') -%>


================================================
FILE: examples/content-negotiation/db.js
================================================
'use strict'

var users = [];

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

module.exports = users;


================================================
FILE: examples/content-negotiation/index.js
================================================
'use strict'

var express = require('../../');
var app = module.exports = express();
var users = require('./db');

// so either you can deal with different types of formatting
// for expected response in index.js
app.get('/', function(req, res){
  res.format({
    html: function(){
      res.send('<ul>' + users.map(function(user){
        return '<li>' + user.name + '</li>';
      }).join('') + '</ul>');
    },

    text: function(){
      res.send(users.map(function(user){
        return ' - ' + user.name + '\n';
      }).join(''));
    },

    json: function(){
      res.json(users);
    }
  });
});

// or you could write a tiny middleware like
// this to add a layer of abstraction
// and make things a bit more declarative:

function format(path) {
  var obj = require(path);
  return function(req, res){
    res.format(obj);
  };
}

app.get('/users', format('./users'));

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/content-negotiation/users.js
================================================
'use strict'

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

exports.html = function(req, res){
  res.send('<ul>' + users.map(function(user){
    return '<li>' + user.name + '</li>';
  }).join('') + '</ul>');
};

exports.text = function(req, res){
  res.send(users.map(function(user){
    return ' - ' + user.name + '\n';
  }).join(''));
};

exports.json = function(req, res){
  res.json(users);
};


================================================
FILE: examples/cookie-sessions/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var cookieSession = require('cookie-session');
var express = require('../../');

var app = module.exports = express();

// add req.session cookie support
app.use(cookieSession({ secret: 'manny is cool' }));

// do something with the session
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) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/cookies/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var express = require('../../');
var app = module.exports = express();
var logger = require('morgan');
var cookieParser = require('cookie-parser');

// custom log format
if (process.env.NODE_ENV !== 'test') app.use(logger(':method :url'))

// parses request cookies, populating
// req.cookies and req.signedCookies
// when the secret is passed, used
// for signing the cookies.
app.use(cookieParser('my secret here'));

// parses x-www-form-urlencoded
app.use(express.urlencoded())

app.get('/', function(req, res){
  if (req.cookies.remember) {
    res.send('Remembered :). Click to <a href="/forget">forget</a>!.');
  } else {
    res.send('<form method="post"><p>Check to <label>'
      + '<input type="checkbox" name="remember"/> remember me</label> '
      + '<input type="submit" value="Submit"/>.</p></form>');
  }
});

app.get('/forget', function(req, res){
  res.clearCookie('remember');
  res.redirect(req.get('Referrer') || '/');
});

app.post('/', function(req, res){
  var minute = 60000;

  if (req.body && req.body.remember) {
    res.cookie('remember', 1, { maxAge: minute })
  }

  res.redirect(req.get('Referrer') || '/');
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/downloads/files/CCTV大赛上海分赛区.txt
================================================
Only for test.
The file name is faked.

================================================
FILE: examples/downloads/files/amazing.txt
================================================
what an amazing download

================================================
FILE: examples/downloads/files/notes/groceries.txt
================================================
* milk
* eggs
* bread


================================================
FILE: examples/downloads/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var express = require('../../');
var path = require('node: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/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) {
  res.download(req.params.file.join('/'), { root: FILES_DIR }, function (err) {
    if (!err) return; // file sent
    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!');
  });
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/ejs/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

var app = module.exports = express();

// Register ejs as .html. If we did
// not call this, we would need to
// name our views foo.ejs instead
// of foo.html. The __express method
// is simply a function that engines
// use to hook into the Express view
// system by default, so if we want
// to change "foo.ejs" to "foo.html"
// we simply pass _any_ function, in this
// case `ejs.__express`.

app.engine('.html', require('ejs').__express);

// Optional since express defaults to CWD/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()
// ex: res.render('users.html').
app.set('view engine', 'html');

// Placeholder users
var users = [
  { name: 'tobi', email: 'tobi@learnboost.com' },
  { name: 'loki', email: 'loki@learnboost.com' },
  { name: 'jane', email: 'jane@learnboost.com' }
];

app.get('/', function(req, res){
  res.render('users', {
    users: users,
    title: "EJS example",
    header: "Some users"
  });
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/ejs/public/stylesheets/style.css
================================================
body {
  padding: 50px 80px;
  font: 14px "Helvetica Neue", "Lucida Grande", Arial, sans-serif;
}


================================================
FILE: examples/ejs/views/footer.html
================================================
</body>
</html>


================================================
FILE: examples/ejs/views/header.html
================================================
<!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="/stylesheets/style.css">
</head>
<body>


================================================
FILE: examples/ejs/views/users.html
================================================
<%- include('header.html') -%>

<h1>Users</h1>
<ul id="users">
  <% users.forEach(function(user){ %>
    <li><%= user.name %> &lt;<%= user.email %>&gt;</li>
  <% }) %>
</ul>

<%- include('footer.html') -%>


================================================
FILE: examples/error/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var express = require('../../');
var logger = require('morgan');
var app = module.exports = express();
var test = app.get('env') === 'test'

if (!test) app.use(logger('dev'));

// error handling middleware have an arity of 4
// instead of the typical (req, res, next),
// otherwise they behave exactly like regular
// middleware, you may have several of them,
// in different orders etc.

function error(err, req, res, next) {
  // log it
  if (!test) console.error(err.stack);

  // respond with 500 "Internal Server Error".
  res.status(500);
  res.send('Internal Server Error');
}

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!'));
  });
});

// the error handler is placed after routes
// if it were above it would not receive errors
// from app.get() etc
app.use(error);

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/error-pages/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

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

// our custom "verbose errors" setting
// which we can use in the templates
// via settings['verbose errors']
app.enable('verbose errors');

// disable them in production
// use $ NODE_ENV=production node examples/error-pages
if (app.settings.env === 'production') app.disable('verbose errors')

silent || app.use(logger('dev'));

// Routes

app.get('/', function(req, res){
  res.render('index.ejs');
});

app.get('/404', function(req, res, next){
  // trigger a 404 since no other middleware
  // will match /404 after this one, and we're not
  // responding here
  next();
});

app.get('/403', function(req, res, next){
  // trigger a 403 error
  var err = new Error('not allowed!');
  err.status = 403;
  next(err);
});

app.get('/500', function(req, res, next){
  // trigger a generic (500) error
  next(new Error('keyboard cat!'));
});

// Error handlers

// Since this is the last non-error-handling
// middleware use()d, we assume 404, as nothing else
// responded.

// $ curl http://localhost:3000/notfound
// $ curl http://localhost:3000/notfound -H "Accept: application/json"
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"

app.use(function(req, res, next){
  res.status(404);

  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
// as regular middleware, however they require an
// arity of 4, aka the signature (err, req, res, next).
// when connect has an error, it will invoke ONLY error-handling
// middleware.

// If we were to next() here any remaining non-error-handling
// middleware would then be executed, or if we next(err) to
// continue passing the error, only error-handling middleware
// would remain being executed, however here
// we simply respond with an error page.

app.use(function(err, req, res, next){
  // we may use properties of the error object
  // here and next(err) appropriately, or if
  // we possibly recovered from the error, simply next().
  res.status(err.status || 500);
  res.render('500', { error: err });
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/error-pages/views/404.ejs
================================================
<%- include('error_header') -%>
<h2>Cannot find <%= url %></h2>
<%- include('footer') -%>


================================================
FILE: examples/error-pages/views/500.ejs
================================================
<%- include('error_header') -%>
<h2>Error: <%= error.message %></h2>
<% if (settings['verbose errors']) { %>
  <pre><%= error.stack %></pre>
<% } else { %>
  <p>An error occurred!</p>
<% } %>
<%- include('footer') -%>


================================================
FILE: examples/error-pages/views/error_header.ejs
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Error</title>
</head>

<body>
<h1>An error occurred!</h1>


================================================
FILE: examples/error-pages/views/footer.ejs
================================================
</body>
</html>


================================================
FILE: examples/error-pages/views/index.ejs
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Custom Pages Example</title>
</head>

<body>
<h1>My Site</h1>
<h2>Pages Example</h2>

<ul>
<li>visit <a href="/500">500</a></li>
<li>visit <a href="/404">404</a></li>
<li>visit <a href="/403">403</a></li>
</ul>

</body>
</html>


================================================
FILE: examples/hello-world/index.js
================================================
'use strict'

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

var app = module.exports = express()

app.get('/', function(req, res){
  res.send('Hello World');
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/markdown/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

var app = module.exports = express();

// register .md as an engine in express view system

app.engine('md', function(path, options, fn){
  fs.readFile(path, 'utf8', function(err, str){
    if (err) return fn(err);
    var html = marked.parse(str).replace(/\{([^}]+)\}/g, function(_, name){
      return escapeHtml(options[name] || '');
    });
    fn(null, html);
  });
});

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

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

app.get('/', function(req, res){
  res.render('index', { title: 'Markdown Example' });
});

app.get('/fail', function(req, res){
  res.render('missing', { title: 'Markdown Example' });
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/markdown/views/index.md
================================================

# {title}

Just an example view rendered with _markdown_.

================================================
FILE: examples/multi-router/controllers/api_v1.js
================================================
'use strict'

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

var apiv1 = express.Router();

apiv1.get('/', function(req, res) {
  res.send('Hello from APIv1 root route.');
});

apiv1.get('/users', function(req, res) {
  res.send('List of APIv1 users.');
});

module.exports = apiv1;


================================================
FILE: examples/multi-router/controllers/api_v2.js
================================================
'use strict'

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

var apiv2 = express.Router();

apiv2.get('/', function(req, res) {
  res.send('Hello from APIv2 root route.');
});

apiv2.get('/users', function(req, res) {
  res.send('List of APIv2 users.');
});

module.exports = apiv2;


================================================
FILE: examples/multi-router/index.js
================================================
'use strict'

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

var app = module.exports = express();

app.use('/api/v1', require('./controllers/api_v1'));
app.use('/api/v2', require('./controllers/api_v2'));

app.get('/', function(req, res) {
  res.send('Hello from root route.')
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/mvc/controllers/main/index.js
================================================
'use strict'

exports.index = function(req, res){
  res.redirect('/users');
};


================================================
FILE: examples/mvc/controllers/pet/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

exports.engine = 'ejs';

exports.before = function(req, res, next){
  var pet = db.pets[req.params.pet_id];
  if (!pet) return next('route');
  req.pet = pet;
  next();
};

exports.show = function(req, res, next){
  res.render('show', { pet: req.pet });
};

exports.edit = function(req, res, next){
  res.render('edit', { pet: req.pet });
};

exports.update = function(req, res, next){
  var body = req.body;
  req.pet.name = body.pet.name;
  res.message('Information updated!');
  res.redirect('/pet/' + req.pet.id);
};


================================================
FILE: examples/mvc/controllers/pet/views/edit.ejs
================================================
<!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>

<body>
<h1><%= pet.name %></h1>
<form action="/pet/<%= pet.id %>?_method=put" method="post">
  <label>Name: <input type="text" name="pet[name]" value="<%= pet.name %>"></label>
  <input type="submit" value="Update">
</form>
</body>
</html>


================================================
FILE: examples/mvc/controllers/pet/views/show.ejs
================================================
<!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>

<body>
<h1><%= pet.name %> <a href="/pet/<%= pet.id %>/edit">edit</a></h1>

<p>You are viewing <%= pet.name %></p>
</body>
</html>


================================================
FILE: examples/mvc/controllers/user/index.js
================================================
'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();
  // pretend to query a database...
  process.nextTick(function(){
    req.user = db.users[id];
    // cant find that user
    if (!req.user) return next('route');
    // found it, move on to the routes
    next();
  });
};

exports.list = function(req, res, next){
  res.render('list', { users: db.users });
};

exports.edit = function(req, res, next){
  res.render('edit', { user: req.user });
};

exports.show = function(req, res, next){
  res.render('show', { user: req.user });
};

exports.update = function(req, res, next){
  var body = req.body;
  req.user.name = body.user.name;
  res.message('Information updated!');
  res.redirect('/user/' + req.user.id);
};


================================================
FILE: examples/mvc/controllers/user/views/edit.hbs
================================================
<!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>


================================================
FILE: examples/mvc/controllers/user/views/list.hbs
================================================
<!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>


================================================
FILE: examples/mvc/controllers/user/views/show.hbs
================================================
<!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>


================================================
FILE: examples/mvc/controllers/user-pet/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

exports.name = 'pet';
exports.prefix = '/user/:user_id';

exports.create = function(req, res, next){
  var id = req.params.user_id;
  var user = db.users[id];
  var body = req.body;
  if (!user) return next('route');
  var pet = { name: body.pet.name };
  pet.id = db.pets.push(pet) - 1;
  user.pets.push(pet);
  res.message('Added pet ' + body.pet.name);
  res.redirect('/user/' + id);
};


================================================
FILE: examples/mvc/db.js
================================================
'use strict'

// faux database

var pets = exports.pets = [];

pets.push({ name: 'Tobi', id: 0 });
pets.push({ name: 'Loki', id: 1 });
pets.push({ name: 'Jane', id: 2 });
pets.push({ name: 'Raul', id: 3 });

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 });


================================================
FILE: examples/mvc/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var express = require('../..');
var logger = require('morgan');
var path = require('node:path');
var session = require('express-session');
var methodOverride = require('method-override');

var app = module.exports = express();

// 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', path.join(__dirname, 'views'));

// define a custom res.message() method
// which stores messages in the session
app.response.message = function(msg){
  // reference `req.session` via the `this.req` reference
  var sess = this.req.session;
  // simply add the msg to an array for later
  sess.messages = sess.messages || [];
  sess.messages.push(msg);
  return this;
};

// log
if (!module.parent) app.use(logger('dev'));

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

// session support
app.use(session({
  resave: false, // don't save session if unmodified
  saveUninitialized: false, // don't create session until something stored
  secret: 'some secret here'
}));

// parse request bodies (req.body)
app.use(express.urlencoded({ extended: true }))

// allow overriding methods in query (?_method=put)
app.use(methodOverride('_method'));

// expose the "messages" local variable when views are rendered
app.use(function(req, res, next){
  var msgs = req.session.messages || [];

  // expose "messages" local variable
  res.locals.messages = msgs;

  // expose "hasMessages"
  res.locals.hasMessages = !! msgs.length;

  /* This is equivalent:
   res.locals({
     messages: msgs,
     hasMessages: !! msgs.length
   });
  */

  next();
  // empty or "flush" the messages so they
  // don't build up
  req.session.messages = [];
});

// load controllers
require('./lib/boot')(app, { verbose: !module.parent });

app.use(function(err, req, res, next){
  // log it
  if (!module.parent) console.error(err.stack);

  // error page
  res.status(500).render('5xx');
});

// assume 404 since no middleware responded
app.use(function(req, res, next){
  res.status(404).render('404', { url: req.originalUrl });
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/mvc/lib/boot.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

module.exports = function(parent, options){
  var dir = path.join(__dirname, '..', 'controllers');
  var verbose = options.verbose;
  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(file);
    var name = obj.name || name;
    var prefix = obj.prefix || '';
    var app = express();
    var handler;
    var method;
    var url;

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

    // generate routes based
    // on the exported methods
    for (var key in obj) {
      // "reserved" exports
      if (~['name', 'prefix', 'engine', 'before'].indexOf(key)) continue;
      // route exports
      switch (key) {
        case 'show':
          method = 'get';
          url = '/' + name + '/:' + name + '_id';
          break;
        case 'list':
          method = 'get';
          url = '/' + name + 's';
          break;
        case 'edit':
          method = 'get';
          url = '/' + name + '/:' + name + '_id/edit';
          break;
        case 'update':
          method = 'put';
          url = '/' + name + '/:' + name + '_id';
          break;
        case 'create':
          method = 'post';
          url = '/' + name;
          break;
        case 'index':
          method = 'get';
          url = '/';
          break;
        default:
          /* istanbul ignore next */
          throw new Error('unrecognized route: ' + name + '.' + key);
      }

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

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

    // mount the app
    parent.use(app);
  });
};


================================================
FILE: examples/mvc/public/style.css
================================================
body {
  padding: 50px;
  font: 16px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
a {
  color: #107aff;
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
h1 a {
  font-size: 16px;
}


================================================
FILE: examples/mvc/views/404.ejs
================================================
<!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>


================================================
FILE: examples/mvc/views/5xx.ejs
================================================
<!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>


================================================
FILE: examples/online/index.js
================================================
'use strict'

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

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

/**
 * Module dependencies.
 */

var express = require('../..');
var online = require('online');
var redis = require('redis');
var db = redis.createClient();

// online

online = online(db);

// app

var app = express();

// activity tracking, in this case using
// the UA string, you would use req.user.id etc

app.use(function(req, res, next){
  // fire-and-forget
  online.add(req.headers['user-agent']);
  next();
});

/**
 * List helper.
 */

function list(ids) {
  return '<ul>' + ids.map(function(id){
    return '<li>' + id + '</li>';
  }).join('') + '</ul>';
}

/**
 * GET users online.
 */

app.get('/', function(req, res, next){
  online.last(5, function(err, ids){
    if (err) return next(err);
    res.send('<p>Users online: ' + ids.length + '</p>' + list(ids));
  });
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/params/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var createError = require('http-errors')
var express = require('../../');
var app = module.exports = express();

// Faux database

var users = [
  { name: 'tj' }
  , { name: 'tobi' }
  , { name: 'loki' }
  , { name: 'jane' }
  , { name: 'bandit' }
];

// Convert :to and :from to integers

app.param(['to', 'from'], function(req, res, next, num, name){
  req.params[name] = parseInt(num, 10);
  if( isNaN(req.params[name]) ){
    next(createError(400, 'failed to parseInt '+num));
  } else {
    next();
  }
});

// Load user by id

app.param('user', function(req, res, next, id){
  req.user = users[id]
  if (req.user) {
    next();
  } else {
    next(createError(404, 'failed to find user'));
  }
});

/**
 * GET index.
 */

app.get('/', function(req, res){
  res.send('Visit /user/0 or /users/0-2');
});

/**
 * GET :user.
 */

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) {
  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 + 1).join(', '));
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/resource/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

var app = module.exports = express();

// Ad-hoc example resource method

app.resource = function(path, obj) {
  this.get(path, obj.index);
  this.get(path + '/:a..:b{.:format}', function(req, res){
    var a = parseInt(req.params.a, 10);
    var b = parseInt(req.params.b, 10);
    var format = req.params.format;
    obj.range(req, res, a, b, format);
  });
  this.get(path + '/:id', obj.show);
  this.delete(path + '/:id', function(req, res){
    var id = parseInt(req.params.id, 10);
    obj.destroy(req, res, id);
  });
};

// Fake records

var users = [
  { name: 'tj' }
  , { name: 'ciaran' }
  , { name: 'aaron' }
  , { name: 'guillermo' }
  , { name: 'simon' }
  , { name: 'tobi' }
];

// Fake controller.

var User = {
  index: function(req, res){
    res.send(users);
  },
  show: function(req, res){
    res.send(users[req.params.id] || { error: 'Cannot find user' });
  },
  destroy: function(req, res, id){
    var destroyed = id in users;
    delete users[id];
    res.send(destroyed ? 'destroyed' : 'Cannot find user');
  },
  range: function(req, res, a, b, format){
    var range = users.slice(a, b + 1);
    switch (format) {
      case 'json':
        res.send(range);
        break;
      case 'html':
      default:
        var html = '<ul>' + range.map(function(user){
          return '<li>' + user.name + '</li>';
        }).join('\n') + '</ul>';
        res.send(html);
        break;
    }
  }
};

// curl http://localhost:3000/users     -- responds with all users
// curl http://localhost:3000/users/1   -- responds with user 1
// curl http://localhost:3000/users/4   -- responds with error
// curl http://localhost:3000/users/1..3 -- responds with several users
// curl -X DELETE http://localhost:3000/users/1  -- deletes the user

app.resource('/users', User);

app.get('/', function(req, res){
  res.send([
    '<h1>Examples:</h1> <ul>'
    , '<li>GET /users</li>'
    , '<li>GET /users/1</li>'
    , '<li>GET /users/3</li>'
    , '<li>GET /users/1..3</li>'
    , '<li>GET /users/1..3.json</li>'
    , '<li>DELETE /users/4</li>'
    , '</ul>'
  ].join('\n'));
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/route-map/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var escapeHtml = require('escape-html')
var express = require('../../lib/express');

var verbose = process.env.NODE_ENV !== 'test'

var app = module.exports = express();

app.map = function(a, route){
  route = route || '';
  for (var key in a) {
    switch (typeof a[key]) {
      // { '/path': { ... }}
      case 'object':
        app.map(a[key], route + key);
        break;
      // get: function(){ ... }
      case 'function':
        if (verbose) console.log('%s %s', key, route);
        app[key](route, a[key]);
        break;
    }
  }
};

var users = {
  list: function(req, res){
    res.send('user list');
  },

  get: function(req, res){
    res.send('user ' +  escapeHtml(req.params.uid))
  },

  delete: function(req, res){
    res.send('delete users');
  }
};

var pets = {
  list: function(req, res){
    res.send('user ' + escapeHtml(req.params.uid) + '\'s pets')
  },

  delete: function(req, res){
    res.send('delete ' + escapeHtml(req.params.uid) + '\'s pet ' + escapeHtml(req.params.pid))
  }
};

app.map({
  '/users': {
    get: users.list,
    delete: users.delete,
    '/:uid': {
      get: users.get,
      '/pets': {
        get: pets.list,
        '/:pid': {
          delete: pets.delete
        }
      }
    }
  }
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/route-middleware/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

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

var app = express();

// Example requests:
//     curl http://localhost:3000/user/0
//     curl http://localhost:3000/user/0/edit
//     curl http://localhost:3000/user/1
//     curl http://localhost:3000/user/1/edit (unauthorized since this is not you)
//     curl -X DELETE http://localhost:3000/user/0 (unauthorized since you are not an admin)

// Placeholder users
var users = [
  { 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' }
];

function loadUser(req, res, next) {
  // You would fetch your user from the db
  var user = users[req.params.id];
  if (user) {
    req.user = user;
    next();
  } else {
    next(new Error('Failed to load user ' + req.params.id));
  }
}

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) {
    next();
  } else {
    // You may want to implement specific exceptions
    // such as UnauthorizedError or similar so that you
    // can handle these can be special-cased in an error handler
    // (view ./examples/pages for this)
    next(new Error('Unauthorized'));
  }
}

function andRestrictTo(role) {
  return function(req, res, next) {
    if (req.authenticatedUser.role === role) {
      next();
    } else {
      next(new Error('Unauthorized'));
    }
  }
}

// Middleware for faux authentication
// you would of course implement something real,
// but this illustrates how an authenticated user
// may interact with middleware

app.use(function(req, res, next){
  req.authenticatedUser = users[0];
  next();
});

app.get('/', function(req, res){
  res.redirect('/user/0');
});

app.get('/user/:id', loadUser, function(req, res){
  res.send('Viewing user ' + req.user.name);
});

app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
  res.send('Editing user ' + req.user.name);
});

app.delete('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
  res.send('Deleted user ' + req.user.name);
});

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/route-separation/index.js
================================================
'use strict'

/**
 * Module dependencies.
 */

var express = require('../..');
var path = require('node:path');
var app = express();
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var methodOverride = require('method-override');
var site = require('./site');
var post = require('./post');
var user = require('./user');

module.exports = app;

// Config

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

/* istanbul ignore next */
if (!module.parent) {
  app.use(logger('dev'));
}

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

// General

app.get('/', site.index);

// User

app.get('/users', user.list);
app.all('/user/:id{/:op}', user.load);
app.get('/user/:id', user.view);
app.get('/user/:id/view', user.view);
app.get('/user/:id/edit', user.edit);
app.put('/user/:id/edit', user.update);

// Posts

app.get('/posts', post.list);

/* istanbul ignore next */
if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}


================================================
FILE: examples/route-separation/post.js
================================================
'use strict'

// Fake posts database

var posts = [
  { title: 'Foo', body: 'some foo bar' },
  { title: 'Foo bar', body: 'more foo bar' },
  { title: 'Foo bar baz', body: 'more foo bar baz' }
];

exports.list = function(req, res){
  res.render('posts', { title: 'Posts', posts: posts });
};


================================================
FILE: examples/route-separation/public/style.css
================================================
body {
  padding: 50px;
  font: 14px "Helvetica Neue", Arial, sans-serif;
}
a {
  color: #00AEFF;
  text-decoration: none;
}
a.edit {
  color: #000;
  opacity: .3;
}
a.edit::before {
  content: ' [';
}
a.edit::after {
  content: ']';
}
dt {
  font-weight: bold;
}
dd {
  margin: 15px;
}

================================================
FILE: examples/route-separation/site.js
================================================
'use strict'

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


================================================
FILE: examples/route-separation/user.js
================================================
'use strict'

// Fake user database

var users = [
  { name: 'TJ', email: 'tj@vision-media.ca' },
  { name: 'Tobi', email: 'tobi@vision-media.ca' }
];

exports.list = function(req, res){
  res.render('users', { title: 'Users', users: users });
};

exports.load = function(req, res, next){
  var id = req.params.id;
  req.user = users[id];
  if (req.user) {
    next();
  } else {
    var err = new Error('cannot find user ' + id);
    err.status = 404;
    next(err);
  }
};

exports.view = function(req, res){
  res.render('users/view', {
    title: 'Viewing user ' + req.user.name,
    user: req.user
  });
};

exports.edit = function(req, res){
  res.render('users/edit', {
    title: 'Editing user ' + req.user.name,
    user: req.user
  });
};

exports.update = function(req, res){
  // Normally you would handle all kinds of
  // validation and save back to the db
  var user = req.body.user;
  req.user.name = user.name;
  req.user.email = user.email;
  res.redirect(req.get('Referrer') || '/');
};


================================================
FILE: examples/route-separation/views/footer.ejs
================================================
Download .txt
gitextract_l4z7lniq/

├── .editorconfig
├── .eslintignore
├── .eslintrc.yml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── ci.yml
│       ├── codeql.yml
│       ├── legacy.yml
│       └── scorecard.yml
├── .gitignore
├── .npmrc
├── History.md
├── LICENSE
├── Readme.md
├── examples/
│   ├── README.md
│   ├── auth/
│   │   ├── index.js
│   │   └── views/
│   │       ├── foot.ejs
│   │       ├── head.ejs
│   │       └── login.ejs
│   ├── content-negotiation/
│   │   ├── db.js
│   │   ├── index.js
│   │   └── users.js
│   ├── cookie-sessions/
│   │   └── index.js
│   ├── cookies/
│   │   └── index.js
│   ├── downloads/
│   │   ├── files/
│   │   │   ├── CCTV大赛上海分赛区.txt
│   │   │   ├── amazing.txt
│   │   │   └── notes/
│   │   │       └── groceries.txt
│   │   └── index.js
│   ├── ejs/
│   │   ├── index.js
│   │   ├── public/
│   │   │   └── stylesheets/
│   │   │       └── style.css
│   │   └── views/
│   │       ├── footer.html
│   │       ├── header.html
│   │       └── users.html
│   ├── error/
│   │   └── index.js
│   ├── error-pages/
│   │   ├── index.js
│   │   └── views/
│   │       ├── 404.ejs
│   │       ├── 500.ejs
│   │       ├── error_header.ejs
│   │       ├── footer.ejs
│   │       └── index.ejs
│   ├── hello-world/
│   │   └── index.js
│   ├── markdown/
│   │   ├── index.js
│   │   └── views/
│   │       └── index.md
│   ├── multi-router/
│   │   ├── controllers/
│   │   │   ├── api_v1.js
│   │   │   └── api_v2.js
│   │   └── index.js
│   ├── mvc/
│   │   ├── controllers/
│   │   │   ├── main/
│   │   │   │   └── index.js
│   │   │   ├── pet/
│   │   │   │   ├── index.js
│   │   │   │   └── views/
│   │   │   │       ├── edit.ejs
│   │   │   │       └── show.ejs
│   │   │   ├── user/
│   │   │   │   ├── index.js
│   │   │   │   └── views/
│   │   │   │       ├── edit.hbs
│   │   │   │       ├── list.hbs
│   │   │   │       └── show.hbs
│   │   │   └── user-pet/
│   │   │       └── index.js
│   │   ├── db.js
│   │   ├── index.js
│   │   ├── lib/
│   │   │   └── boot.js
│   │   ├── public/
│   │   │   └── style.css
│   │   └── views/
│   │       ├── 404.ejs
│   │       └── 5xx.ejs
│   ├── online/
│   │   └── index.js
│   ├── params/
│   │   └── index.js
│   ├── resource/
│   │   └── index.js
│   ├── route-map/
│   │   └── index.js
│   ├── route-middleware/
│   │   └── index.js
│   ├── route-separation/
│   │   ├── index.js
│   │   ├── post.js
│   │   ├── public/
│   │   │   └── style.css
│   │   ├── site.js
│   │   ├── user.js
│   │   └── views/
│   │       ├── footer.ejs
│   │       ├── header.ejs
│   │       ├── index.ejs
│   │       ├── posts/
│   │       │   └── index.ejs
│   │       └── users/
│   │           ├── edit.ejs
│   │           ├── index.ejs
│   │           └── view.ejs
│   ├── search/
│   │   ├── index.js
│   │   └── public/
│   │       ├── client.js
│   │       └── index.html
│   ├── session/
│   │   ├── index.js
│   │   └── redis.js
│   ├── static-files/
│   │   ├── index.js
│   │   └── public/
│   │       ├── css/
│   │       │   └── style.css
│   │       ├── hello.txt
│   │       └── js/
│   │           └── app.js
│   ├── vhost/
│   │   └── index.js
│   ├── view-constructor/
│   │   ├── github-view.js
│   │   └── index.js
│   ├── view-locals/
│   │   ├── index.js
│   │   ├── user.js
│   │   └── views/
│   │       └── index.ejs
│   └── web-service/
│       └── index.js
├── index.js
├── lib/
│   ├── application.js
│   ├── express.js
│   ├── request.js
│   ├── response.js
│   ├── utils.js
│   └── view.js
├── package.json
└── test/
    ├── Route.js
    ├── Router.js
    ├── acceptance/
    │   ├── auth.js
    │   ├── content-negotiation.js
    │   ├── cookie-sessions.js
    │   ├── cookies.js
    │   ├── downloads.js
    │   ├── ejs.js
    │   ├── error-pages.js
    │   ├── error.js
    │   ├── hello-world.js
    │   ├── markdown.js
    │   ├── multi-router.js
    │   ├── mvc.js
    │   ├── params.js
    │   ├── resource.js
    │   ├── route-map.js
    │   ├── route-separation.js
    │   ├── vhost.js
    │   └── web-service.js
    ├── app.all.js
    ├── app.engine.js
    ├── app.head.js
    ├── app.js
    ├── app.listen.js
    ├── app.locals.js
    ├── app.options.js
    ├── app.param.js
    ├── app.render.js
    ├── app.request.js
    ├── app.response.js
    ├── app.route.js
    ├── app.router.js
    ├── app.routes.error.js
    ├── app.use.js
    ├── config.js
    ├── exports.js
    ├── express.json.js
    ├── express.raw.js
    ├── express.static.js
    ├── express.text.js
    ├── express.urlencoded.js
    ├── fixtures/
    │   ├── % of dogs.txt
    │   ├── .name
    │   ├── blog/
    │   │   ├── index.html
    │   │   └── post/
    │   │       └── index.tmpl
    │   ├── broken.send
    │   ├── default_layout/
    │   │   ├── name.tmpl
    │   │   └── user.tmpl
    │   ├── email.tmpl
    │   ├── empty.txt
    │   ├── local_layout/
    │   │   └── user.tmpl
    │   ├── name.tmpl
    │   ├── name.txt
    │   ├── nums.txt
    │   ├── pets/
    │   │   └── names.txt
    │   ├── snow ☃/
    │   │   └── .gitkeep
    │   ├── todo.html
    │   ├── todo.txt
    │   ├── user.html
    │   ├── user.tmpl
    │   └── users/
    │       ├── index.html
    │       └── tobi.txt
    ├── middleware.basic.js
    ├── regression.js
    ├── req.accepts.js
    ├── req.acceptsCharsets.js
    ├── req.acceptsEncodings.js
    ├── req.acceptsLanguages.js
    ├── req.baseUrl.js
    ├── req.fresh.js
    ├── req.get.js
    ├── req.host.js
    ├── req.hostname.js
    ├── req.ip.js
    ├── req.ips.js
    ├── req.is.js
    ├── req.path.js
    ├── req.protocol.js
    ├── req.query.js
    ├── req.range.js
    ├── req.route.js
    ├── req.secure.js
    ├── req.signedCookies.js
    ├── req.stale.js
    ├── req.subdomains.js
    ├── req.xhr.js
    ├── res.append.js
    ├── res.attachment.js
    ├── res.clearCookie.js
    ├── res.cookie.js
    ├── res.download.js
    ├── res.format.js
    ├── res.get.js
    ├── res.json.js
    ├── res.jsonp.js
    ├── res.links.js
    ├── res.locals.js
    ├── res.location.js
    ├── res.redirect.js
    ├── res.render.js
    ├── res.send.js
    ├── res.sendFile.js
    ├── res.sendStatus.js
    ├── res.set.js
    ├── res.status.js
    ├── res.type.js
    ├── res.vary.js
    ├── support/
    │   ├── env.js
    │   ├── tmpl.js
    │   └── utils.js
    └── utils.js
Download .txt
SYMBOL INDEX (116 symbols across 38 files)

FILE: examples/auth/index.js
  function authenticate (line 60) | function authenticate(name, pass, fn) {
  function restrict (line 75) | function restrict(req, res, next) {

FILE: examples/content-negotiation/index.js
  function format (line 33) | function format(path) {

FILE: examples/error/index.js
  function error (line 20) | function error(err, req, res, next) {

FILE: examples/online/index.js
  function list (line 40) | function list(ids) {

FILE: examples/route-middleware/index.js
  function loadUser (line 25) | function loadUser(req, res, next) {
  function andRestrictToSelf (line 36) | function andRestrictToSelf(req, res, next) {
  function andRestrictTo (line 50) | function andRestrictTo(role) {

FILE: examples/search/index.js
  function initializeRedis (line 29) | async function initializeRedis() {

FILE: examples/view-constructor/github-view.js
  function GithubView (line 23) | function GithubView(name, options){

FILE: examples/view-locals/index.js
  function ferrets (line 17) | function ferrets(user) {
  function count (line 48) | function count(req, res, next) {
  function users (line 56) | function users(req, res, next) {
  function count2 (line 86) | function count2(req, res, next) {
  function users2 (line 94) | function users2(req, res, next) {

FILE: examples/view-locals/user.js
  function User (line 7) | function User(name, age, species) {

FILE: examples/web-service/index.js
  function error (line 15) | function error(status, msg) {

FILE: lib/application.js
  function logerror (line 615) | function logerror(err) {
  function tryRender (line 625) | function tryRender(view, options, callback) {

FILE: lib/express.js
  function createApplication (line 36) | function createApplication() {

FILE: lib/request.js
  function defineGetter (line 521) | function defineGetter(obj, name, getter) {

FILE: lib/response.js
  function sendfile (line 921) | function sendfile(res, file, options, callback) {
  function stringify (line 1023) | function stringify (value, replacer, spaces, escape) {

FILE: lib/utils.js
  function acceptParams (line 89) | function acceptParams (str) {
  function createETagGenerator (line 249) | function createETagGenerator (options) {
  function parseExtendedQueryString (line 267) | function parseExtendedQueryString(str) {

FILE: lib/view.js
  function View (line 52) | function View(name, options) {
  function tryStat (line 197) | function tryStat(path) {

FILE: test/Router.js
  function no (line 463) | function no() {
  function fn1 (line 481) | function fn1(req, res, next) {
  function fn2 (line 486) | function fn2(req, res, next) {

FILE: test/acceptance/auth.js
  function getCookie (line 4) | function getCookie(res) {

FILE: test/acceptance/cookie-sessions.js
  function getCookies (line 34) | function getCookies(res) {

FILE: test/app.engine.js
  function render (line 8) | function render(path, options, fn) {

FILE: test/app.render.js
  function View (line 64) | function View(name, options){
  function View (line 210) | function View(name, options){
  function View (line 234) | function View(name, options){
  function View (line 264) | function View(name, options){
  function View (line 357) | function View(name, options){
  function createApp (line 386) | function createApp() {

FILE: test/app.router.js
  function handler1 (line 16) | function handler1(req, res, next) {
  function handler2 (line 21) | function handler2(req, res) {
  function fn (line 852) | function fn(req, res, next) {
  function fn (line 877) | function fn(req, res, next) {
  function fn1 (line 941) | function fn1(req, res, next) {
  function fn2 (line 945) | function fn2(req, res, next) {
  function fn3 (line 949) | function fn3(err, req, res, next) {
  function supportsRegexp (line 1210) | function supportsRegexp(source) {

FILE: test/app.use.js
  function fn1 (line 92) | function fn1(req, res, next) {
  function fn2 (line 97) | function fn2(req, res, next) {
  function fn1 (line 129) | function fn1(req, res, next) {
  function fn2 (line 134) | function fn2(req, res, next) {
  function fn1 (line 176) | function fn1(req, res, next) {
  function fn2 (line 181) | function fn2(req, res, next) {
  function fn3 (line 186) | function fn3(req, res, next) {
  function fn1 (line 204) | function fn1(req, res, next) {
  function fn2 (line 209) | function fn2(req, res, next) {
  function fn3 (line 214) | function fn3(req, res, next) {
  function fn1 (line 232) | function fn1(req, res, next) {
  function fn2 (line 237) | function fn2(req, res, next) {
  function fn3 (line 242) | function fn3(req, res, next) {
  function fn1 (line 299) | function fn1(req, res, next) {
  function fn2 (line 304) | function fn2(req, res, next) {
  function fn1 (line 367) | function fn1(req, res, next) {
  function fn2 (line 372) | function fn2(req, res, next) {
  function fn3 (line 377) | function fn3(req, res, next) {
  function fn1 (line 395) | function fn1(req, res, next) {
  function fn2 (line 400) | function fn2(req, res, next) {
  function fn3 (line 405) | function fn3(req, res, next) {
  function fn1 (line 423) | function fn1(req, res, next) {
  function fn2 (line 428) | function fn2(req, res, next) {
  function fn3 (line 433) | function fn3(req, res, next) {
  function fn1 (line 473) | function fn1(req, res, next) {
  function fn2 (line 478) | function fn2(req, res, next) {
  function fn3 (line 483) | function fn3(req, res, next) {

FILE: test/config.js
  function fn (line 107) | function fn() { return false }
  function fn1 (line 123) | function fn1() { return false }
  function fn2 (line 124) | function fn2() { return true }

FILE: test/express.json.js
  function accept (line 356) | function accept (req) {
  function accept (line 370) | function accept (req) {
  function accept (line 382) | function accept (req) {
  function createApp (line 722) | function createApp (options) {
  function parseError (line 742) | function parseError (str) {
  function shouldContainInBody (line 750) | function shouldContainInBody (str) {

FILE: test/express.raw.js
  function accept (line 243) | function accept (req) {
  function accept (line 256) | function accept (req) {
  function accept (line 268) | function accept (req) {
  function createApp (line 492) | function createApp (options) {

FILE: test/express.static.js
  function createApp (line 804) | function createApp (dir, options, fn) {

FILE: test/express.text.js
  function accept (line 258) | function accept (req) {
  function accept (line 272) | function accept (req) {
  function accept (line 284) | function accept (req) {
  function createApp (line 549) | function createApp (options) {

FILE: test/express.urlencoded.js
  function accept (line 487) | function accept (req) {
  function accept (line 501) | function accept (req) {
  function accept (line 513) | function accept (req) {
  function createManyParams (line 788) | function createManyParams (count) {
  function createApp (line 805) | function createApp (options) {
  function expectKeyCount (line 824) | function expectKeyCount (count) {

FILE: test/req.ip.js
  function getExpectedClientAddress (line 109) | function getExpectedClientAddress(server) {

FILE: test/req.query.js
  function createApp (line 94) | function createApp(setting) {

FILE: test/res.append.js
  function shouldHaveHeaderValues (line 107) | function shouldHaveHeaderValues (key, values) {

FILE: test/res.format.js
  function test (line 182) | function test(app) {

FILE: test/res.location.js
  function createRedirectServerForDomain (line 127) | function createRedirectServerForDomain (domain) {
  function testRequestedRedirect (line 141) | function testRequestedRedirect (app, inputUrl, expected, expectedHost, d...

FILE: test/res.render.js
  function createApp (line 361) | function createApp() {

FILE: test/res.sendFile.js
  function handleHeaders (line 90) | function handleHeaders (res) {
  function createApp (line 905) | function createApp(path, options, fn) {

FILE: test/support/tmpl.js
  function onReadFile (line 6) | function onReadFile(err, str) {
  function generateVariableLookup (line 25) | function generateVariableLookup(data) {

FILE: test/support/utils.js
  function shouldHaveBody (line 28) | function shouldHaveBody (buf) {
  function shouldHaveHeader (line 45) | function shouldHaveHeader (header) {
  function shouldNotHaveBody (line 57) | function shouldNotHaveBody () {
  function shouldNotHaveHeader (line 69) | function shouldNotHaveHeader(header) {
  function getMajorVersion (line 75) | function getMajorVersion(versionString) {
  function shouldSkipQuery (line 79) | function shouldSkipQuery(versionString) {
Condensed preview — 213 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (747K chars).
[
  {
    "path": ".editorconfig",
    "chars": 180,
    "preview": "# https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".eslintignore",
    "chars": 22,
    "preview": "coverage\nnode_modules\n"
  },
  {
    "path": ".eslintrc.yml",
    "chars": 415,
    "preview": "root: true\nenv:\n  es2022: true\n  node: true\nrules:\n  eol-last: error\n  eqeqeq: [error, allow-null]\n  indent: [error, 2, "
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 373,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: monthly\n\n  - pa"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 3224,
    "preview": "name: ci\n\non:\n  push:\n    branches:\n      - master\n      - develop\n      - '4.x'\n      - '5.x'\n      - '5.0'\n    paths-i"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "chars": 2647,
    "preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
  },
  {
    "path": ".github/workflows/legacy.yml",
    "chars": 2746,
    "preview": "name: legacy\n\non:\n  push:\n    branches:\n      - master\n      - develop\n      - '4.x'\n      - '5.x'\n      - '5.0'\n    pat"
  },
  {
    "path": ".github/workflows/scorecard.yml",
    "chars": 2981,
    "preview": "# This workflow uses actions that are not certified by GitHub. They are provided\n# by a third-party and are governed by "
  },
  {
    "path": ".gitignore",
    "chars": 257,
    "preview": "# npm\nnode_modules\npackage-lock.json\nnpm-shrinkwrap.json\n*.log\n*.gz\n\n# Yarn\nyarn-error.log\nyarn.lock\n\n# Coveralls\n.nyc_o"
  },
  {
    "path": ".npmrc",
    "chars": 19,
    "preview": "package-lock=false\n"
  },
  {
    "path": "History.md",
    "chars": 124518,
    "preview": "# Unreleased Changes\n\n## 🚀 Improvements\n\n* Improve HTML structure in `res.redirect()` responses when HTML format is acce"
  },
  {
    "path": "LICENSE",
    "chars": 1249,
    "preview": "(The MIT License)\n\nCopyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2013-2014 Roman Shtylman <s"
  },
  {
    "path": "Readme.md",
    "chars": 10177,
    "preview": "[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](https://expressjs.com/)\n\n**Fast, unopinionated, minima"
  },
  {
    "path": "examples/README.md",
    "chars": 1592,
    "preview": "# Express examples\n\nThis page contains list of examples using Express.\n\n- [auth](./auth) - Authentication with login and"
  },
  {
    "path": "examples/auth/index.js",
    "chars": 3570,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../..');\nvar hash = require('pbkdf2-password')()\nv"
  },
  {
    "path": "examples/auth/views/foot.ejs",
    "chars": 18,
    "preview": "  </body>\n</html>\n"
  },
  {
    "path": "examples/auth/views/head.ejs",
    "chars": 394,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width,initial"
  },
  {
    "path": "examples/auth/views/login.ejs",
    "chars": 533,
    "preview": "\n<%- include('head', { title: 'Authentication Example' }) -%>\n\n<h1>Login</h1>\n<%- message %>\nTry accessing <a href=\"/res"
  },
  {
    "path": "examples/content-negotiation/db.js",
    "chars": 146,
    "preview": "'use strict'\n\nvar users = [];\n\nusers.push({ name: 'Tobi' });\nusers.push({ name: 'Loki' });\nusers.push({ name: 'Jane' });"
  },
  {
    "path": "examples/content-negotiation/index.js",
    "chars": 1003,
    "preview": "'use strict'\n\nvar express = require('../../');\nvar app = module.exports = express();\nvar users = require('./db');\n\n// so"
  },
  {
    "path": "examples/content-negotiation/users.js",
    "chars": 382,
    "preview": "'use strict'\n\nvar users = require('./db');\n\nexports.html = function(req, res){\n  res.send('<ul>' + users.map(function(us"
  },
  {
    "path": "examples/cookie-sessions/index.js",
    "chars": 551,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar cookieSession = require('cookie-session');\nvar express = require('../"
  },
  {
    "path": "examples/cookies/index.js",
    "chars": 1311,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\nvar app = module.exports = express();\nva"
  },
  {
    "path": "examples/downloads/files/CCTV大赛上海分赛区.txt",
    "chars": 38,
    "preview": "Only for test.\nThe file name is faked."
  },
  {
    "path": "examples/downloads/files/amazing.txt",
    "chars": 24,
    "preview": "what an amazing download"
  },
  {
    "path": "examples/downloads/files/notes/groceries.txt",
    "chars": 22,
    "preview": "* milk\n* eggs\n* bread\n"
  },
  {
    "path": "examples/downloads/index.js",
    "chars": 1165,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\nvar path = require('node:path');\n\nvar ap"
  },
  {
    "path": "examples/ejs/index.js",
    "chars": 1331,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\nvar path = require('node:path');\n\nvar ap"
  },
  {
    "path": "examples/ejs/public/stylesheets/style.css",
    "chars": 98,
    "preview": "body {\n  padding: 50px 80px;\n  font: 14px \"Helvetica Neue\", \"Lucida Grande\", Arial, sans-serif;\n}\n"
  },
  {
    "path": "examples/ejs/views/footer.html",
    "chars": 16,
    "preview": "</body>\n</html>\n"
  },
  {
    "path": "examples/ejs/views/header.html",
    "chars": 236,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,ini"
  },
  {
    "path": "examples/ejs/views/users.html",
    "chars": 206,
    "preview": "<%- include('header.html') -%>\n\n<h1>Users</h1>\n<ul id=\"users\">\n  <% users.forEach(function(user){ %>\n    <li><%= user.na"
  },
  {
    "path": "examples/error/index.js",
    "chars": 1333,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\nvar logger = require('morgan');\nvar app "
  },
  {
    "path": "examples/error-pages/index.js",
    "chars": 2665,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\nvar path = require('node:path');\nvar app"
  },
  {
    "path": "examples/error-pages/views/404.ejs",
    "chars": 90,
    "preview": "<%- include('error_header') -%>\n<h2>Cannot find <%= url %></h2>\n<%- include('footer') -%>\n"
  },
  {
    "path": "examples/error-pages/views/500.ejs",
    "chars": 218,
    "preview": "<%- include('error_header') -%>\n<h2>Error: <%= error.message %></h2>\n<% if (settings['verbose errors']) { %>\n  <pre><%= "
  },
  {
    "path": "examples/error-pages/views/error_header.ejs",
    "chars": 186,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
  },
  {
    "path": "examples/error-pages/views/footer.ejs",
    "chars": 16,
    "preview": "</body>\n</html>\n"
  },
  {
    "path": "examples/error-pages/views/index.ejs",
    "chars": 356,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
  },
  {
    "path": "examples/hello-world/index.js",
    "chars": 269,
    "preview": "'use strict'\n\nvar express = require('../../');\n\nvar app = module.exports = express()\n\napp.get('/', function(req, res){\n "
  },
  {
    "path": "examples/markdown/index.js",
    "chars": 1025,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar escapeHtml = require('escape-html');\nvar express = require('../..');\n"
  },
  {
    "path": "examples/markdown/views/index.md",
    "chars": 58,
    "preview": "\n# {title}\n\nJust an example view rendered with _markdown_."
  },
  {
    "path": "examples/multi-router/controllers/api_v1.js",
    "chars": 272,
    "preview": "'use strict'\n\nvar express = require('../../..');\n\nvar apiv1 = express.Router();\n\napiv1.get('/', function(req, res) {\n  r"
  },
  {
    "path": "examples/multi-router/controllers/api_v2.js",
    "chars": 272,
    "preview": "'use strict'\n\nvar express = require('../../..');\n\nvar apiv2 = express.Router();\n\napiv2.get('/', function(req, res) {\n  r"
  },
  {
    "path": "examples/multi-router/index.js",
    "chars": 387,
    "preview": "'use strict'\n\nvar express = require('../..');\n\nvar app = module.exports = express();\n\napp.use('/api/v1', require('./cont"
  },
  {
    "path": "examples/mvc/controllers/main/index.js",
    "chars": 79,
    "preview": "'use strict'\n\nexports.index = function(req, res){\n  res.redirect('/users');\n};\n"
  },
  {
    "path": "examples/mvc/controllers/pet/index.js",
    "chars": 599,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar db = require('../../db');\n\nexports.engine = 'ejs';\n\nexports.before = "
  },
  {
    "path": "examples/mvc/controllers/pet/views/edit.ejs",
    "chars": 448,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
  },
  {
    "path": "examples/mvc/controllers/pet/views/show.ejs",
    "chars": 334,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
  },
  {
    "path": "examples/mvc/controllers/user/index.js",
    "chars": 872,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar db = require('../../db');\n\nexports.engine = 'hbs';\n\nexports.before = "
  },
  {
    "path": "examples/mvc/controllers/user/views/edit.hbs",
    "chars": 731,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale"
  },
  {
    "path": "examples/mvc/controllers/user/views/list.hbs",
    "chars": 388,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale"
  },
  {
    "path": "examples/mvc/controllers/user/views/show.hbs",
    "chars": 601,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale"
  },
  {
    "path": "examples/mvc/controllers/user-pet/index.js",
    "chars": 468,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar db = require('../../db');\n\nexports.name = 'pet';\nexports.prefix = '/u"
  },
  {
    "path": "examples/mvc/db.js",
    "chars": 420,
    "preview": "'use strict'\n\n// faux database\n\nvar pets = exports.pets = [];\n\npets.push({ name: 'Tobi', id: 0 });\npets.push({ name: 'Lo"
  },
  {
    "path": "examples/mvc/index.js",
    "chars": 2320,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../..');\nvar logger = require('morgan');\nvar path "
  },
  {
    "path": "examples/mvc/lib/boot.js",
    "chars": 2263,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../..');\nvar fs = require('node:fs');\nvar path "
  },
  {
    "path": "examples/mvc/public/style.css",
    "chars": 206,
    "preview": "body {\n  padding: 50px;\n  font: 16px \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\na {\n  color: #107aff;\n  text-deco"
  },
  {
    "path": "examples/mvc/views/404.ejs",
    "chars": 313,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width,initial"
  },
  {
    "path": "examples/mvc/views/5xx.ejs",
    "chars": 336,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width,initial"
  },
  {
    "path": "examples/online/index.js",
    "chars": 1024,
    "preview": "'use strict'\n\n// install redis first:\n// https://redis.io/\n\n// then:\n// $ npm install redis online\n// $ redis-server\n\n/*"
  },
  {
    "path": "examples/params/index.js",
    "chars": 1353,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar createError = require('http-errors')\nvar express = require('../../');"
  },
  {
    "path": "examples/resource/index.js",
    "chars": 2295,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\n\nvar app = module.exports = express();\n\n"
  },
  {
    "path": "examples/route-map/index.js",
    "chars": 1419,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar escapeHtml = require('escape-html')\nvar express = require('../../lib/"
  },
  {
    "path": "examples/route-middleware/index.js",
    "chars": 2399,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../lib/express');\n\nvar app = express();\n\n// Exa"
  },
  {
    "path": "examples/route-separation/index.js",
    "chars": 1136,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../..');\nvar path = require('node:path');\nvar app "
  },
  {
    "path": "examples/route-separation/post.js",
    "chars": 292,
    "preview": "'use strict'\n\n// Fake posts database\n\nvar posts = [\n  { title: 'Foo', body: 'some foo bar' },\n  { title: 'Foo bar', body"
  },
  {
    "path": "examples/route-separation/public/style.css",
    "chars": 286,
    "preview": "body {\n  padding: 50px;\n  font: 14px \"Helvetica Neue\", Arial, sans-serif;\n}\na {\n  color: #00AEFF;\n  text-decoration: non"
  },
  {
    "path": "examples/route-separation/site.js",
    "chars": 115,
    "preview": "'use strict'\n\nexports.index = function(req, res){\n  res.render('index', { title: 'Route Separation Example' });\n};\n"
  },
  {
    "path": "examples/route-separation/user.js",
    "chars": 1006,
    "preview": "'use strict'\n\n// Fake user database\n\nvar users = [\n  { name: 'TJ', email: 'tj@vision-media.ca' },\n  { name: 'Tobi', emai"
  },
  {
    "path": "examples/route-separation/views/footer.ejs",
    "chars": 16,
    "preview": "</body>\n</html>\n"
  },
  {
    "path": "examples/route-separation/views/header.ejs",
    "chars": 224,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,ini"
  },
  {
    "path": "examples/route-separation/views/index.ejs",
    "chars": 196,
    "preview": "<%- include('header') -%>\n\n<h1><%= title %></h1>\n\n<ul>\n  <li>Visit the <a href=\"/users\">users</a> page.</li>\n  <li>Visit"
  },
  {
    "path": "examples/route-separation/views/posts/index.ejs",
    "chars": 209,
    "preview": "<%- include('../header') -%>\n\n<h1>Posts</h1>\n\n<dl id=\"posts\">\n  <% posts.forEach(function(post) { %>\n    <dt><%= post.ti"
  },
  {
    "path": "examples/route-separation/views/users/edit.ejs",
    "chars": 439,
    "preview": "<%- include('../header') -%>\n\n<h1>Editing <%= user.name %></h1>\n\n<div id=\"user\">\n  <form action=\"?_method=put\" method=\"p"
  },
  {
    "path": "examples/route-separation/views/users/index.ejs",
    "chars": 288,
    "preview": "<%- include('../header') -%>\n\n<h1><%= title %></h1>\n\n<div id=\"users\">\n  <% users.forEach(function(user, index) { %>\n    "
  },
  {
    "path": "examples/route-separation/views/users/view.ejs",
    "chars": 144,
    "preview": "<%- include('../header') -%>\n\n<h1><%= user.name %></h1>\n\n<div id=\"user\">\n  <p>Email: <%= user.email %></p>\n</div>\n\n<%- i"
  },
  {
    "path": "examples/search/index.js",
    "chars": 1577,
    "preview": "'use strict'\n\n// install redis first:\n// https://redis.io/\n\n// then:\n// $ npm install redis\n// $ redis-server\n\n/**\n * Mo"
  },
  {
    "path": "examples/search/public/client.js",
    "chars": 390,
    "preview": "'use strict'\n\nvar search = document.querySelector('[type=search]');\nvar code = document.querySelector('pre');\n\nsearch.ad"
  },
  {
    "path": "examples/search/public/index.html",
    "chars": 483,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,ini"
  },
  {
    "path": "examples/session/index.js",
    "chars": 844,
    "preview": "'use strict'\n\n// install redis first:\n// https://redis.io/\n\n// then:\n// $ npm install redis\n// $ redis-server\n\nvar expre"
  },
  {
    "path": "examples/session/redis.js",
    "chars": 957,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../..');\nvar logger = require('morgan');\nvar sessi"
  },
  {
    "path": "examples/static-files/index.js",
    "chars": 1363,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../..');\nvar logger = require('morgan');\nvar path "
  },
  {
    "path": "examples/static-files/public/css/style.css",
    "chars": 11,
    "preview": "body {\n  \n}"
  },
  {
    "path": "examples/static-files/public/hello.txt",
    "chars": 3,
    "preview": "hey"
  },
  {
    "path": "examples/static-files/public/js/app.js",
    "chars": 7,
    "preview": "// foo\n"
  },
  {
    "path": "examples/vhost/index.js",
    "chars": 1037,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../..');\nvar logger = require('morgan');\nvar vhost"
  },
  {
    "path": "examples/view-constructor/github-view.js",
    "chars": 1069,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar https = require('node:https');\nvar path = require('node:path');\nvar e"
  },
  {
    "path": "examples/view-constructor/index.js",
    "chars": 1167,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\nvar GithubView = require('./github-view'"
  },
  {
    "path": "examples/view-locals/index.js",
    "chars": 3127,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../..');\nvar path = require('node:path');\nvar User"
  },
  {
    "path": "examples/view-locals/user.js",
    "chars": 730,
    "preview": "'use strict'\n\nmodule.exports = User;\n\n// faux model\n\nfunction User(name, age, species) {\n  this.name = name;\n  this.age "
  },
  {
    "path": "examples/view-locals/views/index.ejs",
    "chars": 500,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width,initial"
  },
  {
    "path": "examples/web-service/index.js",
    "chars": 3044,
    "preview": "'use strict'\n\n/**\n * Module dependencies.\n */\n\nvar express = require('../../');\n\nvar app = module.exports = express();\n\n"
  },
  {
    "path": "index.js",
    "chars": 224,
    "preview": "/*!\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2013 Roman Shtylman\n * Copyright(c) 2014-2015 Do"
  },
  {
    "path": "lib/application.js",
    "chars": 13977,
    "preview": "/*!\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2013 Roman Shtylman\n * Copyright(c) 2014-2015 Do"
  },
  {
    "path": "lib/express.js",
    "chars": 1636,
    "preview": "/*!\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2013 Roman Shtylman\n * Copyright(c) 2014-2015 Do"
  },
  {
    "path": "lib/request.js",
    "chars": 12254,
    "preview": "/*!\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2013 Roman Shtylman\n * Copyright(c) 2014-2015 Do"
  },
  {
    "path": "lib/response.js",
    "chars": 24844,
    "preview": "/*!\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2014-2015 Douglas Christopher Wilson\n * MIT Lice"
  },
  {
    "path": "lib/utils.js",
    "chars": 5293,
    "preview": "/*!\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2014-2015 Douglas Christopher Wilson\n * MIT Lice"
  },
  {
    "path": "lib/view.js",
    "chars": 3809,
    "preview": "/*!\n * express\n * Copyright(c) 2009-2013 TJ Holowaychuk\n * Copyright(c) 2013 Roman Shtylman\n * Copyright(c) 2014-2015 Do"
  },
  {
    "path": "package.json",
    "chars": 2731,
    "preview": "{\n  \"name\": \"express\",\n  \"description\": \"Fast, unopinionated, minimalist web framework\",\n  \"version\": \"5.2.1\",\n  \"author"
  },
  {
    "path": "test/Route.js",
    "chars": 6480,
    "preview": "'use strict'\n\nvar after = require('after');\nvar assert = require('node:assert')\nvar express = require('../')\n  , Route ="
  },
  {
    "path": "test/Router.js",
    "chars": 17372,
    "preview": "'use strict'\n\nvar after = require('after');\nvar express = require('../')\n  , Router = express.Router\n  , methods = requi"
  },
  {
    "path": "test/acceptance/auth.js",
    "chars": 3064,
    "preview": "var app = require('../../examples/auth')\nvar request = require('supertest')\n\nfunction getCookie(res) {\n  return res.head"
  },
  {
    "path": "test/acceptance/content-negotiation.js",
    "chars": 1402,
    "preview": "\nvar request = require('supertest')\n  , app = require('../../examples/content-negotiation');\n\ndescribe('content-negotiat"
  },
  {
    "path": "test/acceptance/cookie-sessions.js",
    "chars": 942,
    "preview": "\nvar app = require('../../examples/cookie-sessions')\nvar request = require('supertest')\n\ndescribe('cookie-sessions', fun"
  },
  {
    "path": "test/acceptance/cookies.js",
    "chars": 1746,
    "preview": "\nvar app = require('../../examples/cookies')\n  , request = require('supertest');\nvar utils = require('../support/utils')"
  },
  {
    "path": "test/acceptance/downloads.js",
    "chars": 1265,
    "preview": "\nvar app = require('../../examples/downloads')\n  , request = require('supertest');\n\ndescribe('downloads', function(){\n  "
  },
  {
    "path": "test/acceptance/ejs.js",
    "chars": 505,
    "preview": "\nvar request = require('supertest')\n  , app = require('../../examples/ejs');\n\ndescribe('ejs', function(){\n  describe('GE"
  },
  {
    "path": "test/acceptance/error-pages.js",
    "chars": 2315,
    "preview": "\nvar app = require('../../examples/error-pages')\n  , request = require('supertest');\n\ndescribe('error-pages', function()"
  },
  {
    "path": "test/acceptance/error.js",
    "chars": 608,
    "preview": "\nvar app = require('../../examples/error')\n  , request = require('supertest');\n\ndescribe('error', function(){\n  describe"
  },
  {
    "path": "test/acceptance/hello-world.js",
    "chars": 488,
    "preview": "\nvar app = require('../../examples/hello-world')\nvar request = require('supertest')\n\ndescribe('hello-world', function ()"
  },
  {
    "path": "test/acceptance/markdown.js",
    "chars": 476,
    "preview": "\nvar app = require('../../examples/markdown')\nvar request = require('supertest')\n\ndescribe('markdown', function(){\n  des"
  },
  {
    "path": "test/acceptance/multi-router.js",
    "chars": 1173,
    "preview": "var app = require('../../examples/multi-router')\nvar request = require('supertest')\n\ndescribe('multi-router', function()"
  },
  {
    "path": "test/acceptance/mvc.js",
    "chars": 3292,
    "preview": "\nvar request = require('supertest')\n  , app = require('../../examples/mvc');\n\ndescribe('mvc', function(){\n  describe('GE"
  },
  {
    "path": "test/acceptance/params.js",
    "chars": 1064,
    "preview": "var app = require('../../examples/params')\nvar request = require('supertest')\n\ndescribe('params', function(){\n  describe"
  },
  {
    "path": "test/acceptance/resource.js",
    "chars": 1844,
    "preview": "var app = require('../../examples/resource')\nvar request = require('supertest')\n\ndescribe('resource', function(){\n  desc"
  },
  {
    "path": "test/acceptance/route-map.js",
    "chars": 1048,
    "preview": "\nvar request = require('supertest')\n  , app = require('../../examples/route-map');\n\ndescribe('route-map', function(){\n  "
  },
  {
    "path": "test/acceptance/route-separation.js",
    "chars": 2541,
    "preview": "\nvar app = require('../../examples/route-separation')\nvar request = require('supertest')\n\ndescribe('route-separation', f"
  },
  {
    "path": "test/acceptance/vhost.js",
    "chars": 1190,
    "preview": "var app = require('../../examples/vhost')\nvar request = require('supertest')\n\ndescribe('vhost', function(){\n  describe('"
  },
  {
    "path": "test/acceptance/web-service.js",
    "chars": 3129,
    "preview": "\nvar request = require('supertest')\n  , app = require('../../examples/web-service');\n\ndescribe('web-service', function()"
  },
  {
    "path": "test/app.all.js",
    "chars": 790,
    "preview": "'use strict'\n\nvar after = require('after')\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('a"
  },
  {
    "path": "test/app.engine.js",
    "chars": 2246,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('../')\n  , fs = require('node:fs');\nvar path = r"
  },
  {
    "path": "test/app.head.js",
    "chars": 1412,
    "preview": "'use strict'\n\nvar express = require('../');\nvar request = require('supertest');\nvar assert = require('node:assert');\n\nde"
  },
  {
    "path": "test/app.js",
    "chars": 2738,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('..')\nvar request = require('supertest')\n\ndescri"
  },
  {
    "path": "test/app.listen.js",
    "chars": 1711,
    "preview": "'use strict'\n\nvar express = require('../')\nvar assert = require('node:assert')\n\ndescribe('app.listen()', function(){\n  i"
  },
  {
    "path": "test/app.locals.js",
    "chars": 806,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('../')\n\ndescribe('app', function(){\n  describe('"
  },
  {
    "path": "test/app.options.js",
    "chars": 2845,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('OPTIONS', function(){\n  it('sh"
  },
  {
    "path": "test/app.param.js",
    "chars": 7560,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('app', function(){\n  describe('"
  },
  {
    "path": "test/app.render.js",
    "chars": 11092,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('..');\nvar path = require('node:path')\nvar tmpl "
  },
  {
    "path": "test/app.request.js",
    "chars": 2983,
    "preview": "'use strict'\n\nvar after = require('after')\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('a"
  },
  {
    "path": "test/app.response.js",
    "chars": 2973,
    "preview": "'use strict'\n\nvar after = require('after')\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('a"
  },
  {
    "path": "test/app.route.js",
    "chars": 4762,
    "preview": "'use strict'\n\nvar express = require('../');\nvar request = require('supertest');\n\ndescribe('app.route', function(){\n  it("
  },
  {
    "path": "test/app.router.js",
    "chars": 29831,
    "preview": "'use strict'\n\nvar after = require('after');\nvar express = require('../')\n  , request = require('supertest')\n  , assert ="
  },
  {
    "path": "test/app.routes.error.js",
    "chars": 1504,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('../')\n  , request = require('supertest');\n\ndesc"
  },
  {
    "path": "test/app.use.js",
    "chars": 12605,
    "preview": "'use strict'\n\nvar after = require('after');\nvar assert = require('node:assert')\nvar express = require('..');\nvar request"
  },
  {
    "path": "test/config.js",
    "chars": 5823,
    "preview": "'use strict'\n\nvar assert = require('node:assert');\nvar express = require('..');\n\ndescribe('config', function () {\n  desc"
  },
  {
    "path": "test/exports.js",
    "chars": 2344,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('../');\nvar request = require('supertest');\n\ndes"
  },
  {
    "path": "test/express.json.js",
    "chars": 23652,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage\n"
  },
  {
    "path": "test/express.raw.js",
    "chars": 16296,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage\n"
  },
  {
    "path": "test/express.static.js",
    "chars": 23498,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('..')\nvar path = require('node:path')\nconst { Bu"
  },
  {
    "path": "test/express.text.js",
    "chars": 17249,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage\n"
  },
  {
    "path": "test/express.urlencoded.js",
    "chars": 26722,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar AsyncLocalStorage = require('node:async_hooks').AsyncLocalStorage\n"
  },
  {
    "path": "test/fixtures/% of dogs.txt",
    "chars": 3,
    "preview": "20%"
  },
  {
    "path": "test/fixtures/.name",
    "chars": 4,
    "preview": "tobi"
  },
  {
    "path": "test/fixtures/blog/index.html",
    "chars": 12,
    "preview": "<b>index</b>"
  },
  {
    "path": "test/fixtures/blog/post/index.tmpl",
    "chars": 18,
    "preview": "<h1>blog post</h1>"
  },
  {
    "path": "test/fixtures/broken.send",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "test/fixtures/default_layout/name.tmpl",
    "chars": 12,
    "preview": "<p>$name</p>"
  },
  {
    "path": "test/fixtures/default_layout/user.tmpl",
    "chars": 17,
    "preview": "<p>$user.name</p>"
  },
  {
    "path": "test/fixtures/email.tmpl",
    "chars": 23,
    "preview": "<p>This is an email</p>"
  },
  {
    "path": "test/fixtures/empty.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "test/fixtures/local_layout/user.tmpl",
    "chars": 23,
    "preview": "<span>$user.name</span>"
  },
  {
    "path": "test/fixtures/name.tmpl",
    "chars": 12,
    "preview": "<p>$name</p>"
  },
  {
    "path": "test/fixtures/name.txt",
    "chars": 4,
    "preview": "tobi"
  },
  {
    "path": "test/fixtures/nums.txt",
    "chars": 9,
    "preview": "123456789"
  },
  {
    "path": "test/fixtures/pets/names.txt",
    "chars": 9,
    "preview": "tobi,loki"
  },
  {
    "path": "test/fixtures/snow ☃/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "test/fixtures/todo.html",
    "chars": 18,
    "preview": "<li>groceries</li>"
  },
  {
    "path": "test/fixtures/todo.txt",
    "chars": 11,
    "preview": "- groceries"
  },
  {
    "path": "test/fixtures/user.html",
    "chars": 20,
    "preview": "<p>{{user.name}}</p>"
  },
  {
    "path": "test/fixtures/user.tmpl",
    "chars": 17,
    "preview": "<p>$user.name</p>"
  },
  {
    "path": "test/fixtures/users/index.html",
    "chars": 23,
    "preview": "<p>tobi, loki, jane</p>"
  },
  {
    "path": "test/fixtures/users/tobi.txt",
    "chars": 6,
    "preview": "ferret"
  },
  {
    "path": "test/middleware.basic.js",
    "chars": 1051,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('../');\nvar request = require('supertest');\n\ndes"
  },
  {
    "path": "test/regression.js",
    "chars": 377,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('throw after .end()', function("
  },
  {
    "path": "test/req.accepts.js",
    "chars": 2964,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.acceptsCharsets.js",
    "chars": 1609,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.acceptsEncodings.js",
    "chars": 953,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.acceptsLanguages.js",
    "chars": 1425,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.baseUrl.js",
    "chars": 2120,
    "preview": "'use strict'\n\nvar express = require('..')\nvar request = require('supertest')\n\ndescribe('req', function(){\n  describe('.b"
  },
  {
    "path": "test/req.fresh.js",
    "chars": 1664,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.get.js",
    "chars": 1415,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n  , assert = require('node:assert');\n\ndesc"
  },
  {
    "path": "test/req.host.js",
    "chars": 3536,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n\ndescribe('req', function(){\n  describe('."
  },
  {
    "path": "test/req.hostname.js",
    "chars": 4420,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n\ndescribe('req', function(){\n  describe('."
  },
  {
    "path": "test/req.ip.js",
    "chars": 2979,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.ips.js",
    "chars": 1743,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.is.js",
    "chars": 3782,
    "preview": "'use strict'\n\nvar express = require('..')\nvar request = require('supertest')\n\ndescribe('req.is()', function () {\n  descr"
  },
  {
    "path": "test/req.path.js",
    "chars": 412,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.protocol.js",
    "chars": 2579,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.query.js",
    "chars": 2703,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('../')\n  , request = require('supertest');\n\ndesc"
  },
  {
    "path": "test/req.range.js",
    "chars": 2351,
    "preview": "'use strict'\n\nvar express = require('..');\nvar request = require('supertest')\n\ndescribe('req', function(){\n  describe('."
  },
  {
    "path": "test/req.route.js",
    "chars": 662,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.secure.js",
    "chars": 2457,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.signedCookies.js",
    "chars": 851,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n  , cookieParser = require('cookie-parser'"
  },
  {
    "path": "test/req.stale.js",
    "chars": 1102,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.subdomains.js",
    "chars": 4328,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/req.xhr.js",
    "chars": 1030,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('req', function(){\n  describe('"
  },
  {
    "path": "test/res.append.js",
    "chars": 2925,
    "preview": "'use strict'\n\nvar assert = require('node:assert')\nvar express = require('..')\nvar request = require('supertest')\n\ndescri"
  },
  {
    "path": "test/res.attachment.js",
    "chars": 1936,
    "preview": "'use strict'\n\nconst { Buffer } = require('node:buffer');\n\nvar express = require('../')\n  , request = require('supertest'"
  },
  {
    "path": "test/res.clearCookie.js",
    "chars": 1606,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('res', function(){\n  describe('"
  },
  {
    "path": "test/res.cookie.js",
    "chars": 7428,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n  , cookieParser = require('cookie-parser'"
  },
  {
    "path": "test/res.download.js",
    "chars": 13140,
    "preview": "'use strict'\n\nvar after = require('after');\nvar assert = require('node:assert')\nvar AsyncLocalStorage = require('node:as"
  },
  {
    "path": "test/res.format.js",
    "chars": 5901,
    "preview": "'use strict'\n\nvar after = require('after')\nvar express = require('../')\n  , request = require('supertest')\n  , assert = "
  },
  {
    "path": "test/res.get.js",
    "chars": 472,
    "preview": "'use strict'\n\nvar express = require('..');\nvar request = require('supertest');\n\ndescribe('res', function(){\n  describe('"
  },
  {
    "path": "test/res.json.js",
    "chars": 4812,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n  , assert = require('node:assert');\n\ndesc"
  },
  {
    "path": "test/res.jsonp.js",
    "chars": 9154,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n  , assert = require('node:assert');\nvar u"
  },
  {
    "path": "test/res.links.js",
    "chars": 1877,
    "preview": "'use strict'\n\nvar express = require('..');\nvar request = require('supertest');\n\ndescribe('res', function(){\n  describe('"
  },
  {
    "path": "test/res.locals.js",
    "chars": 733,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest');\n\ndescribe('res', function(){\n  describe('"
  },
  {
    "path": "test/res.location.js",
    "chars": 8420,
    "preview": "'use strict'\n\nvar express = require('../')\n  , request = require('supertest')\n  , assert = require('node:assert')\n  , ur"
  }
]

// ... and 13 more files (download for full content)

About this extraction

This page contains the full source code of the expressjs/express GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 213 files (689.9 KB), approximately 194.0k tokens, and a symbol index with 116 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!