1
0
Fork 0
forked from svrjs/svrjs
This repository has been archived on 2024-11-10. You can view files and clone it, but cannot push or open issues or pull requests.
svrjs/src/utils/urlParser.js

90 lines
3.2 KiB
JavaScript

const url = require("url");
// SVR.JS URL parser function (needed only for SVR.JS 2.x and 3.x mods)
function parseURL(uri, prepend) {
// Replace newline characters with its respective URL encodings
uri = uri.replace(/\r/g, "%0D").replace(/\n/g, "%0A");
// If URL begins with a slash, prepend a string if available
if (prepend && uri[0] == "/") uri = prepend.replace(/\/+$/, "") + uri;
// Determine if URL has slashes
let hasSlashes = uri.indexOf("/") != -1;
// Parse the URL using regular expression
let parsedURI = uri.match(
/^(?:([^:]+:)(\/\/)?)?(?:([^@/?#*]+)@)?([^:/?#*]+|\[[^*]\/]\])?(?::([0-9]+))?(\*|\/[^?#]*)?(\?[^#]*)?(#[\S\s]*)?/,
);
// Match 1: protocol
// Match 2: slashes after protocol
// Match 3: authentication credentials
// Match 4: host name
// Match 5: port
// Match 6: path name
// Match 7: query string
// Match 8: hash
// If regular expression didn't match the entire URL, throw an error
if (parsedURI[0].length != uri.length) throw new Error("Invalid URL: " + uri);
// If match 1 is not empty, set the slash variable based on state of match 2
if (parsedURI[1]) hasSlashes = parsedURI[2] == "//";
// If match 6 is empty and URL has slashes, set it to a slash.
if (hasSlashes && !parsedURI[6]) parsedURI[6] = "/";
// If match 4 contains Unicode characters, convert it to Punycode. If the result is an empty string, throw an error
if (parsedURI[4] && !parsedURI[4].match(/^[a-zA-Z0-9.-]+$/)) {
parsedURI[4] = url.domainToASCII(parsedURI[4]);
if (!parsedURI[4]) throw new Error("Invalid URL: " + uri);
}
// Create a new URL object
let uobject = new url.Url();
// Populate a URL object
if (hasSlashes) uobject.slashes = true;
if (parsedURI[1]) uobject.protocol = parsedURI[1];
if (parsedURI[3]) uobject.auth = parsedURI[3];
if (parsedURI[4]) {
uobject.host = parsedURI[4] + (parsedURI[5] ? ":" + parsedURI[5] : "");
if (parsedURI[4][0] == "[")
uobject.hostname = parsedURI[4].substring(1, parsedURI[4].length - 1);
else uobject.hostname = parsedURI[4];
}
if (parsedURI[5]) uobject.port = parsedURI[5];
if (parsedURI[6]) uobject.pathname = parsedURI[6];
if (parsedURI[7]) {
uobject.search = parsedURI[7];
// Parse query strings
let qobject = Object.create(null);
const parsedQuery = parsedURI[7]
.substring(1)
.match(/([^&=]*)(?:=([^&]*))?/g);
parsedQuery.forEach((qp) => {
if (qp.length > 0) {
let parsedQP = qp.match(/([^&=]*)(?:=([^&]*))?/);
if (parsedQP) {
qobject[parsedQP[1]] = parsedQP[2] ? parsedQP[2] : "";
}
}
});
uobject.query = qobject;
} else {
uobject.query = Object.create(null);
}
if (parsedURI[8]) uobject.hash = parsedURI[8];
if (uobject.pathname)
uobject.path = uobject.pathname + (uobject.search ? uobject.search : "");
uobject.href =
(uobject.protocol ? uobject.protocol + (uobject.slashes ? "//" : "") : "") +
(uobject.auth ? uobject.auth + "@" : "") +
(uobject.hostname ? uobject.hostname : "") +
(uobject.port ? ":" + uobject.port : "") +
(uobject.path ? uobject.path : "") +
(uobject.hash ? uobject.hash : "");
return uobject;
}
module.exports = parseURL;