Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Do not enforce header value type

Fixes #35
  • Loading branch information...
commit 5b9b0a9f81c670aea4950f92ed37b0f23ed11804 1 parent 4b06f41
@mjackson authored
View
4 CHANGES
@@ -1,3 +1,7 @@
+= HEAD
+
+ * Do not enforce header value type in the lint middleware.
+
= 0.18.0 / 2012-10-07
* The input stream is paused by default.
View
3  SPEC
@@ -96,7 +96,8 @@ The headers must be an object whose properties are the names of HTTP headers in
their canonical form (i.e. "Content-Type" instead of "content-type"). Header
names may contain only letters, digits, "-", and "_" and must start with a
letter and must not end with a "-" or "_". If more than one value for a header
-is required, the value for that property must be an array.
+is required, the value for that property must be an array. Otherwise it may be
+a string or a number.
There must be a Content-Type header, except for when the status is 1xx, 204, or
304, in which case there must be none given.
View
2  lib/common-logger.js
@@ -27,7 +27,7 @@ module.exports = function (app, stream) {
if ('Content-Length' in headers) {
length = headers['Content-Length'];
} else if (typeof body === 'string') {
- length = String(Buffer.byteLength(body));
+ length = Buffer.byteLength(body);
} else if (typeof body.length === 'number') {
length = String(body.length);
}
View
4 lib/content-length.js
@@ -9,9 +9,9 @@ module.exports = function (app) {
app(env, function (status, headers, body) {
if (!('Content-Length' in headers) && !headers['Transfer-Encoding'] && !utils.isEmptyBodyStatus(status)) {
if (typeof body === 'string') {
- headers['Content-Length'] = String(Buffer.byteLength(body));
+ headers['Content-Length'] = Buffer.byteLength(body);
} else if (typeof body.length === 'number') {
- headers['Content-Length'] = String(body.length);
+ headers['Content-Length'] = body.length;
} else {
env.error.write('Cannot set Content-Length for body with no length\n');
}
View
2  lib/directory.js
@@ -139,7 +139,7 @@ function generateListing(env, callback, root, pathInfo, scriptName) {
callback(200, {
'Content-Type': 'text/html',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
}, content);
});
}
View
19 lib/lint.js
@@ -1,5 +1,4 @@
-var Stream = require('stream').Stream;
-var EventEmitter = require('events').EventEmitter;
+var Stream = require('stream');
var strata = require('./index');
var utils = require('./utils');
@@ -180,8 +179,10 @@ function checkHeaders(headers) {
// required, the value for that property must be an array.
assert(typeof headers === 'object', 'Headers must be an object');
+ var value;
for (var headerName in headers) {
- assert(typeof headers[headerName] === 'string', 'Value for header "' + headerName + '" must be a string');
+ value = headers[headerName];
+ assert(typeof value === 'string' || typeof value === 'number' || Array.isArray(value), 'Header value must be a string, number, or array');
assert((/^[0-9A-Za-z_-]+$/).test(headerName), 'Invalid header name "' + headerName + '"');
assert((/^[A-Za-z]/).test(headerName), 'Header name must start with a letter');
assert(!(/[_-]$/).test(headerName), 'Header name must not end with a "_" or "-"');
@@ -191,23 +192,23 @@ function checkHeaders(headers) {
function checkBody(body) {
// The body must be either a string or a readable Stream. If it is a Stream, the
// response will be pumped through to the client.
- assert(typeof body === 'string' || body instanceof EventEmitter, 'Body must be a string or Stream');
+ assert(typeof body === 'string' || body instanceof Stream, 'Body must be a string or Stream');
}
function checkContentType(status, headers) {
// There must be a Content-Type header, except for when the status is 1xx, 204, or
// 304, in which case there must be none given.
- if (utils.STATUS_WITH_NO_ENTITY_BODY.indexOf(status) == -1) {
- assert('Content-Type' in headers, 'Missing Content-Type header');
+ if (utils.isEmptyBodyStatus(status)) {
+ assert(!('Content-Type' in headers), 'Content-Type header given for response with no entity body');
} else {
- assert(!('Content-Type' in headers), 'Content-Type header given for respons with no entity body');
+ assert('Content-Type' in headers, 'Missing Content-Type header');
}
}
function checkContentLength(status, headers, body) {
// There must not be a Content-Length header when the status is 1xx, 204, or 304,
// or it must be "0".
- if (utils.STATUS_WITH_NO_ENTITY_BODY.indexOf(status) != -1 && 'Content-Length' in headers) {
- assert(headers['Content-Length'] == '0', 'Non-zero Content-Length header given for respons with no entity body');
+ if (utils.isEmptyBodyStatus(status) && 'Content-Length' in headers) {
+ assert(headers['Content-Length'] == '0', 'Non-zero Content-Length header given for response with no entity body');
}
}
View
2  lib/redirect.js
@@ -13,7 +13,7 @@ function redirect(env, callback, location, status) {
callback(status, {
'Content-Type': 'text/html',
- 'Content-Length': String(Buffer.byteLength(content)),
+ 'Content-Length': Buffer.byteLength(content),
'Location': location
}, content);
}
View
12 lib/utils.js
@@ -213,7 +213,7 @@ function ok(env, callback) {
callback(200, {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
}, content);
}
@@ -225,7 +225,7 @@ function badRequest(env, callback) {
callback(400, {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
}, content);
}
@@ -239,7 +239,7 @@ function unauthorized(env, callback, realm) {
callback(401, {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content)),
+ 'Content-Length': Buffer.byteLength(content),
'WWW-Authenticate': 'Basic realm="' + realm + '"'
}, content);
}
@@ -252,7 +252,7 @@ function forbidden(env, callback) {
callback(403, {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
}, content);
}
@@ -264,7 +264,7 @@ function notFound(env, callback) {
callback(404, {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
}, content);
}
@@ -276,6 +276,6 @@ function serverError(env, callback) {
callback(500, {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
}, content);
}
View
2  test/index-test.js
@@ -16,7 +16,7 @@ describe('strata', function () {
var queryString = 'a=1&b=2';
var userAgent = 'test suite';
var content = 'Hello world!';
- var contentLength = String(Buffer.byteLength(content));
+ var contentLength = Buffer.byteLength(content);
var env;
beforeEach(function () {
View
4 test/lint-test.js
@@ -160,12 +160,12 @@ describe('lint', function () {
}, /must be an object/);
app = lint(function (env, callback) {
- callback(200, { 'Content-Type': 123 }, '');
+ callback(200, { 'Header': {} }, '');
});
assert.throws(function () {
app(mock.env(), noop);
- }, /must be a string/);
+ }, /value must be a/);
app = lint(function (env, callback) {
callback(200, { '1Header': '' }, '');
View
10 test/request-test.js
@@ -263,7 +263,7 @@ describe('Request', function () {
call(app, mock.env({
headers: {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
},
input: content
}), noop);
@@ -290,7 +290,7 @@ describe('Request', function () {
call(app, mock.env({
headers: {
'Content-Type': 'application/json',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
},
input: content
}), noop);
@@ -317,7 +317,7 @@ describe('Request', function () {
call(app, mock.env({
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
},
input: content
}), noop);
@@ -348,7 +348,7 @@ Hello world!\r\n\
call(app, mock.env({
headers: {
'Content-Type': 'multipart/form-data; boundary="AaB03x"',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
},
input: content
}), noop);
@@ -381,7 +381,7 @@ Hello world!\r\n\
queryString: queryString,
headers: {
'Content-Type': 'multipart/form-data; boundary="AaB03x"',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
},
input: content
}), noop);
View
2  test/response-test.js
@@ -10,7 +10,7 @@ describe('Response', function () {
var code = 200;
var content = 'Hello world!';
var contentType = 'text/plain';
- var contentLength = String(Buffer.byteLength(content));
+ var contentLength = Buffer.byteLength(content);
var headersMap = {
'Content-Type': contentType,
'Content-Length': contentLength
View
2  test/session-cookie-test.js
@@ -87,7 +87,7 @@ function stringify(env, callback) {
callback(200, {
'Content-Type': 'text/plain',
- 'Content-Length': String(Buffer.byteLength(content))
+ 'Content-Length': Buffer.byteLength(content)
}, content);
}
Please sign in to comment.
Something went wrong with that request. Please try again.