appjs
Version:
AppJS is a SDK on top of nodejs to develop desktop applications using HTML/CSS/JS
198 lines (179 loc) • 5.38 kB
JavaScript
var ServerResponse = require('http').ServerResponse,
STATUS_CODES = require('http').STATUS_CODES,
fs = require('fs'),
path = require('path'),
url = require('url'),
mime = require('mime'),
inherit = require('../utils').inherit,
decorate = require('../utils').decorate;
var EMPTY = new Buffer(0);
var appjsVersion = 'AppJS' + require('../../package.json').version;
module.exports = Response;
function Response(request, callback){
this.callback = callback;
this.request = request;
this.headers = baseHeaders.child();
}
inherit(Response, ServerResponse, [
// we can set the status of the response
// Rename the 'status' property in order to use this function
function status(status){
this.statusCode = status;
return this;
},
function end(data){
// be sure all parameters will be passed to 'send' method
return this.send.apply(this, arguments);
},
function send(status, mimetype, data){
// rename the 'status' property in order to use 'status' function
if (arguments.length === 1) {
if (typeof status === 'number') {
this.statusCode = status;
} else {
this.mimetype = 'text/html';
this.data = status;
}
} else if (arguments.length === 2){
this.statusCode = status;
this.data = Buffer.isBuffer(mimetype) ? mimetype : new Buffer(mimetype);
} else {
this.statusCode = status;
this.mimetype = mimetype;
this.data = Buffer.isBuffer(data) ? data : new Buffer(data);
}
this.dispatch();
},
function dispatch(){
this.statusCode || (this.statusCode = 200);
this.mimetype || (this.mimetype = 'text/html');
this.data || (this.data = EMPTY);
this.responseCode = STATUS_CODES[this.statusCode];
if (!Buffer.isBuffer(this.data)) {
if (this.data !== null && typeof this.data === 'object') {
this.mimetype = 'application/json';
this.data = new Buffer(JSON.stringify(this.data));
} else if (typeof this.data === 'string' || typeof this.data === 'number') {
this.data = new Buffer(this.data);
} else {
this.data = EMPTY;
}
}
this.headers.setHeader('Content-Length', this.data.length);
this.headers.setHeader('Content-Type', this.mimetype);
this.callback(this.statusCode, this.responseCode, this.mimetype, this.headers.toArrays(), this.data);
},
function redirect(destination){
this.statusCode = 302;
this.setHeader('Location', url.resolve(this.request.headers.Referer, destination));
this.dispatch();
return this;
},
function setHeader(name, header){
this.headers.setHeader(name, header);
},
function sendFile(status, filepath){
var self = this;
if (arguments.length === 2) {
this.path = path.resolve(filepath);
this.statusCode = status;
} else {
this.path = path.resolve(status);
}
fs.stat(this.path, function(err, stat){
if (err || !stat.isFile()) {
self.send(404);
} else {
self.mimetype = mime.lookup(self.path);
fs.readFile(self.path, function(err, buffer){
if (err) {
self.send(500);
} else {
self.data = buffer;
self.dispatch();
}
});
}
});
}
]);
function Headers(init){
if (init instanceof Headers) {
this.inheritHeaders(init);
} else {
this.names = Object.create(null);
this.headers = Object.create(null);
if (init) {
this.setHeaders(init);
}
}
}
decorate(Headers.prototype, true, [
function setHeader(name, value){
var key = name.toLowerCase();
this.names[key] = name;
this.headers[key] = value;
},
function setHeaders(source){
if (source instanceof Headers) {
source.listHeaders().forEach(function(name){
var key = name.toLowerCase();
this.names[key] = name;
this.headers[key] = source.headers[key];
}, this);
} else {
for (var k in Object(source)) {
this.setHeader(k, source[k]);
}
}
},
function inheritHeaders(source){
if (source instanceof Headers) {
if (!this.names || !this.listHeaders().length) {
this.names = Object.create(source.names);
this.headers = Object.create(source.headers);
} else {
this.names.__proto__ = source.names;
this.headers.__proto__ = source.headers;
}
} else {
// throw?
}
},
function getHeader(name){
return this.headers[name.toLowerCase()];
},
function removeHeader(name){
var key = name.toLowerCase();
delete this.names[key];
delete this.headers[key];
},
function listHeaders(){
var i=0, k=[];
for (k[i++] in this.names);
return k;
},
function toArrays(){
var out = { names: [], headers: [] }
for (var k in this.names) {
out.names.push(this.names[k]);
out.headers.push(this.headers[k]);
}
return out;
},
function toObject(){
var out = {};
this.listHeaders().forEach(function(key){
out[this.names[key]] = this.headers[key];
}, this);
return out;
},
function child(){
return new Headers(this);
}
]);
var baseHeaders = new Headers({
'Connection': 'Keep-Alive',
'Keep-Alive': 'timeout=3, max=100',
'Server': appjsVersion
});