forked from svrjs/svrjs
Update to SVR.JS 3.14.0
This commit is contained in:
parent
688c850c50
commit
91f2d3b50f
4 changed files with 131 additions and 21 deletions
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>SVR.JS 3.13.1</title>
|
<title>SVR.JS 3.14.0</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<style>
|
<style>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Welcome to SVR.JS 3.13.1</h1>
|
<h1>Welcome to SVR.JS 3.14.0</h1>
|
||||||
<br/>
|
<br/>
|
||||||
<img src="/logo.png" style="width: 256px;" />
|
<img src="/logo.png" style="width: 256px;" />
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -134,8 +134,9 @@
|
||||||
</div>
|
</div>
|
||||||
<p>Changes:</p>
|
<p>Changes:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Fixed error handling for invalid URL rewrite regexes.</li>
|
<li>Added new <i>config.json</i> properties: <i>useClientCertificate</i>, <i>rejectUnauthorizedClientCertificates</i>, <i>cipherSuite</i>, <i>ecdhCurve</i>, <i>tlsMinVersion</i>, <i>tlsMaxVersion</i>, <i>signatureAlgorithms</i> and <i>http2Settings</i>.</li>
|
||||||
<li>Fixed bug with non-working HTTP proxy handler (excluding CONNECT method).</li>
|
<li>Added support for web root postfixes (along with postfix prefixes).</li>
|
||||||
|
<li>Custom head and foot inclusion is now returning 500 error in case of server error instead of crashing the server.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br/>
|
<br/>
|
||||||
<a href="/tests.html">Tests</a><br/>
|
<a href="/tests.html">Tests</a><br/>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>SVR.JS 3.13.1 Licenses</title>
|
<title>SVR.JS 3.14.0 Licenses</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<style>
|
<style>
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>SVR.JS 3.13.1 Licenses</h1>
|
<h1>SVR.JS 3.14.0 Licenses</h1>
|
||||||
<h2>SVR.JS 3.13.1</h2>
|
<h2>SVR.JS 3.14.0</h2>
|
||||||
<div style="display: inline-block; text-align: left; border-width: 2px; border-style: solid; border-color: gray; padding: 8px;">
|
<div style="display: inline-block; text-align: left; border-width: 2px; border-style: solid; border-color: gray; padding: 8px;">
|
||||||
MIT License<br/>
|
MIT License<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br/>
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br/>
|
||||||
SOFTWARE.<br/>
|
SOFTWARE.<br/>
|
||||||
</div>
|
</div>
|
||||||
<h2>Packages used by SVR.JS 3.13.1</h2>
|
<h2>Packages used by SVR.JS 3.14.0</h2>
|
||||||
<div style="width: 100%; background-color: #ccc; border: 1px solid green; text-align: left; margin: 10px 0;">
|
<div style="width: 100%; background-color: #ccc; border: 1px solid green; text-align: left; margin: 10px 0;">
|
||||||
<div style="float: right;">License: MIT</div>
|
<div style="float: right;">License: MIT</div>
|
||||||
<div style="font-size: 20px;">
|
<div style="font-size: 20px;">
|
||||||
|
|
127
svr.js
127
svr.js
|
@ -69,7 +69,7 @@ function deleteFolderRecursive(path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var os = require("os");
|
var os = require("os");
|
||||||
var version = "3.13.1";
|
var version = "3.14.0";
|
||||||
var singlethreaded = false;
|
var singlethreaded = false;
|
||||||
|
|
||||||
if (process.versions) process.versions.svrjs = version; // Inject SVR.JS into process.versions
|
if (process.versions) process.versions.svrjs = version; // Inject SVR.JS into process.versions
|
||||||
|
@ -1086,6 +1086,8 @@ var useWebRootServerSideScript = true;
|
||||||
var exposeModsInErrorPages = true;
|
var exposeModsInErrorPages = true;
|
||||||
var disableTrailingSlashRedirects = false;
|
var disableTrailingSlashRedirects = false;
|
||||||
var environmentVariables = {};
|
var environmentVariables = {};
|
||||||
|
var wwwrootPostfixesVHost = [];
|
||||||
|
var wwwrootPostfixPrefixesVHost = [];
|
||||||
|
|
||||||
// Get properties from config.json
|
// Get properties from config.json
|
||||||
if (configJSON.blacklist != undefined) rawBlackList = configJSON.blacklist;
|
if (configJSON.blacklist != undefined) rawBlackList = configJSON.blacklist;
|
||||||
|
@ -1139,6 +1141,8 @@ if (configJSON.useWebRootServerSideScript != undefined) useWebRootServerSideScri
|
||||||
if (configJSON.exposeModsInErrorPages != undefined) exposeModsInErrorPages = configJSON.exposeModsInErrorPages;
|
if (configJSON.exposeModsInErrorPages != undefined) exposeModsInErrorPages = configJSON.exposeModsInErrorPages;
|
||||||
if (configJSON.disableTrailingSlashRedirects != undefined) disableTrailingSlashRedirects = configJSON.disableTrailingSlashRedirects;
|
if (configJSON.disableTrailingSlashRedirects != undefined) disableTrailingSlashRedirects = configJSON.disableTrailingSlashRedirects;
|
||||||
if (configJSON.environmentVariables != undefined) environmentVariables = configJSON.environmentVariables;
|
if (configJSON.environmentVariables != undefined) environmentVariables = configJSON.environmentVariables;
|
||||||
|
if (configJSON.wwwrootPostfixesVHost != undefined) wwwrootPostfixesVHost = configJSON.wwwrootPostfixesVHost;
|
||||||
|
if (configJSON.wwwrootPostfixPrefixesVHost != undefined) wwwrootPostfixPrefixesVHost = configJSON.wwwrootPostfixPrefixesVHost;
|
||||||
|
|
||||||
var wwwrootError = null;
|
var wwwrootError = null;
|
||||||
try {
|
try {
|
||||||
|
@ -2065,12 +2069,21 @@ if (!cluster.isPrimary) {
|
||||||
allowHTTP1: true,
|
allowHTTP1: true,
|
||||||
requireHostHeader: false,
|
requireHostHeader: false,
|
||||||
key: key,
|
key: key,
|
||||||
cert: cert
|
cert: cert,
|
||||||
|
requestCert: configJSON.useClientCertificate,
|
||||||
|
rejectUnauthorized: configJSON.rejectUnauthorizedClientCertificates,
|
||||||
|
ciphers: configJSON.cipherSuite,
|
||||||
|
ecdhCurve: configJSON.ecdhCurve,
|
||||||
|
minVersion: configJSON.tlsMinVersion,
|
||||||
|
maxVersion: configJSON.tlsMaxVersion,
|
||||||
|
sigalgs: configJSON.signatureAlgorithms,
|
||||||
|
settings: configJSON.http2Settings
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
server = http2.createServer({
|
server = http2.createServer({
|
||||||
allowHTTP1: true,
|
allowHTTP1: true,
|
||||||
requireHostHeader: false
|
requireHostHeader: false,
|
||||||
|
settings: configJSON.http2Settings
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2078,7 +2091,14 @@ if (!cluster.isPrimary) {
|
||||||
server = https.createServer({
|
server = https.createServer({
|
||||||
key: key,
|
key: key,
|
||||||
cert: cert,
|
cert: cert,
|
||||||
requireHostHeader: false
|
requireHostHeader: false,
|
||||||
|
requestCert: configJSON.useClientCertificate,
|
||||||
|
rejectUnauthorized: configJSON.rejectUnauthorizedClientCertificates,
|
||||||
|
ciphers: configJSON.cipherSuite,
|
||||||
|
ecdhCurve: configJSON.ecdhCurve,
|
||||||
|
minVersion: configJSON.tlsMinVersion,
|
||||||
|
maxVersion: configJSON.tlsMaxVersion,
|
||||||
|
sigalgs: configJSON.signatureAlgorithms
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
@ -2315,8 +2335,9 @@ if (!cluster.isPrimary) {
|
||||||
});
|
});
|
||||||
socket.on("error", function () {});
|
socket.on("error", function () {});
|
||||||
|
|
||||||
var head = fs.existsSync("./.head") ? fs.readFileSync("./.head").toString() : (fs.existsSync("./head.html") ? fs.readFileSync("./head.html").toString() : ""); // header
|
// Header and footer placeholders
|
||||||
var foot = fs.existsSync("./.foot") ? fs.readFileSync("./.foot").toString() : (fs.existsSync("./foot.html") ? fs.readFileSync("./foot.html").toString() : ""); // footer
|
var head = "";
|
||||||
|
var foot = "";
|
||||||
|
|
||||||
function responseEnd(body) {
|
function responseEnd(body) {
|
||||||
// If body is Buffer, then it is converted to String anyway.
|
// If body is Buffer, then it is converted to String anyway.
|
||||||
|
@ -2464,6 +2485,9 @@ if (!cluster.isPrimary) {
|
||||||
serverconsole.locmessage("Somebody connected to " + (secure && fromMain ? ((typeof sport == "number" ? "port " : "socket ") + sport) : ((typeof port == "number" ? "port " : "socket ") + port)) + "...");
|
serverconsole.locmessage("Somebody connected to " + (secure && fromMain ? ((typeof sport == "number" ? "port " : "socket ") + sport) : ((typeof port == "number" ? "port " : "socket ") + port)) + "...");
|
||||||
serverconsole.reqmessage("Client " + ((!reqip || reqip == "") ? "[unknown client]" : (reqip + ((reqport && reqport !== 0) && reqport != "" ? ":" + reqport : ""))) + " sent invalid request.");
|
serverconsole.reqmessage("Client " + ((!reqip || reqip == "") ? "[unknown client]" : (reqip + ((reqport && reqport !== 0) && reqport != "" ? ":" + reqport : ""))) + " sent invalid request.");
|
||||||
try {
|
try {
|
||||||
|
head = fs.existsSync("./.head") ? fs.readFileSync("./.head").toString() : (fs.existsSync("./head.html") ? fs.readFileSync("./head.html").toString() : ""); // header
|
||||||
|
foot = fs.existsSync("./.foot") ? fs.readFileSync("./.foot").toString() : (fs.existsSync("./foot.html") ? fs.readFileSync("./foot.html").toString() : ""); // footer
|
||||||
|
|
||||||
if ((err.code && (err.code.indexOf("ERR_SSL_") == 0 || err.code.indexOf("ERR_TLS_") == 0)) || (!err.code && err.message.indexOf("SSL routines") != -1)) {
|
if ((err.code && (err.code.indexOf("ERR_SSL_") == 0 || err.code.indexOf("ERR_TLS_") == 0)) || (!err.code && err.message.indexOf("SSL routines") != -1)) {
|
||||||
if (err.code == "ERR_SSL_HTTP_REQUEST" || err.message.indexOf("http request") != -1) {
|
if (err.code == "ERR_SSL_HTTP_REQUEST" || err.message.indexOf("http request") != -1) {
|
||||||
serverconsole.errmessage("Client sent HTTP request to HTTPS port.");
|
serverconsole.errmessage("Client sent HTTP request to HTTPS port.");
|
||||||
|
@ -2962,8 +2986,9 @@ if (!cluster.isPrimary) {
|
||||||
var acceptEncoding = req.headers["accept-encoding"];
|
var acceptEncoding = req.headers["accept-encoding"];
|
||||||
if (!acceptEncoding) acceptEncoding = "";
|
if (!acceptEncoding) acceptEncoding = "";
|
||||||
|
|
||||||
var head = fs.existsSync("./.head") ? fs.readFileSync("./.head").toString() : (fs.existsSync("./head.html") ? fs.readFileSync("./head.html").toString() : ""); // header
|
// Header and footer placeholders
|
||||||
var foot = fs.existsSync("./.foot") ? fs.readFileSync("./.foot").toString() : (fs.existsSync("./foot.html") ? fs.readFileSync("./foot.html").toString() : ""); // footer
|
var head = "";
|
||||||
|
var foot = "";
|
||||||
|
|
||||||
function responseEnd(body) {
|
function responseEnd(body) {
|
||||||
// If body is Buffer, then it is converted to String anyway.
|
// If body is Buffer, then it is converted to String anyway.
|
||||||
|
@ -3128,6 +3153,12 @@ if (!cluster.isPrimary) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
head = fs.existsSync("./.head") ? fs.readFileSync("./.head").toString() : (fs.existsSync("./head.html") ? fs.readFileSync("./head.html").toString() : ""); // header
|
||||||
|
foot = fs.existsSync("./.foot") ? fs.readFileSync("./.foot").toString() : (fs.existsSync("./foot.html") ? fs.readFileSync("./foot.html").toString() : ""); // footer
|
||||||
|
} catch (err) {
|
||||||
|
callServerError(500, undefined, generateErrorStack(err));
|
||||||
|
}
|
||||||
|
|
||||||
// Function to perform HTTP redirection to a specified destination URL
|
// Function to perform HTTP redirection to a specified destination URL
|
||||||
function redirect(destination, isTemporary, keepMethod, customHeaders) {
|
function redirect(destination, isTemporary, keepMethod, customHeaders) {
|
||||||
|
@ -4189,7 +4220,7 @@ if (!cluster.isPrimary) {
|
||||||
doCallback = false;
|
doCallback = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (matchHostname(mapEntry.host) && createRegex(mapEntry.definingRegex).test(address) && !(mapEntry.isNotDirectory && _fileState == 2) && !(mapEntry.isNotFile && _fileState == 1)) {
|
if (matchHostname(mapEntry.host) && address.match(createRegex(mapEntry.definingRegex)) && !(mapEntry.isNotDirectory && _fileState == 2) && !(mapEntry.isNotFile && _fileState == 1)) {
|
||||||
try {
|
try {
|
||||||
mapEntry.replacements.forEach(function (replacement) {
|
mapEntry.replacements.forEach(function (replacement) {
|
||||||
rewrittenURL = rewrittenURL.replace(createRegex(replacement.regex), replacement.replacement);
|
rewrittenURL = rewrittenURL.replace(createRegex(replacement.regex), replacement.replacement);
|
||||||
|
@ -4237,6 +4268,84 @@ if (!cluster.isPrimary) {
|
||||||
|
|
||||||
var origHref = href;
|
var origHref = href;
|
||||||
|
|
||||||
|
// Add web root postfixes
|
||||||
|
if(!isProxy) {
|
||||||
|
var urlWithPostfix = req.url;
|
||||||
|
var postfixPrefix = "";
|
||||||
|
wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) {
|
||||||
|
if (req.url.indexOf(currentPostfixPrefix) == 0) {
|
||||||
|
if (currentPostfixPrefix.match(/\/+$/)) postfixPrefix = currentPostfixPrefix.replace(/\/+$/,"");
|
||||||
|
else if (urlWithPostfix.length == currentPostfixPrefix.length || urlWithPostfix[currentPostfixPrefix.length] == "?" || urlWithPostfix[currentPostfixPrefix.length] == "/" || urlWithPostfix[currentPostfixPrefix.length] == "#") postfixPrefix = currentPostfixPrefix;
|
||||||
|
else return true;
|
||||||
|
urlWithPostfix = urlWithPostfix.substr(postfixPrefix.length);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
wwwrootPostfixesVHost.every(function (postfixEntry) {
|
||||||
|
if (matchHostname(postfixEntry.host) && !(postfixEntry.skipRegex && req.url.match(createRegex(postfixEntry.skipRegex)))) {
|
||||||
|
urlWithPostfix = postfixPrefix + "/" + postfixEntry.postfix + urlWithPostfix;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (urlWithPostfix != req.url) {
|
||||||
|
serverconsole.resmessage("Added web root postfix: " + req.url + " => " + urlWithPostfix);
|
||||||
|
req.url = urlWithPostfix;
|
||||||
|
uobject = parseURL(req.url);
|
||||||
|
search = uobject.search;
|
||||||
|
href = uobject.pathname;
|
||||||
|
ext = path.extname(href).toLowerCase();
|
||||||
|
ext = ext.substr(1, ext.length);
|
||||||
|
|
||||||
|
try {
|
||||||
|
decodedHref = decodeURIComponent(href);
|
||||||
|
} catch (err) {
|
||||||
|
// Return 400 error
|
||||||
|
callServerError(400);
|
||||||
|
serverconsole.errmessage("Bad request!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sHref = sanitizeURL(href);
|
||||||
|
var preparedReqUrl2 = uobject.pathname + (uobject.search ? uobject.search : "") + (uobject.hash ? uobject.hash : "");
|
||||||
|
|
||||||
|
if (req.url != preparedReqUrl2 || sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/")) {
|
||||||
|
callServerError(403);
|
||||||
|
serverconsole.errmessage("Content blocked.");
|
||||||
|
return;
|
||||||
|
} else if (sHref != href) {
|
||||||
|
var rewrittenAgainURL = uobject;
|
||||||
|
rewrittenAgainURL.path = null;
|
||||||
|
rewrittenAgainURL.href = null;
|
||||||
|
rewrittenAgainURL.pathname = sHref;
|
||||||
|
rewrittenAgainURL.hostname = null;
|
||||||
|
rewrittenAgainURL.host = null;
|
||||||
|
rewrittenAgainURL.port = null;
|
||||||
|
rewrittenAgainURL.protocol = null;
|
||||||
|
rewrittenAgainURL.slashes = null;
|
||||||
|
rewrittenAgainURL = url.format(rewrittenAgainURL);
|
||||||
|
serverconsole.resmessage("URL sanitized: " + req.url + " => " + rewrittenAgainURL);
|
||||||
|
req.url = rewrittenAgainURL;
|
||||||
|
uobject = parseURL(req.url);
|
||||||
|
search = uobject.search;
|
||||||
|
href = uobject.pathname;
|
||||||
|
ext = path.extname(href).toLowerCase();
|
||||||
|
ext = ext.substr(1, ext.length);
|
||||||
|
try {
|
||||||
|
decodedHref = decodeURIComponent(href);
|
||||||
|
} catch (err) {
|
||||||
|
// Return 400 error
|
||||||
|
callServerError(400);
|
||||||
|
serverconsole.errmessage("Bad request!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Rewrite URLs
|
// Rewrite URLs
|
||||||
rewriteURL(req.url, rewriteMap, function(err, rewrittenURL) {
|
rewriteURL(req.url, rewriteMap, function(err, rewrittenURL) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>SVR.JS 3.13.1 Tests</title>
|
<title>SVR.JS 3.14.0 Tests</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<style>
|
<style>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>SVR.JS 3.13.1 Tests</h1>
|
<h1>SVR.JS 3.14.0 Tests</h1>
|
||||||
<h2>Directory (without trailing slash)</h2>
|
<h2>Directory (without trailing slash)</h2>
|
||||||
<iframe src="/testdir" width="50%" height="300px"></iframe>
|
<iframe src="/testdir" width="50%" height="300px"></iframe>
|
||||||
<h2>Directory (with query)</h2>
|
<h2>Directory (with query)</h2>
|
||||||
|
|
Reference in a new issue