// this module parses the passed URL, returning an object that is uniform and easy to use const urlParse = require("url-parse"); const jsl = require("svjsl"); const fs = require("fs-extra"); const settings = require("../settings"); /** * @typedef {Object} ParsedUrl * @prop {null} error If not errored, this will be `null`, else it will contain a string with the error message * @prop {String} initialURL The requested URL * @prop {(Array|null)} pathArray If empty, this will be `null`, else it will be an array of the URL path * @prop {(Object|null)} queryParams If empty, this will be `null`, else it will be an object of query parameters */ /** * @typedef {Object} ErroredParsedUrl * @prop {String} error If not errored, this will be `null`, else it will contain a string with the error message * @prop {String} initialURL The requested URL */ /** * Parses the passed URL, returning a fancy object * @param {String} url * @returns {(ParsedUrl|ErroredParsedUrl)} */ function parseURL(url) { try { let trimFirstSlash = u2 => { if(u2[0] == "") u2.shift(); return u2; }; let parsed = urlParse(url); let qstrObj = {}; let qstrArr = []; let rawQstr = (parsed.query == "" ? null : parsed.query); if(rawQstr && rawQstr.startsWith("?")) rawQstr = rawQstr.substr(1); if(!jsl.isEmpty(rawQstr) && rawQstr.includes("&")) qstrArr = rawQstr.split("&"); else if(!jsl.isEmpty(rawQstr)) qstrArr = [rawQstr]; if(qstrArr.length > 0) { qstrArr.forEach(qstrEntry => { if(qstrEntry.includes("=")) { let splitEntry = qstrEntry.split("="); let val = decodeURIComponent(splitEntry[1].toLowerCase()); if(["true", "false"].includes(val.toLowerCase())) val = val.toLowerCase() === "true"; qstrObj[decodeURIComponent(splitEntry[0])] = val; } else { let valuelessEntry = qstrEntry.trim(); qstrObj[decodeURIComponent(valuelessEntry)] = true; } }); } else qstrObj = null; let retObj = { error: null, initialURL: url, pathArray: trimFirstSlash(parsed.pathname.split("/")), queryParams: qstrObj }; return retObj; } catch(err) { return { error: err.toString(), initialURL: url }; } } function getFileFormatFromQString(qstrObj) { if(!jsl.isEmpty(qstrObj.format)) { let possibleFormats = Object.keys(JSON.parse(fs.readFileSync(settings.jokes.fileFormatsPath).toString())); if(possibleFormats.includes(qstrObj.format)) return qstrObj.format; else return settings.jokes.defaultFileFormat.fileFormat; } else return settings.jokes.defaultFileFormat.fileFormat; } /** * Returns the MIME type of the provided file format string (example: "json" -> "application/json") * @param {String} fileFormatString * @returns {String} */ function getMimeTypeFromFileFormatString(fileFormatString) { let allFileTypes = JSON.parse(fs.readFileSync(settings.jokes.fileFormatsPath).toString()); if(!jsl.isEmpty(allFileTypes[fileFormatString])) return allFileTypes[fileFormatString].mimeType; else return settings.jokes.defaultFileFormat.mimeType; } module.exports = parseURL; module.exports.getFileFormatFromQString = getFileFormatFromQString; module.exports.getMimeTypeFromFileFormatString = getMimeTypeFromFileFormatString;