Compare commits

..

2 Commits

Author SHA1 Message Date
Sebastian Beltran
a865e5402d fix lint error
Signed-off-by: Sebastian Beltran <bjohansebas@gmail.com>
2025-08-12 18:00:28 -05:00
Sebastian Beltran
786fbf417a test: enhance req.is() tests with additional cases
Signed-off-by: Sebastian Beltran <bjohansebas@gmail.com>
2025-08-12 17:59:17 -05:00
17 changed files with 205 additions and 139 deletions

View File

@@ -27,11 +27,11 @@ jobs:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 'lts/*'
@@ -46,19 +46,19 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
node-version: [18, 19, 20, 21, 22, 23, 24, 25]
node-version: [18, 19, 20, 21, 22, 23, 24]
# 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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.node-version }}
@@ -80,7 +80,7 @@ jobs:
run: npm run test-ci
- name: Upload code coverage
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }}
path: ./coverage/lcov.info
@@ -93,7 +93,7 @@ jobs:
contents: read
checks: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
@@ -102,7 +102,7 @@ jobs:
run: sudo apt-get -y install lcov
- name: Collect coverage reports
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: ./coverage
pattern: coverage-node-*
@@ -112,6 +112,6 @@ jobs:
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
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6
with:
file: ./lcov.info

View File

@@ -39,13 +39,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5
uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with:
languages: ${{ matrix.language }}
config: |
@@ -71,4 +71,4 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5
uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2

View File

@@ -37,12 +37,12 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.node-version }}
@@ -64,7 +64,7 @@ jobs:
run: npm run test-ci
- name: Upload code coverage
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: coverage-node-${{ matrix.node-version }}-${{ matrix.os }}
path: ./coverage/lcov.info
@@ -77,7 +77,7 @@ jobs:
contents: read
checks: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
@@ -86,7 +86,7 @@ jobs:
run: sudo apt-get -y install lcov
- name: Collect coverage reports
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: ./coverage
pattern: coverage-node-*
@@ -96,6 +96,6 @@ jobs:
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
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6
with:
file: ./lcov.info

View File

@@ -32,12 +32,12 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
with:
results_file: results.sarif
results_format: sarif
@@ -59,7 +59,7 @@ jobs:
# 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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: SARIF file
path: results.sarif
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5
uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with:
sarif_file: results.sarif

4
.gitignore vendored
View File

@@ -5,10 +5,6 @@ npm-shrinkwrap.json
*.log
*.gz
# Yarn
yarn-error.log
yarn.lock
# Coveralls
.nyc_output
coverage

View File

@@ -1,22 +1,3 @@
# 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)
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
========================

View File

@@ -40,9 +40,7 @@ app.get('/', (req, res) => {
res.send('Hello World')
})
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000')
})
app.listen(3000)
```
## Installation
@@ -154,7 +152,7 @@ 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?tab=security-ov-file).
If you discover a security vulnerability in Express, please see [Security Policies and Procedures](SECURITY.md).
### Running Tests
@@ -208,12 +206,13 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj)
* [bjohansebas](https://github.com/bjohansebas) - **Sebastian Beltran**
* [carpasse](https://github.com/carpasse) - **Carlos Serrano**
* [CBID2](https://github.com/CBID2) - **Christine Belzie**
* [dpopp07](https://github.com/dpopp07) - **Dustin Popp**
* [UlisesGascon](https://github.com/UlisesGascon) - **Ulises Gascón** (he/him)
* [3imed-jaberi](https://github.com/3imed-jaberi) - **Imed Jaberi**
* [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)
* [Sushmeet](https://github.com/Sushmeet) - **Sushmeet Sunger**
* [rxmarbles](https://github.com/rxmarbles) **Rick Markins** (He/him)
<details>
<summary>Triagers emeriti members</summary>
@@ -252,9 +251,6 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj)
* [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>
@@ -263,14 +259,14 @@ The original author of Express is [TJ Holowaychuk](https://github.com/tj)
[MIT](LICENSE)
[coveralls-image]: https://img.shields.io/coverallsCoverage/github/expressjs/express?branch=master
[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/express/master
[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/express/ci.yml?branch=master&label=ci
[github-actions-ci-image]: https://badgen.net/github/checks/expressjs/express/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-image]: https://badgen.net/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
[npm-version-image]: https://badgen.net/npm/v/express
[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/express/badge
[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/express
[Code of Conduct]: https://github.com/expressjs/.github/blob/HEAD/CODE_OF_CONDUCT.md

56
SECURITY.md Normal file
View File

@@ -0,0 +1,56 @@
# Security Policies and Procedures
This document outlines security procedures and general policies for the Express
project.
* [Reporting a Bug](#reporting-a-bug)
* [Disclosure Policy](#disclosure-policy)
* [Comments on this Policy](#comments-on-this-policy)
## Reporting a Bug
The Express team and community take all security bugs in Express seriously.
Thank you for improving the security of Express. We appreciate your efforts and
responsible disclosure and will make every effort to acknowledge your
contributions.
Report security bugs by emailing `express-security@lists.openjsf.org`.
To ensure the timely response to your report, please ensure that the entirety
of the report is contained within the email body and not solely behind a web
link or an attachment.
The lead maintainer will acknowledge your email within 48 hours, and will send a
more detailed response within 48 hours indicating the next steps in handling
your report. After the initial reply to your report, the security team will
endeavor to keep you informed of the progress towards a fix and full
announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining
the module.
## Pre-release Versions
Alpha and Beta releases are unstable and **not suitable for production use**.
Vulnerabilities found in pre-releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section.
Due to the unstable nature of the branch it is not guaranteed that any fixes will be released in the next pre-release.
## Disclosure Policy
When the security team receives a security bug report, they will assign it to a
primary handler. This person will coordinate the fix and release process,
involving the following steps:
* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* Prepare fixes for all releases still under maintenance. These fixes will be
released as fast as possible to npm.
## The Express Threat Model
We are currently working on a new version of the security model, the most updated version can be found [here](https://github.com/expressjs/security-wg/blob/main/docs/ThreatModel.md)
## Comments on this Policy
If you have suggestions on how this process could be improved please submit a
pull request.

View File

@@ -597,7 +597,7 @@ app.render = function render(name, options, callback) {
app.listen = function listen() {
var server = http.createServer(this)
var args = slice.call(arguments)
var args = Array.prototype.slice.call(arguments)
if (typeof args[args.length - 1] === 'function') {
var done = args[args.length - 1] = once(args[args.length - 1])
server.once('error', done)

View File

@@ -75,20 +75,24 @@ req.header = function header(name) {
switch (lc) {
case 'referer':
case 'referrer':
return this.headers.referer || this.headers.referrer;
return this.headers.referrer
|| this.headers.referer;
default:
return this.headers[lc];
}
};
/**
* To do: update docs.
*
* Check if the given `type(s)` is acceptable, returning
* the best match when true, otherwise `false`, in which
* the best match when true, otherwise `undefined`, in which
* case you should respond with 406 "Not Acceptable".
*
* The `type` value may be a single MIME type string
* such as "application/json", an extension name
* such as "json", an argument list such as `"json", "html", "text/plain"`,
* such as "json", a comma-delimited list such as "json, html, text/plain",
* an argument list such as `"json", "html", "text/plain"`,
* or an array `["json", "html", "text/plain"]`. When a list
* or array is given, the _best_ match, if any is returned.
*
@@ -103,7 +107,7 @@ req.header = function header(name) {
* // => "html"
* req.accepts('text/html');
* // => "text/html"
* req.accepts('json', 'text');
* req.accepts('json, text');
* // => "json"
* req.accepts('application/json');
* // => "application/json"
@@ -111,11 +115,12 @@ req.header = function header(name) {
* // Accept: text/*, application/json
* req.accepts('image/png');
* req.accepts('png');
* // => false
* // => undefined
*
* // Accept: text/*;q=.5, application/json
* req.accepts(['html', 'json']);
* req.accepts('html', 'json');
* req.accepts('html, json');
* // => "json"
*
* @param {String|Array} type(s)
@@ -142,34 +147,17 @@ req.acceptsEncodings = function(){
};
/**
* Checks if the specified `charset`s are acceptable based on the request's `Accept-Charset` header.
* Returns the best matching charset or an array of acceptable charsets.
* Check if the given `charset`s are acceptable,
* otherwise you should respond with 406 "Not Acceptable".
*
* The `charset` argument(s) can be:
* - A single charset string (e.g., "utf-8")
* - Multiple charset strings as arguments (e.g., `"utf-8", "iso-8859-1"`)
* - A comma-delimited list of charsets (e.g., `"utf-8, iso-8859-1"`)
*
* Examples:
*
* // Accept-Charset: utf-8, iso-8859-1
* req.acceptsCharsets('utf-8');
* // => "utf-8"
*
* req.acceptsCharsets('utf-8', 'iso-8859-1');
* // => "utf-8"
*
* req.acceptsCharsets('utf-8, utf-16');
* // => "utf-8"
*
* @param {...String} charsets - The charset(s) to check against the `Accept-Charset` header.
* @return {String|Array} - The best matching charset, or an array of acceptable charsets.
* @param {String} ...charset
* @return {String|Array}
* @public
*/
req.acceptsCharsets = function(...charsets) {
const accept = accepts(this);
return accept.charsets(...charsets);
req.acceptsCharsets = function(){
var accept = accepts(this);
return accept.charsets.apply(accept, arguments);
};
/**
@@ -294,12 +282,12 @@ req.is = function is(types) {
*/
defineGetter(req, 'protocol', function protocol(){
var proto = this.socket.encrypted
var proto = this.connection.encrypted
? 'https'
: 'http';
var trust = this.app.get('trust proxy fn');
if (!trust(this.socket.remoteAddress, 0)) {
if (!trust(this.connection.remoteAddress, 0)) {
return proto;
}
@@ -418,7 +406,7 @@ defineGetter(req, 'host', function host(){
var trust = this.app.get('trust proxy fn');
var val = this.get('X-Forwarded-Host');
if (!val || !trust(this.socket.remoteAddress, 0)) {
if (!val || !trust(this.connection.remoteAddress, 0)) {
val = this.get('Host');
} else if (val.indexOf(',') !== -1) {
// Note: X-Forwarded-Host is normally only ever a

View File

@@ -850,8 +850,7 @@ res.redirect = function redirect(url) {
html: function(){
var u = escapeHtml(address);
body = '<!DOCTYPE html><head><title>' + statuses.message[status] + '</title></head>'
+ '<body><p>' + statuses.message[status] + '. Redirecting to ' + u + '</p></body>'
body = '<p>' + statuses.message[status] + '. Redirecting to ' + u + '</p>'
},
default: function(){

View File

@@ -1,7 +1,7 @@
{
"name": "express",
"description": "Fast, unopinionated, minimalist web framework",
"version": "5.2.1",
"version": "5.1.0",
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"contributors": [
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
@@ -33,7 +33,7 @@
],
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.1",
"body-parser": "^2.2.0",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
@@ -52,7 +52,7 @@
"once": "^1.4.0",
"parseurl": "^1.3.3",
"proxy-addr": "^2.0.7",
"qs": "^6.14.1",
"qs": "^6.14.0",
"range-parser": "^1.2.1",
"router": "^2.2.0",
"send": "^1.1.0",
@@ -84,6 +84,7 @@
},
"files": [
"LICENSE",
"History.md",
"Readme.md",
"index.js",
"lib/"
@@ -91,7 +92,7 @@
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test": "mocha --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
"test": "mocha --require test/support/env --exit --reporter spec --check-leaks test/ test/acceptance/",
"test-ci": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=lcovonly --reporter=text npm test",
"test-cov": "nyc --exclude examples --exclude test --exclude benchmarks --reporter=html --reporter=text npm test",
"test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"

View File

@@ -45,19 +45,6 @@ describe('req', function(){
.set('Accept-Charset', 'foo, bar')
.expect('no', done);
})
it('should return the best matching charset from multiple inputs', function (done) {
var app = express();
app.use(function(req, res, next){
res.end(req.acceptsCharsets('utf-8', 'iso-8859-1'));
});
request(app)
.get('/')
.set('Accept-Charset', 'iso-8859-1, utf-8')
.expect('iso-8859-1', done);
})
})
})
})

View File

@@ -33,20 +33,6 @@ describe('req', function(){
.expect('http://foobar.com', done);
})
it('should prefer Referer over Referrer', function(done){
var app = express();
app.use(function(req, res){
res.end(req.get('Referer'));
});
request(app)
.post('/')
.set('Referrer', 'http://foobar.com')
.set('Referer', 'http://example.com')
.expect('http://example.com', done);
})
it('should throw missing header name', function (done) {
var app = express()

View File

@@ -2,6 +2,7 @@
var express = require('..')
var request = require('supertest')
var after = require('after')
describe('req.is()', function () {
describe('when given a mime type', function () {
@@ -27,10 +28,24 @@ describe('req.is()', function () {
})
request(app)
.post('/')
.type('application/json')
.send('{}')
.expect(200, 'false', done)
.post('/')
.type('application/json')
.send('{}')
.expect(200, 'false', done)
})
it('should return false when none in list matches', function (done) {
var app = express()
app.use(function (req, res) {
res.json(req.is(['image/jpeg', 'text/html']))
})
request(app)
.post('/')
.type('application/json')
.send('{}')
.expect(200, 'false', done)
})
it('should ignore charset', function (done) {
@@ -41,15 +56,15 @@ describe('req.is()', function () {
})
request(app)
.post('/')
.type('application/json; charset=UTF-8')
.send('{}')
.expect(200, '"application/json"', done)
.post('/')
.type('application/json; charset=UTF-8')
.send('{}')
.expect(200, '"application/json"', done)
})
})
describe('when content-type is not present', function(){
it('should return false', function (done) {
it('should return false for single type', function (done) {
var app = express()
app.use(function (req, res) {
@@ -61,6 +76,19 @@ describe('req.is()', function () {
.send('{}')
.expect(200, 'false', done)
})
it('should return false for multiple types', function (done) {
var app = express()
app.use(function (req, res) {
res.json(req.is(['application/json', 'image/jpeg']))
})
request(app)
.post('/')
.send('{}')
.expect(200, 'false', done)
})
})
describe('when given an extension', function(){
@@ -77,6 +105,27 @@ describe('req.is()', function () {
.send('{}')
.expect(200, '"json"', done)
})
it('should lookup the first matching extension from list', function (done) {
var app = express()
var cb = after(2, done)
app.use(function (req, res) {
res.json(req.is(['json', 'html']))
})
request(app)
.post('/')
.type('application/json')
.send('{}')
.expect(200, '"json"', cb)
request(app)
.post('/')
.type('text/html')
.send('{}')
.expect(200, '"html"', cb)
})
})
describe('when given */subtype', function(){
@@ -166,4 +215,31 @@ describe('req.is()', function () {
.expect(200, '"application/json"', done)
})
})
it('should match wildcards in list and return full type or false', function (done){
var app = express()
var cb = after(3, done)
app.use(function (req, res) {
res.json(req.is(['application/*', '*/jpeg']))
})
request(app)
.post('/')
.type('image/jpeg')
.send('{}')
.expect(200, '"image/jpeg"', cb)
request(app)
.post('/')
.type('text/html')
.send('{}')
.expect(200, 'false', cb)
request(app)
.post('/')
.type('application/json')
.send('{}')
.expect(200, '"application/json"', cb)
})
})

View File

@@ -39,7 +39,7 @@ describe('req', function(){
app.enable('trust proxy');
app.use(function(req, res){
req.socket.encrypted = true;
req.connection.encrypted = true;
res.end(req.protocol);
});

View File

@@ -91,7 +91,7 @@ describe('res', function(){
.set('Accept', 'text/html')
.expect('Content-Type', /html/)
.expect('Location', 'http://google.com')
.expect(302, '<!DOCTYPE html><head><title>Found</title></head><body><p>Found. Redirecting to http://google.com</p></body>', done)
.expect(302, '<p>Found. Redirecting to http://google.com</p>', done)
})
it('should escape the url', function(done){
@@ -107,7 +107,7 @@ describe('res', function(){
.set('Accept', 'text/html')
.expect('Content-Type', /html/)
.expect('Location', '%3Cla\'me%3E')
.expect(302, '<!DOCTYPE html><head><title>Found</title></head><body><p>Found. Redirecting to %3Cla&#39;me%3E</p></body>', done)
.expect(302, '<p>Found. Redirecting to %3Cla&#39;me%3E</p>', done)
})
it('should not render evil javascript links in anchor href (prevent XSS)', function(done){
@@ -125,7 +125,7 @@ describe('res', function(){
.set('Accept', 'text/html')
.expect('Content-Type', /html/)
.expect('Location', encodedXss)
.expect(302, '<!DOCTYPE html><head><title>Found</title></head><body><p>Found. Redirecting to ' + encodedXss +'</p></body>', done);
.expect(302, '<p>Found. Redirecting to ' + encodedXss +'</p>', done);
});
it('should include the redirect type', function(done){
@@ -140,7 +140,7 @@ describe('res', function(){
.set('Accept', 'text/html')
.expect('Content-Type', /html/)
.expect('Location', 'http://google.com')
.expect(301, '<!DOCTYPE html><head><title>Moved Permanently</title></head><body><p>Moved Permanently. Redirecting to http://google.com</p></body>', done);
.expect(301, '<p>Moved Permanently. Redirecting to http://google.com</p>', done);
})
})