Merge tag '4.15.4'

This commit is contained in:
Douglas Christopher Wilson 2017-08-07 17:49:33 -04:00
commit c319fe260a
92 changed files with 495 additions and 266 deletions

11
.editorconfig Normal file
View File

@ -0,0 +1,11 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true
[{*.js,*.json,*.yml}]
indent_size = 2
indent_style = space

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
coverage
node_modules

8
.eslintrc Normal file
View File

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

View File

@ -7,8 +7,8 @@ node_js:
- "3.3" - "3.3"
- "4.8" - "4.8"
- "5.12" - "5.12"
- "6.10" - "6.11"
- "7.6" - "7.10"
matrix: matrix:
include: include:
- node_js: "8.0" - node_js: "8.0"
@ -27,5 +27,7 @@ before_install:
# Update Node.js modules # Update Node.js modules
- "test ! -d node_modules || npm prune" - "test ! -d node_modules || npm prune"
- "test ! -d node_modules || npm rebuild" - "test ! -d node_modules || npm rebuild"
script: "npm run-script test-ci" script:
- "npm run test-ci"
- "npm run lint"
after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls" after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls"

View File

@ -6,7 +6,7 @@ Open issues for the expressjs.com website in https://github.com/expressjs/expres
## PRs and Code contributions ## PRs and Code contributions
* Tests must pass. * Tests must pass.
* Follow the [JavaScript Standard Style](http://standardjs.com/). * Follow the [JavaScript Standard Style](http://standardjs.com/) and `npm run lint`.
* If you fix a bug, add a test. * If you fix a bug, add a test.
## Branches ## Branches
@ -27,7 +27,9 @@ a future release of Express.
each new issue you work on, although not compulsory. each new issue you work on, although not compulsory.
4. To run the test suite, first install the dependencies by running `npm install`, 4. To run the test suite, first install the dependencies by running `npm install`,
then run `npm test`. then run `npm test`.
5. If the tests pass, you can commit your changes to your fork and then create 5. Ensure your code is linted by running `npm run lint` -- fix any issue you
see listed.
6. If the tests pass, you can commit your changes to your fork and then create
a pull request from there. Make sure to reference your issue from the pull a pull request from there. Make sure to reference your issue from the pull
request comments by including the issue number e.g. `#123`. request comments by including the issue number e.g. `#123`.

View File

@ -12,7 +12,7 @@ contributors can be involved in decision making.
* A **Contributor** is any individual creating or commenting on an issue or pull request. * A **Contributor** is any individual creating or commenting on an issue or pull request.
* A **Committer** is a subset of contributors who have been given write access to the repository. * A **Committer** is a subset of contributors who have been given write access to the repository.
* A **TC (Technical Committee)** is a group of committers representing the required technical * A **TC (Technical Committee)** is a group of committers representing the required technical
expertise to resolve rare disputes. expertise to resolve rare disputes.
# Logging Issues # Logging Issues
@ -36,24 +36,24 @@ pull requests.
No pull request can be merged without being reviewed. No pull request can be merged without being reviewed.
For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that
contributors in other timezones have time to review. Consideration should also be given to contributors in other timezones have time to review. Consideration should also be given to
weekends and other holiday periods to ensure active committers all have reasonable time to weekends and other holiday periods to ensure active committers all have reasonable time to
become involved in the discussion and review process if they wish. become involved in the discussion and review process if they wish.
The default for each contribution is that it is accepted once no committer has an objection. The default for each contribution is that it is accepted once no committer has an objection.
During review committers may also request that a specific contributor who is most versed in a During review committers may also request that a specific contributor who is most versed in a
particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off" particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off"
process for contributions to land. Once all issues brought by committers are addressed it can process for contributions to land. Once all issues brought by committers are addressed it can
be landed by any committer. be landed by any committer.
In the case of an objection being raised in a pull request by another committer, all involved In the case of an objection being raised in a pull request by another committer, all involved
committers should seek to arrive at a consensus by way of addressing concerns being expressed committers should seek to arrive at a consensus by way of addressing concerns being expressed
by discussion, compromise on the proposed change, or withdrawal of the proposed change. by discussion, compromise on the proposed change, or withdrawal of the proposed change.
If a contribution is controversial and committers cannot agree about how to get it to land If a contribution is controversial and committers cannot agree about how to get it to land
or if it should land then it should be escalated to the TC. TC members should regularly or if it should land then it should be escalated to the TC. TC members should regularly
discuss pending contributions in order to find a resolution. It is expected that only a discuss pending contributions in order to find a resolution. It is expected that only a
small minority of issues be brought to the TC for resolution and that discussion and small minority of issues be brought to the TC for resolution and that discussion and
compromise among committers be the default resolution mechanism. compromise among committers be the default resolution mechanism.
# Becoming a Committer # Becoming a Committer
@ -66,20 +66,20 @@ proper review, and have other committers merge their pull requests.
# TC Process # TC Process
The TC uses a "consensus seeking" process for issues that are escalated to the TC. The TC uses a "consensus seeking" process for issues that are escalated to the TC.
The group tries to find a resolution that has no open objections among TC members. The group tries to find a resolution that has no open objections among TC members.
If a consensus cannot be reached that has no objections then a majority wins vote If a consensus cannot be reached that has no objections then a majority wins vote
is called. It is also expected that the majority of decisions made by the TC are via is called. It is also expected that the majority of decisions made by the TC are via
a consensus seeking process and that voting is only used as a last-resort. a consensus seeking process and that voting is only used as a last-resort.
Resolution may involve returning the issue to committers with suggestions on how to Resolution may involve returning the issue to committers with suggestions on how to
move forward towards a consensus. It is not expected that a meeting of the TC move forward towards a consensus. It is not expected that a meeting of the TC
will resolve all issues on its agenda during that meeting and may prefer to continue will resolve all issues on its agenda during that meeting and may prefer to continue
the discussion happening among the committers. the discussion happening among the committers.
Members can be added to the TC at any time. Any committer can nominate another committer Members can be added to the TC at any time. Any committer can nominate another committer
to the TC and the TC uses its standard consensus seeking process to evaluate whether or to the TC and the TC uses its standard consensus seeking process to evaluate whether or
not to add this new member. Members who do not participate consistently at the level of not to add this new member. Members who do not participate consistently at the level of
a majority of the other members are expected to resign. a majority of the other members are expected to resign.

View File

@ -1,3 +1,11 @@
5.x
===
This incorporates all changes after 4.15.2 up to 4.15.4.
* deps: router@~1.3.1
- deps: debug@2.6.8
5.0.0-alpha.5 / 2017-03-06 5.0.0-alpha.5 / 2017-03-06
========================== ==========================
@ -76,6 +84,47 @@ This is the first Express 5.0 alpha release, based off 4.10.1.
* add: * add:
- `app.router` is a reference to the base router - `app.router` is a reference to the base router
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 4.15.2 / 2017-03-06
=================== ===================

View File

@ -39,15 +39,14 @@ $ npm install express
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)]
* [#express](https://webchat.freenode.net/?channels=express) on freenode IRC * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
* [Github Organization](https://github.com/expressjs) for Official Middleware & Modules * [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/expressjs/express/wiki) * Visit the [Wiki](https://github.com/expressjs/express/wiki)
* [Google Group](https://groups.google.com/group/express-js) for discussion * [Google Group](https://groups.google.com/group/express-js) for discussion
* [Gitter](https://gitter.im/expressjs/express) for support and discussion * [Gitter](https://gitter.im/expressjs/express) for support and discussion
* [Русскоязычная документация](http://jsman.ru/express/)
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x).
###Security Issues ### Security Issues
If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).

View File

@ -7,8 +7,8 @@ environment:
- nodejs_version: "3.3" - nodejs_version: "3.3"
- nodejs_version: "4.8" - nodejs_version: "4.8"
- nodejs_version: "5.12" - nodejs_version: "5.12"
- nodejs_version: "6.10" - nodejs_version: "6.11"
- nodejs_version: "7.6" - nodejs_version: "7.10"
cache: cache:
- node_modules - node_modules
install: install:
@ -22,4 +22,5 @@ test_script:
- node --version - node --version
- npm --version - npm --version
- npm run test-ci - npm run test-ci
- npm run lint
version: "{build}" version: "{build}"

View File

@ -1,5 +1,4 @@
var http = require('http');
var express = require('..'); var express = require('..');
var app = express(); var app = express();

View File

@ -4,4 +4,4 @@ users.push({ name: 'Tobi' });
users.push({ name: 'Loki' }); users.push({ name: 'Loki' });
users.push({ name: 'Jane' }); users.push({ name: 'Jane' });
module.exports = users; module.exports = users;

View File

@ -15,9 +15,8 @@ app.use(count);
// custom middleware // custom middleware
function count(req, res) { function count(req, res) {
req.session.count = req.session.count || 0; req.session.count = (req.session.count || 0) + 1
var n = req.session.count++; res.send('viewed ' + req.session.count + ' times\n')
res.send('viewed ' + n + ' times\n');
} }
/* istanbul ignore next */ /* istanbul ignore next */

View File

@ -26,7 +26,7 @@ app.set('views', path.join(__dirname, 'views'));
// Path to our public directory // Path to our public directory
app.use(express.static(path.join(__dirname + 'public'))); app.use(express.static(path.join(__dirname, 'public')));
// Without this you would need to // Without this you would need to
// supply the extension to res.render() // supply the extension to res.render()

View File

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

View File

@ -4,6 +4,8 @@
var db = require('../../db'); var db = require('../../db');
exports.engine = 'hbs';
exports.before = function(req, res, next){ exports.before = function(req, res, next){
var id = req.params.user_id; var id = req.params.user_id;
if (!id) return next(); if (!id) return next();

View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<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>

View File

@ -1,11 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1= user.name
form(action='/user/#{user.id}?_method=put', method='post')
label= 'Name: '
input(type='text', name='user[name]', value='#{user.name}')
input(type='submit', value='Update')
form(action='/user/#{user.id}/pet', method='post')
label= 'Pet: '
input(type='text', name='pet[name]', placeholder='Name')
input(type='submit', value='Add')

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<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>

View File

@ -1,7 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1 Users
p Click a user below to view their pets.
ul
each user in users
li
a(href='/user/#{user.id}')= user.name

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<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>

View File

@ -1,17 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1= user.name + ' '
a(href='/user/#{user.id}/edit') edit
if (hasMessages)
ul#messages
each msg in messages
li= msg
if (user.pets.length)
p View #{user.name}'s pets:
ul
each pet in user.pets
li
a(href='/pet/#{pet.id}')= pet.name
else
p No pets!

View File

@ -11,4 +11,4 @@ var users = exports.users = [];
users.push({ name: 'TJ', pets: [pets[0], pets[1], pets[2]], id: 0 }); 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: 'Guillermo', pets: [pets[3]], id: 1 });
users.push({ name: 'Nathan', pets: [], id: 2 }); users.push({ name: 'Nathan', pets: [], id: 2 });

View File

@ -11,11 +11,9 @@ var methodOverride = require('method-override');
var app = module.exports = express(); var app = module.exports = express();
// settings // set our default template engine to "ejs"
// which prevents the need for using file extensions
// set our default template engine to "jade" app.set('view engine', 'ejs');
// which prevents the need for extensions
app.set('view engine', 'jade');
// set views for error and 404 pages // set views for error and 404 pages
app.set('views', path.join(__dirname, 'views')); app.set('views', path.join(__dirname, 'views'));

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<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>

View File

@ -1,3 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1 404: Not Found
p Sorry we can't find #{url}

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<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>

View File

@ -1,3 +0,0 @@
link(rel='stylesheet', href='/style.css')
h1 500: Internal Server Error
p Looks like something blew up!

View File

@ -1,4 +1,8 @@
// first:
// install redis first:
// https://redis.io/
// then:
// $ npm install redis online // $ npm install redis online
// $ redis-server // $ redis-server

View File

@ -68,7 +68,7 @@ app.get('/users/:from-:to', function(req, res, next){
var from = req.params.from; var from = req.params.from;
var to = req.params.to; var to = req.params.to;
var names = users.map(function(user){ return user.name; }); var names = users.map(function(user){ return user.name; });
res.send('users ' + names.slice(from, to).join(', ')); res.send('users ' + names.slice(from, to + 1).join(', '));
}); });
/* istanbul ignore next */ /* istanbul ignore next */

View File

@ -75,7 +75,7 @@ app.resource('/users', User);
app.get('/', function(req, res){ app.get('/', function(req, res){
res.send([ res.send([
'<h1>Examples:</h1> <ul>' '<h1>Examples:</h1> <ul>'
, '<li>GET /users</li>' , '<li>GET /users</li>'
, '<li>GET /users/1</li>' , '<li>GET /users/1</li>'
, '<li>GET /users/3</li>' , '<li>GET /users/3</li>'

View File

@ -17,7 +17,7 @@ module.exports = app;
// Config // Config
app.set('view engine', 'jade'); app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views')); app.set('views', path.join(__dirname, 'views'));
/* istanbul ignore next */ /* istanbul ignore next */

View File

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

View File

@ -0,0 +1,2 @@
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><%= title %></title>
<link rel="stylesheet" href="/style.css">
</head>
<body>

View File

@ -0,0 +1,10 @@
<% include header %>
<h1><%= title %></h1>
<ul>
<li>Visit the <a href="/users">users</a> page.</li>
<li>Visit the <a href="/posts">posts</a> page.</li>
</ul>
<% include footer %>

View File

@ -1,6 +0,0 @@
extends layout
block content
ul
li Visit the <a href="/users">users</a> page
li Visit the <a href="/posts">posts</a> page

View File

@ -1,6 +0,0 @@
html
head
title= title
link(href="/style.css", rel="stylesheet")
body
block content

View File

@ -0,0 +1,12 @@
<% include ../header %>
<h1>Posts</h1>
<dl id="posts">
<% posts.forEach(function(post) { %>
<dt><%= post.title %></dt>
<dd><%= post.body %></dd>
<% }) %>
</dl>
<% include ../footer %>

View File

@ -1,8 +0,0 @@
extends ../layout
block content
h1 Posts
dl#posts
for post in posts
dt= post.title
dd= post.body

View File

@ -0,0 +1,23 @@
<% include ../header %>
<h1>Editing <%= user.name %></h1>
<div id="user">
<form action="?_method=put", method="post">
<p>
Name:
<input type="text" value="<%= user.name %>" name="user[name]" />
</p>
<p>
Email:
<input type="email" value="<%= user.email %>" name="user[email]" />
</p>
<p>
<input type="submit" value="Save" />
</p>
</form>
</div>
<% include ../footer %>

View File

@ -1,12 +0,0 @@
extends ../layout
block content
h1 Editing #{user.name}
#user
form(action="?_method=put", method="post")
p Name:
input(type="text", value= user.name, name="user[name]")
p Email:
input(type="text", value= user.email, name="user[email]")
p
input(type="submit", value="Save")

View File

@ -0,0 +1,14 @@
<% include ../header %>
<h1><%= title %></h1>
<div id="users">
<% users.forEach(function(user, index) { %>
<li>
<a href="/user/<%= index %>"><%= user.name %></a>
<a href="/user/<%= index %>/edit">edit</a>
</li>
<% }) %>
</div>
<% include ../footer %>

View File

@ -1,9 +0,0 @@
extends ../layout
block content
h1 Users
#users
for user, i in users
li
a(href="/user/#{i}")= user.name
a.edit(href="/user/#{i}/edit") edit

View File

@ -0,0 +1,9 @@
<% include ../header %>
<h1><%= user.name %></h1>
<div id="user">
<p>Email: <%= user.email %></p>
</div>
<% include ../footer %>

View File

@ -1,6 +0,0 @@
extends ../layout
block content
h1= user.name
#user
p Email: #{user.email}

View File

@ -1,4 +1,8 @@
// first:
// install redis first:
// https://redis.io/
// then:
// $ npm install redis // $ npm install redis
// $ redis-server // $ redis-server

View File

@ -10,4 +10,4 @@ search.addEventListener('keyup', function(){
} }
}; };
xhr.send(); xhr.send();
}, false); }, false);

View File

@ -1,4 +1,8 @@
// first:
// install redis first:
// https://redis.io/
// then:
// $ npm install redis // $ npm install redis
// $ redis-server // $ redis-server

View File

@ -1 +1 @@
foo foo

View File

@ -2,7 +2,7 @@
* Module dependencies. * Module dependencies.
*/ */
var http = require('http'); var https = require('https');
var path = require('path'); var path = require('path');
var extname = path.extname; var extname = path.extname;

View File

@ -3,7 +3,6 @@
*/ */
var express = require('../../'); var express = require('../../');
var http = require('http');
var GithubView = require('./github-view'); var GithubView = require('./github-view');
var md = require('marked').parse; var md = require('marked').parse;

View File

@ -3,11 +3,12 @@
*/ */
var express = require('../..'); var express = require('../..');
var path = require('path');
var User = require('./user'); var User = require('./user');
var app = express(); var app = express();
app.set('views', __dirname); app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade'); app.set('view engine', 'ejs');
// filter ferrets only // filter ferrets only
@ -25,7 +26,7 @@ app.get('/', function(req, res, next){
if (err) return next(err); if (err) return next(err);
User.all(function(err, users){ User.all(function(err, users){
if (err) return next(err); if (err) return next(err);
res.render('user', { res.render('index', {
title: 'Users', title: 'Users',
count: count, count: count,
users: users.filter(ferrets) users: users.filter(ferrets)
@ -59,7 +60,7 @@ function users(req, res, next) {
} }
app.get('/middleware', count, users, function(req, res, next){ app.get('/middleware', count, users, function(req, res, next){
res.render('user', { res.render('index', {
title: 'Users', title: 'Users',
count: req.count, count: req.count,
users: req.users.filter(ferrets) users: req.users.filter(ferrets)
@ -101,7 +102,7 @@ app.get('/middleware-locals', count2, users2, function(req, res, next){
// to pass to res.render(). If we have // to pass to res.render(). If we have
// several routes related to users this // several routes related to users this
// can be a great productivity booster // can be a great productivity booster
res.render('user', { title: 'Users' }); res.render('index', { title: 'Users' });
}); });
// keep in mind that middleware may be placed anywhere // keep in mind that middleware may be placed anywhere

View File

@ -1,12 +0,0 @@
doctype html
html
head
title= title
style.
body {
padding: 50px;
font: 16px Helvetica, Arial;
}
body
h2= title
block content

View File

@ -1,8 +0,0 @@
extends layout
block content
for user in users
.user
h3= user.name
p #{user.name} is a #{user.age} year old #{user.species}.

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= title %></title>
<style media="screen">
body {
padding: 50px;
font: 16px Helvetica, Arial;
}
</style>
</head>
<body>
<h2><%= title %></h2>
<% users.forEach(function(user) { %>
<li><strong><%= user.name %></strong> is a <% user.age %> year old <%= user.species %></li>
<% }); %>
</body>
</html>

View File

@ -61,7 +61,7 @@ var users = [
]; ];
var userRepos = { var userRepos = {
tobi: [repos[0], repos[1]] tobi: [repos[0], repos[1]]
, loki: [repos[1]] , loki: [repos[1]]
, jane: [repos[2]] , jane: [repos[2]]
}; };

View File

@ -25,7 +25,7 @@ var flatten = require('array-flatten');
var merge = require('utils-merge'); var merge = require('utils-merge');
var resolve = require('path').resolve; var resolve = require('path').resolve;
var Router = require('router'); var Router = require('router');
var setPrototyeOf = require('setprototypeof') var setPrototypeOf = require('setprototypeof')
var slice = Array.prototype.slice; var slice = Array.prototype.slice;
/** /**
@ -110,10 +110,10 @@ app.defaultConfiguration = function defaultConfiguration() {
} }
// inherit protos // inherit protos
setPrototyeOf(this.request, parent.request) setPrototypeOf(this.request, parent.request)
setPrototyeOf(this.response, parent.response) setPrototypeOf(this.response, parent.response)
setPrototyeOf(this.engines, parent.engines) setPrototypeOf(this.engines, parent.engines)
setPrototyeOf(this.settings, parent.settings) setPrototypeOf(this.settings, parent.settings)
}); });
// setup locals // setup locals
@ -161,8 +161,8 @@ app.handle = function handle(req, res, callback) {
res.req = req; res.req = req;
// alter the prototypes // alter the prototypes
setPrototyeOf(req, this.request) setPrototypeOf(req, this.request)
setPrototyeOf(res, this.response) setPrototypeOf(res, this.response)
// setup locals // setup locals
if (!res.locals) { if (!res.locals) {
@ -225,8 +225,8 @@ app.use = function use(fn) {
router.use(path, function mounted_app(req, res, next) { router.use(path, function mounted_app(req, res, next) {
var orig = req.app; var orig = req.app;
fn.handle(req, res, function (err) { fn.handle(req, res, function (err) {
setPrototyeOf(req, orig.request) setPrototypeOf(req, orig.request)
setPrototyeOf(res, orig.response) setPrototypeOf(res, orig.response)
next(err); next(err);
}); });
}); });

View File

@ -597,9 +597,14 @@ res.header = function header(field, val) {
: String(val); : String(val);
// add charset to content-type // add charset to content-type
if (field.toLowerCase() === 'content-type' && !charsetRegExp.test(value)) { if (field.toLowerCase() === 'content-type') {
var charset = mime.charsets.lookup(value.split(';')[0]); if (Array.isArray(value)) {
if (charset) value += '; charset=' + charset.toLowerCase(); throw new TypeError('Content-Type cannot be set to an Array');
}
if (!charsetRegExp.test(value)) {
var charset = mime.charsets.lookup(value.split(';')[0]);
if (charset) value += '; charset=' + charset.toLowerCase();
}
} }
this.setHeader(field, value); this.setHeader(field, value);
@ -657,7 +662,7 @@ res.clearCookie = function clearCookie(name, options) {
* *
* @param {String} name * @param {String} name
* @param {String|Object} value * @param {String|Object} value
* @param {Options} options * @param {Object} [options]
* @return {ServerResponse} for chaining * @return {ServerResponse} for chaining
* @public * @public
*/ */

View File

@ -15,7 +15,6 @@
var mime = require('send').mime; var mime = require('send').mime;
var contentType = require('content-type'); var contentType = require('content-type');
var etag = require('etag'); var etag = require('etag');
var flatten = require('array-flatten');
var proxyaddr = require('proxy-addr'); var proxyaddr = require('proxy-addr');
var qs = require('qs'); var qs = require('qs');
var querystring = require('querystring'); var querystring = require('querystring');

View File

@ -16,7 +16,6 @@
var debug = require('debug')('express:view'); var debug = require('debug')('express:view');
var path = require('path'); var path = require('path');
var fs = require('fs'); var fs = require('fs');
var utils = require('./utils');
/** /**
* Module variables. * Module variables.

View File

@ -33,12 +33,12 @@
"content-type": "~1.0.2", "content-type": "~1.0.2",
"cookie": "0.3.1", "cookie": "0.3.1",
"cookie-signature": "1.0.6", "cookie-signature": "1.0.6",
"debug": "2.6.1", "debug": "2.6.8",
"depd": "~1.1.0", "depd": "~1.1.1",
"encodeurl": "~1.0.1", "encodeurl": "~1.0.1",
"escape-html": "~1.0.3", "escape-html": "~1.0.3",
"etag": "~1.8.0", "etag": "~1.8.0",
"finalhandler": "~1.0.0", "finalhandler": "~1.0.4",
"fresh": "0.5.0", "fresh": "0.5.0",
"merge-descriptors": "1.0.1", "merge-descriptors": "1.0.1",
"methods": "~1.1.2", "methods": "~1.1.2",
@ -46,36 +46,37 @@
"parseurl": "~1.3.1", "parseurl": "~1.3.1",
"path-is-absolute": "1.0.1", "path-is-absolute": "1.0.1",
"path-to-regexp": "0.1.7", "path-to-regexp": "0.1.7",
"proxy-addr": "~1.1.3", "proxy-addr": "~1.1.5",
"qs": "6.4.0", "qs": "6.5.0",
"range-parser": "~1.2.0", "range-parser": "~1.2.0",
"router": "~1.3.0", "router": "~1.3.1",
"send": "0.15.1", "send": "0.15.4",
"serve-static": "1.12.1", "serve-static": "1.12.4",
"setprototypeof": "1.0.3", "setprototypeof": "1.0.3",
"statuses": "~1.3.1", "statuses": "~1.3.1",
"type-is": "~1.6.14", "type-is": "~1.6.15",
"utils-merge": "1.0.0", "utils-merge": "1.0.0",
"vary": "~1.1.0" "vary": "~1.1.1"
}, },
"devDependencies": { "devDependencies": {
"after": "0.8.2", "after": "0.8.2",
"body-parser": "1.17.1", "body-parser": "1.17.2",
"cookie-parser": "~1.4.3", "cookie-parser": "~1.4.3",
"ejs": "2.5.6", "cookie-session": "1.3.0",
"express-session": "1.15.1", "ejs": "2.5.7",
"eslint": "2.13.1",
"express-session": "1.15.5",
"hbs": "4.0.1",
"istanbul": "0.4.5", "istanbul": "0.4.5",
"marked": "0.3.6", "marked": "0.3.6",
"method-override": "2.3.7", "method-override": "2.3.9",
"mocha": "3.2.0", "mocha": "3.5.0",
"morgan": "1.8.1", "morgan": "1.8.2",
"multiparty": "4.1.3", "multiparty": "4.1.3",
"pbkdf2-password": "1.2.1", "pbkdf2-password": "1.2.1",
"should": "11.2.0", "should": "11.2.1",
"supertest": "1.2.0", "supertest": "1.2.0",
"connect-redis": "~2.4.1", "connect-redis": "~2.4.1",
"cookie-session": "~1.2.0",
"jade": "~1.11.0",
"vhost": "~3.0.2" "vhost": "~3.0.2"
}, },
"engines": { "engines": {
@ -89,6 +90,7 @@
"lib/" "lib/"
], ],
"scripts": { "scripts": {
"lint": "eslint .",
"test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/", "test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/", "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/", "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",

View File

@ -4,7 +4,6 @@ var should = require('should');
var express = require('../') var express = require('../')
, Route = express.Route , Route = express.Route
, methods = require('methods') , methods = require('methods')
, assert = require('assert');
describe('Route', function(){ describe('Route', function(){
it('should work without handlers', function(done) { it('should work without handlers', function(done) {
@ -25,7 +24,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) { route.dispatch(req, {}, function (err) {
if (err) return done(err); if (err) return done(err);
should(req.called).be.ok; should(req.called).be.ok()
done(); done();
}); });
}) })
@ -84,7 +83,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) { route.dispatch(req, {}, function (err) {
if (err) return done(err); if (err) return done(err);
should(req.called).be.ok; should(req.called).be.ok()
done(); done();
}); });
}) })
@ -104,7 +103,7 @@ describe('Route', function(){
route.dispatch(req, {}, function (err) { route.dispatch(req, {}, function (err) {
if (err) return done(err); if (err) return done(err);
should(req.called).be.true; should(req.called).be.true()
done(); done();
}); });
}) })
@ -156,7 +155,7 @@ describe('Route', function(){
}); });
route.dispatch(req, {}, function (err) { route.dispatch(req, {}, function (err) {
should(err).be.ok; should(err).be.ok()
should(err.message).equal('foobar'); should(err.message).equal('foobar');
req.order.should.equal('a'); req.order.should.equal('a');
done(); done();
@ -182,7 +181,7 @@ describe('Route', function(){
}); });
route.dispatch(req, {}, function (err) { route.dispatch(req, {}, function (err) {
should(err).be.ok; should(err).be.ok()
should(err.message).equal('foobar'); should(err.message).equal('foobar');
req.order.should.equal('a'); req.order.should.equal('a');
done(); done();
@ -222,7 +221,7 @@ describe('Route', function(){
}); });
route.dispatch(req, {}, function(err){ route.dispatch(req, {}, function(err){
should(err).be.ok; should(err).be.ok()
err.message.should.equal('boom!'); err.message.should.equal('boom!');
done(); done();
}); });
@ -234,7 +233,7 @@ describe('Route', function(){
route.all(function(err, req, res, next){ route.all(function(err, req, res, next){
// this should not execute // this should not execute
true.should.be.false; true.should.be.false()
}); });
route.dispatch(req, {}, done); route.dispatch(req, {}, done);

View File

@ -47,7 +47,7 @@ describe('Router', function(){
var router = new Router(); var router = new Router();
router.use(function (req, res) { router.use(function (req, res) {
false.should.be.true; false.should.be.true()
}); });
router.handle({ url: '', method: 'GET' }, {}, done); router.handle({ url: '', method: 'GET' }, {}, done);

View File

@ -7,7 +7,7 @@ describe('cookie-sessions', function () {
it('should display no views', function (done) { it('should display no views', function (done) {
request(app) request(app)
.get('/') .get('/')
.expect(200, 'viewed 0 times\n', done) .expect(200, 'viewed 1 times\n', done)
}) })
it('should set a session cookie', function (done) { it('should set a session cookie', function (done) {
@ -20,12 +20,12 @@ describe('cookie-sessions', function () {
it('should display 1 view on revisit', function (done) { it('should display 1 view on revisit', function (done) {
request(app) request(app)
.get('/') .get('/')
.expect(200, 'viewed 0 times\n', function (err, res) { .expect(200, 'viewed 1 times\n', function (err, res) {
if (err) return done(err) if (err) return done(err)
request(app) request(app)
.get('/') .get('/')
.set('Cookie', getCookies(res)) .set('Cookie', getCookies(res))
.expect(200, 'viewed 1 times\n', done) .expect(200, 'viewed 2 times\n', done)
}) })
}) })
}) })

View File

@ -99,4 +99,4 @@ describe('error-pages', function(){
}) })
}) })
}) })
}) })

View File

@ -26,4 +26,4 @@ describe('error', function(){
.expect(404,done) .expect(404,done)
}) })
}) })
}) })

View File

@ -29,8 +29,8 @@ describe('params', function(){
describe('GET /users/0-2', function(){ describe('GET /users/0-2', function(){
it('should respond with three users', function(done){ it('should respond with three users', function(done){
request(app) request(app)
.get('/users/0-2') .get('/users/0-2')
.expect(/users tj, tobi/,done) .expect(/users tj, tobi, loki/, done)
}) })
}) })

View File

@ -42,4 +42,4 @@ describe('route-map', function(){
.expect('delete 12\'s pet 2', done); .expect('delete 12\'s pet 2', done);
}) })
}) })
}) })

View File

@ -47,7 +47,7 @@ describe('app', function(){
done(); done();
}) })
}) })
it('should work "view engine" setting', function(done){ it('should work "view engine" setting', function(done){
var app = express(); var app = express();
@ -62,7 +62,7 @@ describe('app', function(){
done(); done();
}) })
}) })
it('should work "view engine" with leading "."', function(done){ it('should work "view engine" with leading "."', function(done){
var app = express(); var app = express();

View File

@ -74,7 +74,7 @@ describe('in development', function(){
it('should disable "view cache"', function(){ it('should disable "view cache"', function(){
process.env.NODE_ENV = 'development'; process.env.NODE_ENV = 'development';
var app = express(); var app = express();
app.enabled('view cache').should.be.false; app.enabled('view cache').should.be.false()
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
}) })
}) })
@ -83,7 +83,7 @@ describe('in production', function(){
it('should enable "view cache"', function(){ it('should enable "view cache"', function(){
process.env.NODE_ENV = 'production'; process.env.NODE_ENV = 'production';
var app = express(); var app = express();
app.enabled('view cache').should.be.true; app.enabled('view cache').should.be.true()
process.env.NODE_ENV = 'test'; process.env.NODE_ENV = 'test';
}) })
}) })

View File

@ -1,6 +1,5 @@
var express = require('../') var express = require('../')
, request = require('supertest');
describe('app.listen()', function(){ describe('app.listen()', function(){
it('should wrap with an HTTP server', function(done){ it('should wrap with an HTTP server', function(done){

View File

@ -1,6 +1,5 @@
var express = require('../') var express = require('../')
, request = require('supertest');
describe('app', function(){ describe('app', function(){
describe('.locals(obj)', function(){ describe('.locals(obj)', function(){

View File

@ -16,13 +16,13 @@ describe('app', function(){
app.get('/post/:id', function(req, res){ app.get('/post/:id', function(req, res){
var id = req.params.id; var id = req.params.id;
id.should.be.a.Number; id.should.be.a.Number()
res.send('' + id); res.send('' + id);
}); });
app.get('/user/:uid', function(req, res){ app.get('/user/:uid', function(req, res){
var id = req.params.id; var id = req.params.id;
id.should.be.a.Number; id.should.be.a.Number()
res.send('' + id); res.send('' + id);
}); });
@ -50,7 +50,7 @@ describe('app', function(){
app.get('/user/:id', function(req, res){ app.get('/user/:id', function(req, res){
var id = req.params.id; var id = req.params.id;
id.should.be.a.Number; id.should.be.a.Number()
res.send('' + id); res.send('' + id);
}); });

View File

@ -72,7 +72,7 @@ describe('app', function(){
app.set('view', View); app.set('view', View);
app.render('something', function(err, str){ app.render('something', function(err, str){
err.should.be.ok; err.should.be.ok()
err.message.should.equal('err!'); err.message.should.equal('err!');
done(); done();
}) })

View File

@ -39,7 +39,6 @@ describe('app.router', function(){
it('should include ' + method.toUpperCase(), function(done){ it('should include ' + method.toUpperCase(), function(done){
var app = express(); var app = express();
var calls = [];
app[method]('/foo', function(req, res){ app[method]('/foo', function(req, res){
if ('head' == method) { if ('head' == method) {

View File

@ -44,10 +44,10 @@ describe('app', function(){
d = true; d = true;
next(); next();
}, function(req, res){ }, function(req, res){
a.should.be.false; a.should.be.false()
b.should.be.true; b.should.be.true()
c.should.be.true; c.should.be.true()
d.should.be.false; d.should.be.false()
res.sendStatus(204); res.sendStatus(204);
}); });

View File

@ -49,7 +49,7 @@ describe('config', function () {
var app = express(); var app = express();
assert.strictEqual(app.get('foo'), undefined); assert.strictEqual(app.get('foo'), undefined);
}) })
it('should otherwise return the value', function(){ it('should otherwise return the value', function(){
var app = express(); var app = express();
app.set('foo', 'bar'); app.set('foo', 'bar');
@ -125,7 +125,7 @@ describe('config', function () {
assert.strictEqual(app.get('tobi'), true); assert.strictEqual(app.get('tobi'), true);
}) })
}) })
describe('.disable()', function(){ describe('.disable()', function(){
it('should set the value to false', function(){ it('should set the value to false', function(){
var app = express(); var app = express();
@ -133,26 +133,26 @@ describe('config', function () {
assert.strictEqual(app.get('tobi'), false); assert.strictEqual(app.get('tobi'), false);
}) })
}) })
describe('.enabled()', function(){ describe('.enabled()', function(){
it('should default to false', function(){ it('should default to false', function(){
var app = express(); var app = express();
assert.strictEqual(app.enabled('foo'), false); assert.strictEqual(app.enabled('foo'), false);
}) })
it('should return true when set', function(){ it('should return true when set', function(){
var app = express(); var app = express();
app.set('foo', 'bar'); app.set('foo', 'bar');
assert.strictEqual(app.enabled('foo'), true); assert.strictEqual(app.enabled('foo'), true);
}) })
}) })
describe('.disabled()', function(){ describe('.disabled()', function(){
it('should default to true', function(){ it('should default to true', function(){
var app = express(); var app = express();
assert.strictEqual(app.disabled('foo'), true); assert.strictEqual(app.disabled('foo'), true);
}) })
it('should return false when set', function(){ it('should return false when set', function(){
var app = express(); var app = express();
app.set('foo', 'bar'); app.set('foo', 'bar');

View File

@ -1,23 +1,22 @@
var express = require('../'); var express = require('../');
var request = require('supertest'); var request = require('supertest');
var should = require('should');
describe('exports', function(){ describe('exports', function(){
it('should expose Router', function(){ it('should expose Router', function(){
express.Router.should.be.a.Function; express.Router.should.be.a.Function()
}) })
it('should expose the application prototype', function(){ it('should expose the application prototype', function(){
express.application.set.should.be.a.Function; express.application.set.should.be.a.Function()
}) })
it('should expose the request prototype', function(){ it('should expose the request prototype', function(){
express.request.accepts.should.be.a.Function; express.request.accepts.should.be.a.Function()
}) })
it('should expose the response prototype', function(){ it('should expose the response prototype', function(){
express.response.send.should.be.a.Function; express.response.send.should.be.a.Function()
}) })
it('should permit modifying the .application prototype', function(){ it('should permit modifying the .application prototype', function(){

View File

@ -8,8 +8,8 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.acceptsEncodings('gzip').should.be.ok; req.acceptsEncodings('gzip').should.be.ok()
req.acceptsEncodings('deflate').should.be.ok; req.acceptsEncodings('deflate').should.be.ok()
res.end(); res.end();
}); });
@ -23,7 +23,7 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.acceptsEncodings('bogus').should.not.be.ok; req.acceptsEncodings('bogus').should.not.be.ok()
res.end(); res.end();
}); });

View File

@ -8,8 +8,8 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.acceptsLanguages('en-us').should.be.ok; req.acceptsLanguages('en-us').should.be.ok()
req.acceptsLanguages('en').should.be.ok; req.acceptsLanguages('en').should.be.ok()
res.end(); res.end();
}); });
@ -23,7 +23,7 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.acceptsLanguages('es').should.not.be.ok; req.acceptsLanguages('es').should.not.be.ok()
res.end(); res.end();
}); });
@ -38,9 +38,9 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.acceptsLanguages('en').should.be.ok; req.acceptsLanguages('en').should.be.ok()
req.acceptsLanguages('es').should.be.ok; req.acceptsLanguages('es').should.be.ok()
req.acceptsLanguages('jp').should.be.ok; req.acceptsLanguages('jp').should.be.ok()
res.end(); res.end();
}); });

View File

@ -1,7 +1,6 @@
var express = require('../') var express = require('../')
, request = require('supertest') , request = require('supertest')
, assert = require('assert');
describe('req', function(){ describe('req', function(){
describe('.host', function(){ describe('.host', function(){

View File

@ -1,7 +1,6 @@
var express = require('../') var express = require('../')
, request = require('supertest') , request = require('supertest')
, assert = require('assert');
describe('req', function(){ describe('req', function(){
describe('.hostname', function(){ describe('.hostname', function(){

View File

@ -1,5 +1,4 @@
var assert = require('assert');
var express = require('..'); var express = require('..');
var request = require('supertest') var request = require('supertest')

View File

@ -8,7 +8,7 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.xhr.should.be.true; req.xhr.should.be.true()
res.end(); res.end();
}); });
@ -25,7 +25,7 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.xhr.should.be.true; req.xhr.should.be.true()
res.end(); res.end();
}); });
@ -42,7 +42,7 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.xhr.should.be.false; req.xhr.should.be.false()
res.end(); res.end();
}); });
@ -59,7 +59,7 @@ describe('req', function(){
var app = express(); var app = express();
app.use(function(req, res){ app.use(function(req, res){
req.xhr.should.be.false; req.xhr.should.be.false()
res.end(); res.end();
}); });

View File

@ -89,7 +89,6 @@ describe('res', function(){
it('should remove Content-Disposition', function(done){ it('should remove Content-Disposition', function(done){
var app = express() var app = express()
, calls = 0;
app.use(function (req, res, next) { app.use(function (req, res, next) {
res.download('test/fixtures/foobar.html', function(err){ res.download('test/fixtures/foobar.html', function(err){

View File

@ -1,7 +1,6 @@
var express = require('../') var express = require('../')
, request = require('supertest') , request = require('supertest')
, utils = require('../lib/utils')
, assert = require('assert'); , assert = require('assert');
var app1 = express(); var app1 = express();

View File

@ -42,5 +42,63 @@ describe('res', function(){
.expect('Location', 'https://google.com?q=%A710') .expect('Location', 'https://google.com?q=%A710')
.expect(200, done) .expect(200, done)
}) })
describe('when url is "back"', function () {
it('should set location from "Referer" header', function (done) {
var app = express()
app.use(function (req, res) {
res.location('back').end()
})
request(app)
.get('/')
.set('Referer', '/some/page.html')
.expect('Location', '/some/page.html')
.expect(200, done)
})
it('should set location from "Referrer" header', function (done) {
var app = express()
app.use(function (req, res) {
res.location('back').end()
})
request(app)
.get('/')
.set('Referrer', '/some/page.html')
.expect('Location', '/some/page.html')
.expect(200, done)
})
it('should prefer "Referrer" header', function (done) {
var app = express()
app.use(function (req, res) {
res.location('back').end()
})
request(app)
.get('/')
.set('Referer', '/some/page1.html')
.set('Referrer', '/some/page2.html')
.expect('Location', '/some/page2.html')
.expect(200, done)
})
it('should set the header to "/" without referrer', function (done) {
var app = express()
app.use(function (req, res) {
res.location('back').end()
})
request(app)
.get('/')
.expect('Location', '/')
.expect(200, done)
})
})
}) })
}) })

View File

@ -1,5 +1,4 @@
var assert = require('assert');
var express = require('..'); var express = require('..');
var methods = require('methods'); var methods = require('methods');
var request = require('supertest'); var request = require('supertest');

View File

@ -2,7 +2,6 @@
var after = require('after'); var after = require('after');
var express = require('../') var express = require('../')
, request = require('supertest') , request = require('supertest')
, assert = require('assert');
var onFinished = require('on-finished'); var onFinished = require('on-finished');
var path = require('path'); var path = require('path');
var should = require('should'); var should = require('should');
@ -108,7 +107,7 @@ describe('res', function(){
}); });
app.use(function (err, req, res, next) { app.use(function (err, req, res, next) {
err.code.should.be.empty; err.code.should.be.empty()
cb(); cb();
}); });
@ -224,7 +223,7 @@ describe('res', function(){
app.use(function (req, res) { app.use(function (req, res) {
setImmediate(function () { setImmediate(function () {
res.sendFile(path.resolve(fixtures, 'name.txt'), function (err) { res.sendFile(path.resolve(fixtures, 'name.txt'), function (err) {
should(err).be.ok; should(err).be.ok()
err.code.should.equal('ECONNABORTED'); err.code.should.equal('ECONNABORTED');
cb(); cb();
}); });
@ -243,7 +242,7 @@ describe('res', function(){
app.use(function (req, res) { app.use(function (req, res) {
onFinished(res, function () { onFinished(res, function () {
res.sendFile(path.resolve(fixtures, 'name.txt'), function (err) { res.sendFile(path.resolve(fixtures, 'name.txt'), function (err) {
should(err).be.ok; should(err).be.ok()
err.code.should.equal('ECONNABORTED'); err.code.should.equal('ECONNABORTED');
cb(); cb();
}); });
@ -294,7 +293,7 @@ describe('res', function(){
app.use(function (req, res) { app.use(function (req, res) {
res.sendFile(path.resolve(fixtures, 'does-not-exist'), function (err) { res.sendFile(path.resolve(fixtures, 'does-not-exist'), function (err) {
should(err).be.ok; should(err).be.ok()
err.status.should.equal(404); err.status.should.equal(404);
res.send('got it'); res.send('got it');
}); });

View File

@ -1,5 +1,4 @@
var assert = require('assert')
var express = require('..') var express = require('..')
var request = require('supertest') var request = require('supertest')

View File

@ -73,6 +73,19 @@ describe('res', function(){
.expect('Content-Type', 'text/html; charset=lol') .expect('Content-Type', 'text/html; charset=lol')
.expect(200, done); .expect(200, done);
}) })
it('should throw when Content-Type is an array', function (done) {
var app = express()
app.use(function (req, res) {
res.set('Content-Type', ['text/html'])
res.end()
});
request(app)
.get('/')
.expect(500, /TypeError: Content-Type cannot be set to an Array/, done)
})
}) })
describe('.set(object)', function(){ describe('.set(object)', function(){

View File

@ -1,5 +1,4 @@
var assert = require('assert');
var express = require('..'); var express = require('..');
var request = require('supertest'); var request = require('supertest');
var utils = require('./support/utils'); var utils = require('./support/utils');