Commit 479b30f4 authored by CompileNix's avatar CompileNix

add content-encoding (gzip and deflate) and switch to rexex url routing

parent 49f10117
......@@ -8,6 +8,7 @@ global.url = require("url");
global.fs = require("fs");
global.crypto = require("crypto");
global.os = require("os");
global.zlib = require("zlib");
global.htmlenclode = require("htmlencode").htmlEncode;
var ConfigFile = undefined;
......@@ -47,16 +48,15 @@ var server = require("./server.js");
var requestHandlers = require("./lib/requestHandlers.js");
function Init() {
global.handle = {};
handle[Config.root] = { callback: requestHandlers.Index, cache: true };
handle[Config.root + "static/"] = { callback: requestHandlers.Static, cache: false };
handle[Config.root + "post/"] = { callback: requestHandlers.Post, cache: true };
handle[Config.root + "page/"] = { callback: requestHandlers.Page, cache: true };
handle[Config.root + "ajax/"] = { callback: requestHandlers.Ajax, cache: false };
handle[Config.root + "rss.xml"] = { callback: requestHandlers.RSS, cache: true };
handle[Config.root + "rss"] = { callback: requestHandlers.RSS, cache: true };
handle[Config.root + "edit"] = { callback: requestHandlers.Edit, cache: true };
handle[Config.root + "code/"] = { callback: requestHandlers.Code, cache: false };
global.handle = [];
handle.push({ match: /^\/static\/?.+$/, callback: requestHandlers.Static, cache: false });
handle.push({ match: /^\/post\/?.+$/, callback: requestHandlers.Post, cache: true });
handle.push({ match: /^\/ajax\?.+$/, callback: requestHandlers.ajax, cache: false });
handle.push({ match: /^\/rss$|^\/rss.xml$/, callback: requestHandlers.RSS, cache: true });
handle.push({ match: /^\/edit$|^\/edit\/$/, callback: requestHandlers.Edit, cache: false });
handle.push({ match: /^\/code\/?.+$/, callback: requestHandlers.Code, cache: false });
handle.push({ match: /^\/page\/?.+$/, callback: requestHandlers.Page, cache: true });
handle.push({ match: /^\/$/, callback: requestHandlers.Index, cache: true });
server.Start(router.Route);
}
......@@ -82,6 +82,9 @@ switch (Config.cache) {
}
if (Config.DevMode) {
if (Cache && Config.ClearCacheOnStart) {
Cache.clear();
}
Init();
} else {
if (cluster.isMaster) {
......
......@@ -38,6 +38,10 @@
<Content Include="lib\editor.html" />
<Content Include="lib\footer.html" />
<Content Include="lib\header.html" />
<Content Include="lib\tests\posts\56cb9c4a.json" />
<Content Include="lib\tests\posts\56cb9c4a.json.asc" />
<Content Include="lib\tests\posts\56cb9c69.json" />
<Content Include="lib\tests\posts\56cb9c69.json.asc" />
<Content Include="package.json" />
<Content Include="robots.txt" />
<Content Include="static\activec.png" />
......@@ -82,7 +86,7 @@
<Folder Include="lib\" />
<Folder Include="lib\cache\" />
<Folder Include="lib\requestHandlers\" />
<Folder Include="posts\" />
<Folder Include="lib\tests\posts\" />
<Folder Include="requestHandlers\" />
<Folder Include="static\" />
<Folder Include="lib\tests\" />
......
......@@ -17,10 +17,20 @@ class FsCache extends NullCache {
send(req, res) {
if (this.has(req)) {
const data = JSON.parse(fs.readFileSync(this._path(req), "utf8"));
if (req.headers["accept-encoding"].match(/\bgzip\b/)) {
res.setContentEncoding("gzip");
res.setContent(data.content_gzip.data);
} else if (req.headers["accept-encoding"].match(/\bdeflate\b/)) {
res.setContentEncoding("deflate");
res.setContent(data.content_deflate.data);
} else {
res.setContent(data.content);
}
res.setResponseCode(data.response_code);
res.setContentType(data.mime_type);
res.setLastModified(new Date(fs.statSync(this._path(req)).mtime).toUTCString());
res.setContent(data.content);
res.send();
}
}
......@@ -53,8 +63,11 @@ class FsCache extends NullCache {
const data = JSON.stringify({
mime_type: mime,
response_code: code,
content: cont
content: cont,
content_gzip: zlib.gzipSync(cont, { level: zlib.Z_BEST_COMPRESSION, memLevel: 9, flush: zlib.Z_NO_FLUSH }),
content_deflate: zlib.deflateSync(cont, { level: zlib.Z_BEST_COMPRESSION, memLevel: 9, flush: zlib.Z_NO_FLUSH })
});
console.log("Add cache file: " + this._path(req));
fs.writeFileSync(this._path(req), data);
}
......
......@@ -12,11 +12,21 @@ class MemCache extends NullCache {
send(req, res) {
if (this.has(req)) {
const data = this.cache[this._hash(req)].content;
res.setResponseCode(this.cache[this._hash(req)].response_code);
res.setContentType(this.cache[this._hash(req)].mime_type);
const data = this.cache[this._hash(req)];
if (req.headers["accept-encoding"].match(/\bgzip\b/)) {
res.setContentEncoding("gzip");
res.setContent(data.content_gzip);
} else if (req.headers["accept-encoding"].match(/\bdeflate\b/)) {
res.setContentEncoding("deflate");
res.setContent(data.content_deflate);
} else {
res.setContent(data.content);
}
res.setResponseCode(data.response_code);
res.setContentType(data.mime_type);
res.setLastModified(this.getLastModified(req));
res.setContent(data);
res.send();
}
}
......@@ -46,7 +56,9 @@ class MemCache extends NullCache {
response_code: code,
time: new Date(),
dependencies: dependsOn,
content: cont
content: cont,
content_gzip: zlib.gzipSync(cont, { level: zlib.Z_BEST_COMPRESSION, memLevel: 9, flush: zlib.Z_NO_FLUSH }),
content_deflate: zlib.deflateSync(cont, { level: zlib.Z_BEST_COMPRESSION, memLevel: 9, flush: zlib.Z_NO_FLUSH })
};
console.log("Add mem cache " + this._hash(req));
this.cache[this._hash(req)] = data;
......
......@@ -21,7 +21,7 @@
* {
font-family: Ubuntu, Tahoma, Verdana, sans-serif, serif;
transition: 200ms;
word-break: break-all;
word-break: break-word;
line-height: 1.2em;
}
......
......@@ -41,7 +41,7 @@ function page(request, index) {
if (posts[i - 1]) {
const data = Helper.getPost(posts[i - 1]);
content += "<li>";
content += '[<a href="/post/?p=' + posts[i - 1] + '">' + data.title + "</a>] <br><br>";
content += '[<a href="/post/' + posts[i - 1] + '">' + data.title + "</a>] <br><br>";
content += data.contents;
content += "</li>\n";
deps.push(DirectoryPosts + Helper.GetFsDelimiter() + posts[i - 1] + ".json");
......@@ -57,11 +57,11 @@ function page(request, index) {
content += '<div style="text-align:center">';
if (p < pageCount) {
var older = '<a href="/page/?p=' + (p + 1) + '">' + MessageNewerPage + "</a>";
var older = '<a href="/page/' + (p + 1) + '">' + MessageNewerPage + "</a>";
}
if (p > 1) {
var newer = '<a href="/page/?p=' + (p - 1) + '">' + MessageOlderPage + "</a>";
var newer = '<a href="/page/' + (p - 1) + '">' + MessageOlderPage + "</a>";
}
if (older && newer) {
......
......@@ -7,7 +7,7 @@ function Post(request) {
content: "post not found!",
mimetype: "text/plain"
};
const query = querystring.parse(url.parse(request.url).query)["p"];
const query = request.url.split("/").pop();
var data;
if ((query && query.match(/^[A-Za-z0-9]+$/)) && (data = Helper.getPost(query)) !== "") {
if (data.title) {
......
......@@ -36,9 +36,9 @@ function RSS(request, response, write_cache) {
// author
dataToSend += "<author>" + authorMail + " (" + author + ")</author>\n";
// link
dataToSend += "<link>" + Link + root + "post/?p=" + posts[i] + "</link>\n";
dataToSend += "<link>" + Link + root + "post/" + posts[i] + "</link>\n";
// guid
dataToSend += "<guid>" + Link + root + "post/?p=" + posts[i] + "</guid>\n";
dataToSend += "<guid>" + Link + root + "post/" + posts[i] + "</guid>\n";
// date
dataToSend += "<pubDate>" + new Date(parseInt(posts[i], 16) * 1000).toUTCString() + "</pubDate>\n";
// content (html)
......
......@@ -3,6 +3,7 @@
function _responseWrapper(response) {
this.response = response;
this.data = "";
this.contentEncoding = "";
this.responseCode = 500;
this.contentLength = null;
this.contentType = Config.DefaultContentType || "text/html";
......@@ -20,6 +21,10 @@ _responseWrapper.prototype.setContent = function (content) {
this.updateLength();
}
_responseWrapper.prototype.setContentEncoding = function (encoding) {
this.contentEncoding = encoding;
}
_responseWrapper.prototype.sendFileStream = function (fileStream) {
var t = this;
this.sendHeader();
......@@ -56,7 +61,11 @@ _responseWrapper.prototype.setResponseCode = function (code) {
_responseWrapper.prototype.updateLength = function () {
if (this.data) {
this.contentLength = Buffer.byteLength(this.data, "utf8");
if (this.contentEncoding) {
this.contentLength = Buffer.byteLength(new Buffer(this.data));
} else {
this.contentLength = Buffer.byteLength(this.data, "utf8");
}
}
}
......@@ -65,12 +74,17 @@ _responseWrapper.prototype.sendHeader = function () {
if (this.contentLength) headers["Content-Length"] = this.contentLength;
if (this.expires) headers["Cache-Control"] = "max-age=" + this.expires;
if (this.lastModified) headers["Last-Modified"] = this.lastModified;
if (this.contentEncoding) headers["Content-Encoding"] = this.contentEncoding;
this.response.writeHead(this.responseCode, headers);
}
_responseWrapper.prototype.send = function () {
this.sendHeader();
this.response.end(this.data);
if (this.contentEncoding) {
this.response.end(new Buffer(this.data));
} else {
this.response.end(this.data);
}
}
exports.ResponseWrapper = _responseWrapper;
"use strict";
function Route(callback, request) {
function Route(pathname, request) {
const callback = RouteGetCallback(pathname);
if (typeof callback === "function") {
return callback(request);
} else {
console.log('Request handler found for: "' + url.parse(request.url).pathname + '" but callback is not a function: "' + callback + '"!');
return {
type: "error",
code: 404
}
}
console.log('Request handler found for: "' + pathname + '" but callback is not a function: "' + callback + '"!');
return { type: "error", code: 404 };
}
function RouteExists(pathname) {
if (handle[pathname] == undefined) {
return false;
}
return typeof handle[pathname].callback === "function";
return typeof GetRoute(pathname).callback === "function";
}
function RouteGetCallback(pathname) {
return GetRoute(pathname).callback;
}
function RouteGetCacheEnabled(pathname) {
return GetRoute(pathname).cache;
}
function GetRoute(pathname) {
for (var i = 0; i < handle.length; i++) {
if (handle[i].match.test(pathname)) {
return handle[i];
}
};
return false;
}
exports.Route = Route;
exports.RouteExists = RouteExists;
exports.RouteGetCallback = RouteGetCallback;
exports.RouteGetCacheEnabled = RouteGetCacheEnabled;
exports.GetRoute = GetRoute;
......@@ -4,7 +4,8 @@ global.querystring = require("querystring");
global.url = require("url");
global.fs = require("fs");
global.crypto = require("crypto");
global.os = require("os");
global.os = require("os");
global.zlib = require("zlib");
function GetFsDelimiter() {
switch (os.platform()) {
......@@ -124,7 +125,7 @@ tests.push({
require(".." + GetFsDelimiter() + "cache" + GetFsDelimiter() + "FsCache.js");
const c = new FsCache();
c.clear();
const dummy_request = { url: "test/?x=y" };
var dummy_request = { url: "test/?x=y", headers: { "accept-encoding": "" } };
const dummy_content = "<test> foo bar baz </test>";
const dummy_mimetype = "dummy/mime";
c.add(dummy_request, dummy_content, dummy_mimetype, dummy_mimetype);
......@@ -141,14 +142,22 @@ tests.push({
dummy_response.send = function() {};
c.add(dummy_request, dummy_content, dummy_mimetype, 200);
c.send(dummy_request, dummy_response);
pass &= test_equal(dummy_response.data, dummy_content, "content as expected");
pass &= test_equal(dummy_response.contentType, dummy_mimetype, "mimetype as expected");
pass &= test_equal(dummy_response.responseCode, 200, "status code as expected");
dummy_request = { url: "test/?x=y", headers: { "accept-encoding": "gzip,deflate" } };
c.add(dummy_request, dummy_content, dummy_mimetype, 200);
c.send(dummy_request, dummy_response);
pass &= test_equal(zlib.gunzipSync(new Buffer(dummy_response.data)).toString(), dummy_content, "content_gzip as expected");
dummy_request = { url: "test/?x=y", headers: { "accept-encoding": "deflate,gzip" } };
c.add(dummy_request, dummy_content, dummy_mimetype, 200);
c.send(dummy_request, dummy_response);
pass &= test_equal(zlib.unzipSync(new Buffer(dummy_response.data)).toString(), dummy_content, "content_deflate as expected");
c.clear();
return pass;
......@@ -164,7 +173,7 @@ tests.push({
require(".." + GetFsDelimiter() + "cache" + GetFsDelimiter() + "MemCache.js");
const c = new MemCache();
c.clear();
const dummy_request = { url: "test/?x=y" };
var dummy_request = { url: "test/?x=y", headers: { "accept-encoding": "" } };
const dummy_content = "<test> foo bar baz </test>";
const dummy_mimetype = "dummy/mime";
c.add(dummy_request, dummy_content, dummy_mimetype, dummy_mimetype);
......@@ -178,17 +187,25 @@ tests.push({
const responseWrapper = require(".." + GetFsDelimiter() + "ResponseWrapper.js").ResponseWrapper;
global.Cache = true;
const dummy_response = new responseWrapper();
dummy_response.send = function() {};
dummy_response.send = function () { };
c.add(dummy_request, dummy_content, dummy_mimetype, 200);
c.send(dummy_request, dummy_response);
pass &= test_equal(dummy_response.data, dummy_content, "content as expected");
pass &= test_equal(dummy_response.contentType, dummy_mimetype, "mimetype as expected");
pass &= test_equal(dummy_response.responseCode, 200, "status code as expected");
dummy_request = { url: "test/?x=y", headers: { "accept-encoding": "gzip,deflate" } };
c.add(dummy_request, dummy_content, dummy_mimetype, 200);
c.send(dummy_request, dummy_response);
pass &= test_equal(zlib.gunzipSync(new Buffer(dummy_response.data)).toString(), dummy_content, "content_gzip as expected");
dummy_request = { url: "test/?x=y", headers: { "accept-encoding": "deflate,gzip" } };
c.add(dummy_request, dummy_content, dummy_mimetype, 200);
c.send(dummy_request, dummy_response);
pass &= test_equal(zlib.unzipSync(new Buffer(dummy_response.data)).toString(), dummy_content, "content_deflate as expected");
c.clear();
return pass;
......
......@@ -63,14 +63,14 @@ function process_request(request, response, route) {
response.send();
} else {
const deliverCache = !(HandleClientCacheControl && request.headers["cache-control"] === "no-cache");
const writeCache = handle[pathname].cache;
const writeCache = router.RouteGetCacheEnabled(pathname);
if (deliverCache && Cache.has(request)) {
response.setLastModified(Cache.getLastModified(request));
Cache.send(request, response);
return false;
}
var data = route(handle[pathname].callback, request);
var data = route(pathname, request);
if (request.method === "POST") {
var body = "";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment