зеркало из https://github.com/mozilla/djangode.git
325 строки
11 KiB
JavaScript
325 строки
11 KiB
JavaScript
var http = require('http'),
|
|
sys = require('sys'),
|
|
fs = require('fs'),
|
|
url = require('url'),
|
|
querystring = require('querystring')
|
|
;
|
|
|
|
function extname(path) {
|
|
var index = path.lastIndexOf('.');
|
|
return index < 0 ? '' : path.substring(index);
|
|
}
|
|
|
|
exports.serveFile = function(req, res, filename) {
|
|
// TODO: Ensure security against directory traversal attacks
|
|
var body, headers;
|
|
var content_type = mime.lookup(extname(filename));
|
|
var encoding = (content_type.slice(0,4) === 'text' ? 'utf8' : 'binary');
|
|
var status = 200;
|
|
|
|
function loadResponseData(callback) {
|
|
if (body && headers) {
|
|
callback();
|
|
return;
|
|
}
|
|
sys.puts("loading " + filename + "...");
|
|
fs.readFile(filename, encoding, function (error, data) {
|
|
if (error) {
|
|
status = 404;
|
|
body = '404'
|
|
sys.puts("Error loading " + filename);
|
|
return callback();
|
|
}
|
|
body = data;
|
|
headers = [
|
|
['Content-Type', content_type],
|
|
['Content-Length', (encoding === 'utf8')
|
|
? encodeURIComponent(body).replace(/%../g, 'x').length
|
|
: body.length
|
|
]
|
|
];
|
|
sys.puts("static file " + filename + " loaded");
|
|
callback();
|
|
});
|
|
}
|
|
loadResponseData(function() {
|
|
res.sendHeader(status, headers);
|
|
res.write(body, encoding);
|
|
res.close();
|
|
});
|
|
}
|
|
|
|
exports.serve = function(app, port) {
|
|
sys.puts('Server on http://127.0.0.1:' + port + '/');
|
|
return http.createServer(app).listen(port);
|
|
}
|
|
|
|
function respond(res, body, content_type, status) {
|
|
content_type = content_type || 'text/html';
|
|
res.sendHeader(status || 200, {
|
|
'Content-Type': content_type + '; charset=utf-8'
|
|
});
|
|
res.write(body, 'utf8');
|
|
res.close();
|
|
}
|
|
exports.respond = respond;
|
|
|
|
exports.redirect = redirect = function(res, location, status) {
|
|
status = status || 301;
|
|
res.sendHeader(status || 200, {
|
|
'Content-Type': 'text/html; charset=utf-8',
|
|
'Location': location
|
|
});
|
|
res.write('Redirecting...');
|
|
res.close();
|
|
}
|
|
|
|
exports.extractPost = function(req, callback) {
|
|
req.setBodyEncoding('utf-8');
|
|
var body = '';
|
|
req.addListener('data', function(chunk) {
|
|
body += chunk;
|
|
});
|
|
req.addListener('end', function() {
|
|
callback(querystring.parse(url.parse('http://fake/?' + body).query));
|
|
});
|
|
}
|
|
|
|
var debuginfo = {}
|
|
exports.debuginfo = debuginfo;
|
|
|
|
exports.makeApp = function(urls, options) {
|
|
// Compile the regular expressions
|
|
var compiled = urls.map(function(pair) {
|
|
return [new RegExp(pair[0]), pair[1]];
|
|
});
|
|
options = options || {};
|
|
var show_404 = (options.show_404 || default_show_404);
|
|
var show_500 = (options.show_500 || default_show_500);
|
|
|
|
var app = function(req, res) {
|
|
debuginfo.last_request = req;
|
|
debuginfo.last_response = res;
|
|
var path = url.parse(req.url)["pathname"];
|
|
var view = show_404;
|
|
var args = [req, res];
|
|
for (var pair, i = 0; pair = compiled[i]; i++) {
|
|
//sys.puts("Matching " + pair[0] + " against path " + path);
|
|
var match = pair[0](path);
|
|
if (match) {
|
|
//sys.puts(" matched! " + match);
|
|
// Add matched bits to args
|
|
match.slice(1).forEach(function(arg) {
|
|
args.push(arg);
|
|
});
|
|
view = pair[1];
|
|
break;
|
|
}
|
|
}
|
|
try {
|
|
view.apply(null, args);
|
|
} catch (e) {
|
|
debuginfo.last_e = e;
|
|
show_500(req, res, e);
|
|
}
|
|
}
|
|
app.urls = {};
|
|
urls.forEach(function (item) { app.urls[item[2]] = item[0]; });
|
|
return app;
|
|
}
|
|
|
|
function default_show_404(req, res) {
|
|
respond(res,
|
|
'<h1>404</h1>', 'text/html', 404
|
|
);
|
|
}
|
|
exports.default_show_404 = default_show_404
|
|
|
|
function default_show_500(req, res, e) {
|
|
var msg = ''
|
|
if ('stack' in e && 'type' in e) {
|
|
msg = (
|
|
'<p><strong>' + e.type + '</strong></p><pre>' +
|
|
e.stack + '</pre>'
|
|
);
|
|
} else {
|
|
msg = JSON.stringify(e, 0, 2);
|
|
}
|
|
respond(res, '<h1>500</h1>' + msg, 'text/html', 500);
|
|
}
|
|
exports.default_show_500 = default_show_500
|
|
|
|
exports.mime = mime = {
|
|
lookup : function(ext, fallback) {
|
|
return mime.types[ext.toLowerCase()] || fallback || mime.default_type;
|
|
},
|
|
default_type: 'application/octet-stream',
|
|
types: {
|
|
".3gp" : "video/3gpp",
|
|
".a" : "application/octet-stream",
|
|
".ai" : "application/postscript",
|
|
".aif" : "audio/x-aiff",
|
|
".aiff" : "audio/x-aiff",
|
|
".asc" : "application/pgp-signature",
|
|
".asf" : "video/x-ms-asf",
|
|
".asm" : "text/x-asm",
|
|
".asx" : "video/x-ms-asf",
|
|
".atom" : "application/atom+xml",
|
|
".au" : "audio/basic",
|
|
".avi" : "video/x-msvideo",
|
|
".bat" : "application/x-msdownload",
|
|
".bin" : "application/octet-stream",
|
|
".bmp" : "image/bmp",
|
|
".bz2" : "application/x-bzip2",
|
|
".c" : "text/x-c",
|
|
".cab" : "application/vnd.ms-cab-compressed",
|
|
".cc" : "text/x-c",
|
|
".chm" : "application/vnd.ms-htmlhelp",
|
|
".class" : "application/octet-stream",
|
|
".com" : "application/x-msdownload",
|
|
".conf" : "text/plain",
|
|
".cpp" : "text/x-c",
|
|
".crt" : "application/x-x509-ca-cert",
|
|
".css" : "text/css",
|
|
".csv" : "text/csv",
|
|
".cxx" : "text/x-c",
|
|
".deb" : "application/x-debian-package",
|
|
".der" : "application/x-x509-ca-cert",
|
|
".diff" : "text/x-diff",
|
|
".djv" : "image/vnd.djvu",
|
|
".djvu" : "image/vnd.djvu",
|
|
".dll" : "application/x-msdownload",
|
|
".dmg" : "application/octet-stream",
|
|
".doc" : "application/msword",
|
|
".dot" : "application/msword",
|
|
".dtd" : "application/xml-dtd",
|
|
".dvi" : "application/x-dvi",
|
|
".ear" : "application/java-archive",
|
|
".eml" : "message/rfc822",
|
|
".eps" : "application/postscript",
|
|
".exe" : "application/x-msdownload",
|
|
".f" : "text/x-fortran",
|
|
".f77" : "text/x-fortran",
|
|
".f90" : "text/x-fortran",
|
|
".flv" : "video/x-flv",
|
|
".for" : "text/x-fortran",
|
|
".gem" : "application/octet-stream",
|
|
".gemspec": "text/x-script.ruby",
|
|
".gif" : "image/gif",
|
|
".gz" : "application/x-gzip",
|
|
".h" : "text/x-c",
|
|
".hh" : "text/x-c",
|
|
".htm" : "text/html",
|
|
".html" : "text/html",
|
|
".ico" : "image/vnd.microsoft.icon",
|
|
".ics" : "text/calendar",
|
|
".ifb" : "text/calendar",
|
|
".iso" : "application/octet-stream",
|
|
".jar" : "application/java-archive",
|
|
".java" : "text/x-java-source",
|
|
".jnlp" : "application/x-java-jnlp-file",
|
|
".jpeg" : "image/jpeg",
|
|
".jpg" : "image/jpeg",
|
|
".js" : "application/javascript",
|
|
".json" : "application/json",
|
|
".log" : "text/plain",
|
|
".m3u" : "audio/x-mpegurl",
|
|
".m4v" : "video/mp4",
|
|
".man" : "text/troff",
|
|
".mathml" : "application/mathml+xml",
|
|
".mbox" : "application/mbox",
|
|
".mdoc" : "text/troff",
|
|
".me" : "text/troff",
|
|
".mid" : "audio/midi",
|
|
".midi" : "audio/midi",
|
|
".mime" : "message/rfc822",
|
|
".mml" : "application/mathml+xml",
|
|
".mng" : "video/x-mng",
|
|
".mov" : "video/quicktime",
|
|
".mp3" : "audio/mpeg",
|
|
".mp4" : "video/mp4",
|
|
".mp4v" : "video/mp4",
|
|
".mpeg" : "video/mpeg",
|
|
".mpg" : "video/mpeg",
|
|
".ms" : "text/troff",
|
|
".msi" : "application/x-msdownload",
|
|
".odp" : "application/vnd.oasis.opendocument.presentation",
|
|
".ods" : "application/vnd.oasis.opendocument.spreadsheet",
|
|
".odt" : "application/vnd.oasis.opendocument.text",
|
|
".ogg" : "application/ogg",
|
|
".p" : "text/x-pascal",
|
|
".pas" : "text/x-pascal",
|
|
".pbm" : "image/x-portable-bitmap",
|
|
".pdf" : "application/pdf",
|
|
".pem" : "application/x-x509-ca-cert",
|
|
".pgm" : "image/x-portable-graymap",
|
|
".pgp" : "application/pgp-encrypted",
|
|
".pkg" : "application/octet-stream",
|
|
".pl" : "text/x-script.perl",
|
|
".pm" : "text/x-script.perl-module",
|
|
".png" : "image/png",
|
|
".pnm" : "image/x-portable-anymap",
|
|
".ppm" : "image/x-portable-pixmap",
|
|
".pps" : "application/vnd.ms-powerpoint",
|
|
".ppt" : "application/vnd.ms-powerpoint",
|
|
".ps" : "application/postscript",
|
|
".psd" : "image/vnd.adobe.photoshop",
|
|
".py" : "text/x-script.python",
|
|
".qt" : "video/quicktime",
|
|
".ra" : "audio/x-pn-realaudio",
|
|
".rake" : "text/x-script.ruby",
|
|
".ram" : "audio/x-pn-realaudio",
|
|
".rar" : "application/x-rar-compressed",
|
|
".rb" : "text/x-script.ruby",
|
|
".rdf" : "application/rdf+xml",
|
|
".roff" : "text/troff",
|
|
".rpm" : "application/x-redhat-package-manager",
|
|
".rss" : "application/rss+xml",
|
|
".rtf" : "application/rtf",
|
|
".ru" : "text/x-script.ruby",
|
|
".s" : "text/x-asm",
|
|
".sgm" : "text/sgml",
|
|
".sgml" : "text/sgml",
|
|
".sh" : "application/x-sh",
|
|
".sig" : "application/pgp-signature",
|
|
".snd" : "audio/basic",
|
|
".so" : "application/octet-stream",
|
|
".svg" : "image/svg+xml",
|
|
".svgz" : "image/svg+xml",
|
|
".swf" : "application/x-shockwave-flash",
|
|
".t" : "text/troff",
|
|
".tar" : "application/x-tar",
|
|
".tbz" : "application/x-bzip-compressed-tar",
|
|
".tcl" : "application/x-tcl",
|
|
".tex" : "application/x-tex",
|
|
".texi" : "application/x-texinfo",
|
|
".texinfo" : "application/x-texinfo",
|
|
".text" : "text/plain",
|
|
".tif" : "image/tiff",
|
|
".tiff" : "image/tiff",
|
|
".torrent" : "application/x-bittorrent",
|
|
".tr" : "text/troff",
|
|
".txt" : "text/plain",
|
|
".vcf" : "text/x-vcard",
|
|
".vcs" : "text/x-vcalendar",
|
|
".vrml" : "model/vrml",
|
|
".war" : "application/java-archive",
|
|
".wav" : "audio/x-wav",
|
|
".wma" : "audio/x-ms-wma",
|
|
".wmv" : "video/x-ms-wmv",
|
|
".wmx" : "video/x-ms-wmx",
|
|
".wrl" : "model/vrml",
|
|
".wsdl" : "application/wsdl+xml",
|
|
".xbm" : "image/x-xbitmap",
|
|
".xhtml" : "application/xhtml+xml",
|
|
".xls" : "application/vnd.ms-excel",
|
|
".xml" : "application/xml",
|
|
".xpm" : "image/x-xpixmap",
|
|
".xsl" : "application/xml",
|
|
".xslt" : "application/xslt+xml",
|
|
".yaml" : "text/yaml",
|
|
".yml" : "text/yaml",
|
|
".zip" : "application/zip"
|
|
}
|
|
};
|