spirit
Version:
extensible web library for building applications & frameworks
108 lines (100 loc) • 2.89 kB
JavaScript
;
/**
* node adapter for spirit
*/
var core = require("../core/core");
var request = require("./request");
var response = require("./response");
var Response = require("./response-class.js").Response;
var size_of = require("./utils.js").size_of;
/**
* Detects if 'Content-Length' headers are set
* If not set, it sets the header
* Only possible for string, buffer
* stream type will usually not have a length and need
* to be closed manually with `.end()`
*
* For file-stream, it's possible to fs.stat for a length
* But this function is more of a simple fail-safe
*
* @param {response} resp - response
* @return {object} response headers
*/
var content_length = function content_length(resp) {
if (resp.body === undefined) {
resp.headers["Content-Length"] = 0;
return resp.headers;
}
var h = Response.get(resp, "Content-Length");
if (h === undefined) resp.headers["Content-Length"] = size_of(resp.body);
return resp.headers;
};
/**
* strips all undefined values from `headers`
*
* this is needed because node `res.writeHead` will still write
* headers with undefined values
*
* @param {object} headers - response headers
* @return {object} response headers
*/
var strip = function strip(headers) {
var keys = Object.keys(headers);
for (var i = 0; i < keys.length; i++) {
if (typeof headers[keys[i]] === "undefined") {
delete headers[keys[i]];
}
}
return headers;
};
/**
* writes a http response map to a node HTTP response object
*
* It only knows how to write string/buffer and of course stream
*
* NOTE: There is no guards or type checking
*
* @param {http.Response} res - node http response object
* @param {response-map} resp - response map
*/
var send = function send(res, resp) {
res.writeHead(resp.status, strip(content_length(resp)));
if (resp.body === undefined) {
return res.end();
}
// resp body is a stream
if (typeof resp.body.pipe === "function") {
resp.body.pipe(res);
// resp body is a string or buffer
} else {
res.write(resp.body);
res.end();
}
};
var adapter = function adapter(handler, middleware) {
if (middleware === undefined) {
middleware = [];
} else if (typeof middleware === "function") {
middleware = [middleware];
}
var adp = core.compose(handler, middleware);
return function (req, res) {
var request_map = request.create(req);
adp(request_map).then(function (resp) {
if (!response.is_response(resp)) {
throw new Error("node.js adapter did not receive a proper response (response map). Got: " + JSON.stringify(resp));
}
send(res, resp);
}).catch(function (err) {
var resp = response.err_response(err);
if (process.env.NODE_ENV === "production") {
resp.body_();
}
send(res, resp);
});
};
};
module.exports = {
adapter: adapter,
send: send
};