Comparing version 0.3.8 to 0.3.9
@@ -46,14 +46,19 @@ restify(3) -- Getting Started with restify | ||
'application/json', // Allow these Accept types | ||
'application/foo' | ||
'application/foo' | ||
], | ||
contentHandlers: { // A hash of custom content-type handlers | ||
'application/foo': function(body) { | ||
return JSON.parse(body); | ||
} | ||
return JSON.parse(body); | ||
} | ||
}, | ||
contentWriters: { // A hash of custom serializers | ||
'application/foo': function(obj) { | ||
return JSON.stringify(obj); | ||
} | ||
return JSON.stringify(obj); | ||
} | ||
}, | ||
headers: { // A hash of customer headers | ||
'X-Foo': function(res) { | ||
return 'bar'; | ||
} | ||
}, | ||
key: <PEM>, // Together with `cert`, create an SSL server | ||
@@ -98,3 +103,18 @@ cert: <PEM> // Together with `key`, create an SSL server | ||
`res.send` naturally with content-types not built-in to restify. | ||
* headers: | ||
An object of global headers that are sent back on all requests. Restify | ||
automatically sets the list below. If you don't set those particular keys, | ||
restify fills in default functions; if you do set them, you can fully override | ||
restify's defaults. Note that like contentWriters, this is an object with a | ||
string key as the header name, and the value is a function of the form | ||
f(response) which must return a string. Defaults: | ||
- X-Api-Version (if versioned) | ||
- X-Request-Id | ||
- X-Response-Time | ||
- Content-(Length|Type|MD5) | ||
- Access-Control-Allow-(Origin|Methods|Headers) | ||
- Access-Control-Expose-Headers | ||
## ROUTING | ||
@@ -101,0 +121,0 @@ |
@@ -407,3 +407,4 @@ // Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved. | ||
if (res.body.length > 0) { | ||
switch (res.headers['content-type']) { | ||
var ct = res.headers['content-type'].split(';')[0]; | ||
switch (ct) { | ||
@@ -410,0 +411,0 @@ case 'application/json': |
@@ -64,2 +64,3 @@ // Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved. | ||
} | ||
this.options = _opts; | ||
@@ -76,26 +77,9 @@ this._code = _opts.code; | ||
// These headers allow strict clients (i.e. Google Chrome) to know that | ||
// this server does allow itself to be invoked from pages that aren't | ||
// part of the same origin policy. | ||
headers['Access-Control-Allow-Origin'] = '*'; | ||
if (this._allowedMethods && this._allowedMethods.length) | ||
headers['Access-Control-Allow-Methods'] = this._allowedMethods.join(', '); | ||
if (!_opts.noClose) | ||
headers.Connection = 'close'; | ||
if (this._version) | ||
headers['X-Api-Version'] = this._version; | ||
headers.Date = utils.newHttpDate(now); | ||
headers.Server = this._config.serverName; | ||
headers['X-Request-Id'] = this.requestId; | ||
headers['X-Response-Time'] = this._time; | ||
if (_opts.body && _opts.code !== HttpCodes.NoContent) { | ||
headers['Content-Type'] = this._accept; | ||
if (this._accept === 'application/x-www-form-urlencoded') { | ||
data = querystring.stringify(_opts.body); | ||
data = data + '\n'; | ||
} else if (this._accept === 'application/json') { | ||
data = JSON.stringify(_opts.body); | ||
data = data + '\n'; | ||
} else if (this._config.contentWriters[this._accept]) { | ||
@@ -106,21 +90,21 @@ data = this._config.contentWriters[this._accept](_opts.body); | ||
// actually be in this case. | ||
data = _opts.body; | ||
data = _opts.body + ''; | ||
} | ||
} | ||
this._data = data; | ||
this._bytes = 0; | ||
if (data && _opts.code !== HttpCodes.NoContent) { | ||
data = data + '\n'; | ||
this._bytes = Buffer.byteLength(data, 'utf8'); | ||
if (!_opts.noContentMD5) { | ||
var hash = crypto.createHash('md5'); | ||
hash.update(data); | ||
headers['Content-MD5'] = hash.digest('base64'); | ||
if (!_opts.noClose) | ||
headers.Connection = 'close'; | ||
headers.Date = utils.newHttpDate(now); | ||
headers.Server = this._config.serverName; | ||
for (var k in this._config.headers) { | ||
if (this._config.headers.hasOwnProperty(k)) { | ||
var val = this._config.headers[k](this); | ||
if (val !== undefined && val !== null) | ||
headers[k] = val; | ||
} | ||
} | ||
if (!_opts.noEnd && this._method !== 'HEAD') | ||
headers['Content-Length'] = this._bytes; | ||
log.trace('response.send: code=%d, headers=%o, body=%s', | ||
@@ -127,0 +111,0 @@ _opts.code, headers, data); |
@@ -470,2 +470,17 @@ // Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved. | ||
* and cannot be overridden. | ||
* - headers: An object of global headers that are sent back | ||
* on all requests. Restify automatically sets: | ||
* - X-Api-Version (if versioned) | ||
* - X-Request-Id | ||
* - X-Response-Time | ||
* - Content-(Length|Type|MD5) | ||
* - Access-Control-Allow-(Origin|Methods|Headers) | ||
* - Access-Control-Expose-Headers | ||
* If you don't set those particular keys, restify | ||
* fills in default functions; if you do set them, | ||
* you can fully override restify's defaults. | ||
* Note that like contentWriters, this is an object | ||
* with a string key as the header name, and the | ||
* value is a function of the form f(response) | ||
* which must return a string. | ||
* | ||
@@ -475,3 +490,3 @@ * @return {Object} node HTTP server, with restify "magic". | ||
createServer: function(options) { | ||
var k; | ||
var server; | ||
@@ -496,3 +511,3 @@ | ||
response._method = request.method; | ||
response._allowedMethods = []; | ||
response._allowedMethods = ['OPTIONS']; | ||
response._config = server._config; | ||
@@ -612,2 +627,3 @@ | ||
server._config.contentWriters = {}; | ||
server._config.headers = {}; | ||
@@ -646,3 +662,2 @@ if (options) { | ||
var k; | ||
if (options.contentHandlers) { | ||
@@ -675,2 +690,16 @@ if (typeof(options.contentHandlers) !== 'object') | ||
} | ||
if (options.headers) { | ||
if (typeof(options.headers) !== 'object') | ||
throw new TypeError('headers must be an object'); | ||
for (k in options.headers) { | ||
if (options.headers.hasOwnProperty(k)) { | ||
if (typeof(options.headers[k]) !== 'function') | ||
throw new TypeError('headers values must be functions'); | ||
server._config.headers[k] = options.headers[k]; | ||
} | ||
} | ||
} | ||
} | ||
@@ -717,5 +746,124 @@ | ||
} | ||
log.trace('server will accept types: %o', server._config.acceptable); | ||
var foundXApiVersion = false; | ||
var foundXRequestId = false; | ||
var foundXResponseTime = false; | ||
var foundContentLength = false; | ||
var foundContentType = false; | ||
var foundContentMD5 = false; | ||
var foundACAO = false; | ||
var foundACAM = false; | ||
var foundACAH = false; | ||
var foundACEH = false; | ||
for (k in server._config.headers) { | ||
if (server._config.headers.hasOwnProperty(k)) { | ||
var h = k.toLowerCase(); | ||
switch (h) { | ||
case 'x-api-version': | ||
foundXApiVersion = true; | ||
break; | ||
case 'x-request-id': | ||
foundXRequestId = true; | ||
break; | ||
case 'x-response-time': | ||
foundXResponseTime = true; | ||
break; | ||
case 'content-length': | ||
foundContentLength = true; | ||
break; | ||
case 'content-type': | ||
foundContentType = true; | ||
break; | ||
case 'content-md5': | ||
foundContentMD5 = true; | ||
break; | ||
case 'access-control-allow-origin': | ||
foundACAO = true; | ||
break; | ||
case 'access-control-allow-method': | ||
foundACAM = true; | ||
break; | ||
case 'access-control-allow-headers': | ||
foundACAH = true; | ||
break; | ||
case 'access-control-expose-headers': | ||
foundACEH = true; | ||
break; | ||
} | ||
} | ||
} | ||
if (!foundXApiVersion) { | ||
server._config.headers['X-Api-Version'] = function(res) { | ||
return res._version; | ||
}; | ||
} | ||
if (!foundXRequestId) { | ||
server._config.headers['X-Request-Id'] = function(res) { | ||
return res.requestId; | ||
}; | ||
} | ||
if (!foundXResponseTime) { | ||
server._config.headers['X-Response-Time'] = function(res) { | ||
return res._time; | ||
}; | ||
} | ||
if (!foundContentLength) { | ||
server._config.headers['Content-Length'] = function(res) { | ||
if (!res.options.noEnd && res._method !== 'HEAD' && res._data) { | ||
res._bytes = Buffer.byteLength(res._data, 'utf8'); | ||
} | ||
return res._bytes; | ||
}; | ||
} | ||
if (!foundContentMD5) { | ||
server._config.headers['Content-MD5'] = function(res) { | ||
if (res._data && res.options.code !== 204) { | ||
if (!res.options.noContentMD5) { | ||
var hash = crypto.createHash('md5'); | ||
hash.update(res._data); | ||
return hash.digest('base64'); | ||
} | ||
} | ||
}; | ||
} | ||
if (!foundContentType) { | ||
server._config.headers['Content-Type'] = function(res) { | ||
if (res._data && res.options.code !== 204) | ||
return res._accept; | ||
}; | ||
} | ||
if (!foundACAO) { | ||
server._config.headers['Access-Control-Allow-Origin'] = function(res) { | ||
return '*'; | ||
}; | ||
} | ||
if (!foundACAM) { | ||
server._config.headers['Access-Control-Allow-Methods'] = function(res) { | ||
if (res._allowedMethods && res._allowedMethods.length) | ||
return res._allowedMethods.join(', '); | ||
}; | ||
} | ||
if (!foundACAH) { | ||
server._config.headers['Access-Control-Allow-Headers'] = function(res) { | ||
return [ | ||
'Accept', | ||
'Content-Type', | ||
'Content-Length', | ||
'Date', | ||
'X-Api-Version' | ||
].join(', '); | ||
}; | ||
} | ||
if (!foundACEH) { | ||
server._config.headers['Access-Control-Expose-Headers'] = function(res) { | ||
return [ | ||
'X-Api-Version', | ||
'X-Request-Id', | ||
'X-Response-Time' | ||
].join(', '); | ||
}; | ||
} | ||
return server; | ||
@@ -722,0 +870,0 @@ } |
{ | ||
"name": "restify", | ||
"description": "REST framework specifically meant for web service APIs", | ||
"version": "0.3.8", | ||
"version": "0.3.9", | ||
"repository": { | ||
@@ -6,0 +6,0 @@ "type": "git", |
@@ -451,1 +451,42 @@ // Copyright 2011 Mark Cavage <mcavage@gmail.com> All rights reserved. | ||
}; | ||
exports.test_custom_headers = function(test, assert) { | ||
var server = restify.createServer({ | ||
headers: { | ||
'access-control-allow-headers': function(res) { | ||
return [ | ||
'x-unit-test' | ||
].join(', '); | ||
}, | ||
'X-Unit-Test': function(res) { | ||
return 'foo'; | ||
} | ||
} | ||
}); | ||
server.get('/custom_headers', function(req, res, next) { | ||
res.send(200); | ||
return next(); | ||
}); | ||
var socket = '/tmp/.' + uuid(); | ||
server.listen(socket, function() { | ||
var content = JSON.stringify({json: 'foo'}); | ||
var opts = common.newOptions(socket, '/custom_headers'); | ||
var req = http.request(opts, function(res) { | ||
common.checkResponse(assert, res); | ||
assert.equal(res.statusCode, 200); | ||
console.log(res.headers); | ||
assert.equal(res.headers['access-control-allow-headers'], 'x-unit-test'); | ||
assert.equal(res.headers['x-unit-test'], 'foo'); | ||
server.on('close', function() { | ||
test.finish(); | ||
}); | ||
server.close(); | ||
}); | ||
req.write(content); | ||
req.end(); | ||
}); | ||
}; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
219999
4134