wexen
Version:
1,368 lines (1,367 loc) • 122 kB
JavaScript
import { readFileSync, existsSync, statSync } from "node:fs";
import { gzip } from "zlib";
import { createSecureServer } from "node:http2";
import { networkInterfaces } from "node:os";
import { WebSocketServer, WebSocket } from "ws";
import util from "node:util";
import { resolve } from "node:path";
class HttpError extends Error {
constructor(statusCode, message) {
super(message);
this.statusCode = statusCode;
}
}
var HttpMethod$1 = /* @__PURE__ */ ((HttpMethod2) => {
HttpMethod2["Delete"] = "DELETE";
HttpMethod2["Get"] = "GET";
HttpMethod2["Head"] = "HEAD";
HttpMethod2["Options"] = "OPTIONS";
HttpMethod2["Patch"] = "PATCH";
HttpMethod2["Post"] = "POST";
HttpMethod2["Put"] = "PUT";
return HttpMethod2;
})(HttpMethod$1 || {});
var HttpStatusCode$1 = /* @__PURE__ */ ((HttpStatusCode2) => {
HttpStatusCode2[HttpStatusCode2["Continue"] = 100] = "Continue";
HttpStatusCode2[HttpStatusCode2["SwitchingProtocols"] = 101] = "SwitchingProtocols";
HttpStatusCode2[HttpStatusCode2["Processing"] = 102] = "Processing";
HttpStatusCode2[HttpStatusCode2["EarlyHints"] = 103] = "EarlyHints";
HttpStatusCode2[HttpStatusCode2["Ok"] = 200] = "Ok";
HttpStatusCode2[HttpStatusCode2["Created"] = 201] = "Created";
HttpStatusCode2[HttpStatusCode2["Accepted"] = 202] = "Accepted";
HttpStatusCode2[HttpStatusCode2["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
HttpStatusCode2[HttpStatusCode2["NoContent"] = 204] = "NoContent";
HttpStatusCode2[HttpStatusCode2["ResetContent"] = 205] = "ResetContent";
HttpStatusCode2[HttpStatusCode2["PartialContent"] = 206] = "PartialContent";
HttpStatusCode2[HttpStatusCode2["MultiStatus"] = 207] = "MultiStatus";
HttpStatusCode2[HttpStatusCode2["MultipleChoices"] = 300] = "MultipleChoices";
HttpStatusCode2[HttpStatusCode2["MovedPermanently"] = 301] = "MovedPermanently";
HttpStatusCode2[HttpStatusCode2["MovedTemporarily"] = 302] = "MovedTemporarily";
HttpStatusCode2[HttpStatusCode2["SeeOther"] = 303] = "SeeOther";
HttpStatusCode2[HttpStatusCode2["NotModified"] = 304] = "NotModified";
HttpStatusCode2[HttpStatusCode2["UseProxy"] = 305] = "UseProxy";
HttpStatusCode2[HttpStatusCode2["TemporaryRedirect"] = 307] = "TemporaryRedirect";
HttpStatusCode2[HttpStatusCode2["PermanentRedirect"] = 308] = "PermanentRedirect";
HttpStatusCode2[HttpStatusCode2["BadRequest"] = 400] = "BadRequest";
HttpStatusCode2[HttpStatusCode2["Unauthorized"] = 401] = "Unauthorized";
HttpStatusCode2[HttpStatusCode2["PaymentRequired"] = 402] = "PaymentRequired";
HttpStatusCode2[HttpStatusCode2["Forbidden"] = 403] = "Forbidden";
HttpStatusCode2[HttpStatusCode2["NotFound"] = 404] = "NotFound";
HttpStatusCode2[HttpStatusCode2["MethodNotAllowed"] = 405] = "MethodNotAllowed";
HttpStatusCode2[HttpStatusCode2["NotAcceptable"] = 406] = "NotAcceptable";
HttpStatusCode2[HttpStatusCode2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
HttpStatusCode2[HttpStatusCode2["RequestTimeout"] = 408] = "RequestTimeout";
HttpStatusCode2[HttpStatusCode2["Conflict"] = 409] = "Conflict";
HttpStatusCode2[HttpStatusCode2["Gone"] = 410] = "Gone";
HttpStatusCode2[HttpStatusCode2["LengthRequired"] = 411] = "LengthRequired";
HttpStatusCode2[HttpStatusCode2["PreconditionFailed"] = 412] = "PreconditionFailed";
HttpStatusCode2[HttpStatusCode2["RequestTooLong"] = 413] = "RequestTooLong";
HttpStatusCode2[HttpStatusCode2["RequestUriTooLong"] = 414] = "RequestUriTooLong";
HttpStatusCode2[HttpStatusCode2["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
HttpStatusCode2[HttpStatusCode2["RequestedRangeNotSatisfiable"] = 416] = "RequestedRangeNotSatisfiable";
HttpStatusCode2[HttpStatusCode2["ExpectationFailed"] = 417] = "ExpectationFailed";
HttpStatusCode2[HttpStatusCode2["ImATeapot"] = 418] = "ImATeapot";
HttpStatusCode2[HttpStatusCode2["InsufficientSpaceOnResource"] = 419] = "InsufficientSpaceOnResource";
HttpStatusCode2[HttpStatusCode2["MethodFailure"] = 420] = "MethodFailure";
HttpStatusCode2[HttpStatusCode2["MisdirectedRequest"] = 421] = "MisdirectedRequest";
HttpStatusCode2[HttpStatusCode2["UnprocessableEntity"] = 422] = "UnprocessableEntity";
HttpStatusCode2[HttpStatusCode2["Locked"] = 423] = "Locked";
HttpStatusCode2[HttpStatusCode2["FailedDependency"] = 424] = "FailedDependency";
HttpStatusCode2[HttpStatusCode2["UpgradeRequired"] = 426] = "UpgradeRequired";
HttpStatusCode2[HttpStatusCode2["PreconditionRequired"] = 428] = "PreconditionRequired";
HttpStatusCode2[HttpStatusCode2["TooManyRequests"] = 429] = "TooManyRequests";
HttpStatusCode2[HttpStatusCode2["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
HttpStatusCode2[HttpStatusCode2["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
HttpStatusCode2[HttpStatusCode2["InternalServerError"] = 500] = "InternalServerError";
HttpStatusCode2[HttpStatusCode2["NotImplemented"] = 501] = "NotImplemented";
HttpStatusCode2[HttpStatusCode2["BadGateway"] = 502] = "BadGateway";
HttpStatusCode2[HttpStatusCode2["ServiceUnavailable"] = 503] = "ServiceUnavailable";
HttpStatusCode2[HttpStatusCode2["GatewayTimeout"] = 504] = "GatewayTimeout";
HttpStatusCode2[HttpStatusCode2["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported";
HttpStatusCode2[HttpStatusCode2["InsufficientStorage"] = 507] = "InsufficientStorage";
HttpStatusCode2[HttpStatusCode2["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
return HttpStatusCode2;
})(HttpStatusCode$1 || {});
function newHttpRequest(stream, headers) {
let _url = null;
let _data = null;
let _text = null;
let _json = null;
return {
session: stream.session,
method: headers[":method"],
headers,
get url() {
_url ??= urlFromHeaders(headers);
return _url;
},
async data() {
_data ??= await streamToData(stream);
return _data;
},
async json() {
_json ??= JSON.parse(await this.text());
return _json;
},
async text() {
_text ??= (await streamToData(stream)).toString();
return _text;
},
async file(cb) {
const fileName = headers["x-filename"]?.toString() ?? crypto.randomUUID();
const outputStream = cb(fileName);
stream.pipe(outputStream);
await streamFinish(outputStream);
return {
name: fileName,
type: contentTypeByFilePath(fileName),
size: outputStream.bytesWritten
};
}
};
}
function urlFromHeaders(headers) {
const scheme = headers[":scheme"] || "https";
const authority = headers[":authority"] || headers["host"] || "localhost";
const path = headers[":path"] || "/";
const urlString = `${scheme}://${authority}${path}`;
return new URL(urlString);
}
function streamToData(stream) {
return new Promise((resolve2, reject) => {
const chunks = [];
stream.on("data", (chunk) => chunks.push(chunk));
stream.on("error", (err) => reject(err));
stream.on("end", () => resolve2(Buffer.concat(chunks)));
});
}
function streamFinish(stream) {
return new Promise((resolve2, reject) => {
stream.on("error", (error) => reject(error));
stream.on("finish", () => resolve2());
});
}
function newFileResponse(filePath, statusCode = HttpStatusCode$1.Ok) {
return {
filePath,
headers: {
":status": statusCode,
"content-type": "text/html"
},
async send(stream, request) {
const acceptEncoding = request.headers["accept-encoding"];
const supportsGzip = acceptEncoding?.includes("gzip");
const fileContent = readFileSync(filePath);
if (supportsGzip) {
gzip(fileContent, (err, compressedData) => {
if (err) {
this.headers[":status"] = HttpStatusCode$1.InternalServerError;
this.headers["content-type"] = "text/plain";
stream.respond(this.headers);
stream.end("Compression Error");
return;
}
this.headers["content-encoding"] = "gzip";
stream.respond(this.headers);
stream.end(compressedData);
});
} else {
const contentType = contentTypeByFilePath(this.filePath);
this.headers["content-type"] = contentType;
stream.respond(this.headers);
stream.end(fileContent);
}
}
};
}
function newHtmlResponse(html, statusCode = HttpStatusCode$1.Ok) {
return {
headers: {
":status": statusCode,
"content-type": "text/html"
},
async send(stream, request) {
const acceptEncoding = request.headers["accept-encoding"];
const supportsGzip = acceptEncoding?.includes("gzip");
if (supportsGzip) {
gzip(html, (err, compressedData) => {
if (err) {
this.headers[":status"] = HttpStatusCode$1.InternalServerError;
this.headers["content-type"] = "text/plain";
stream.respond(this.headers);
stream.end("Compression Error");
return;
}
this.headers["content-encoding"] = "gzip";
stream.respond(this.headers);
stream.end(compressedData);
});
} else {
stream.respond(this.headers);
stream.end(html);
}
}
};
}
function newJsonResponse(value, statusCode = HttpStatusCode$1.Ok) {
return {
headers: {
":status": statusCode,
"content-type": "application/json"
},
async send(stream) {
stream.respond(this.headers);
stream.end(JSON.stringify(value));
}
};
}
const notFoundMessage = JSON.stringify({ error: "Not Found" });
function newNotFoundResponse(value) {
return {
headers: {
":status": HttpStatusCode$1.NotFound,
"content-type": "application/json"
},
async send(stream) {
stream.respond(this.headers);
stream.end(value ? JSON.stringify(value) : notFoundMessage);
}
};
}
const DIVIDER = `-`.repeat("https://000.000.000.000:65536".length);
function runWebServer(config) {
logger$h.info(`Web server is running:`, TerminalColor.FG_GREEN);
logger$h.info(DIVIDER);
const server = createSecureServer(config);
return server.on("stream", onServerStream(config)).listen(config.port, () => logListening(config));
}
function onServerStream(config) {
return async (stream, headers) => {
const performanceTime = process.hrtime.bigint();
const request = newHttpRequest(stream, headers);
try {
const response = await middlewareResponse(config, request);
addCors(config, request, response);
await response.send(stream, request);
logRequest(request, response, performanceTime);
} catch (error) {
const response = errorResponse(error);
addCors(config, request, response);
await response.send(stream, request);
logRequest(request, response, performanceTime, `
${String(error["stack"] ?? error)}`);
}
};
}
async function middlewareResponse(config, request) {
if (!config.middlewares?.length) {
throw new HttpError(HttpStatusCode$1.InternalServerError, "Middlewares Not Found");
}
for (const middleware of config.middlewares) {
const response = await middleware(request);
if (response) {
return response;
}
}
return newNotFoundResponse();
}
function errorResponse(error) {
const message = error instanceof HttpError ? error.message : "Internal Error";
const statusCode = error instanceof HttpError ? error.statusCode : HttpStatusCode$1.InternalServerError;
return newJsonResponse({ error: message }, statusCode);
}
function addCors(config, request, response) {
const origin = request.headers["origin"];
if (origin && config.origins?.includes(origin)) {
response.headers["access-control-allow-origin"] = origin;
}
}
function logListening(config) {
logger$h.info(`https://localhost:${config.port}`);
const interfaces = networkInterfaces();
Object.keys(interfaces).map((x) => interfaces[x] ?? []).flat().filter((x) => x.family === "IPv4" && !x.internal).forEach((x) => logger$h.info(`https://${x.address}:${config.port}`));
logger$h.info(DIVIDER);
}
function createWebSocketServer(server) {
const wss = new WebSocketServer({ server });
wss.on("connection", (ws) => {
logger$h.info(`New client connected`);
ws.on("message", (message) => {
wss.clients.forEach((peer) => {
if (peer !== ws && peer.readyState === WebSocket.OPEN) {
peer.send(message.toString());
}
});
});
ws.on("error", (error) => logger$h.error(String(error)));
ws.on("close", (code, reason) => {
if (reason.toString()) {
logger$h.info(`Client disconnected. Code ${code}. Reason ${reason.toString()}`);
} else {
logger$h.info(`Client disconnected`);
}
});
});
return wss;
}
function contentTypeByFileExtension(extension) {
return EXTENSION_CONTENT_TYPE[extension] ?? "application/octet-stream";
}
function contentTypeByFilePath(path) {
const extension = path.split(".").pop()?.toLowerCase();
if (extension) {
return contentTypeByFileExtension(extension);
}
return "application/octet-stream";
}
const EXTENSION_CONTENT_TYPE = {
"123": "application/vnd.lotus-1-2-3",
"3dml": "text/vnd.in3d.3dml",
"3ds": "image/x-3ds",
"3g2": "video/3gpp2",
"3gp": "video/3gpp",
"7z": "application/x-7z-compressed",
aab: "application/x-authorware-bin",
aac: "audio/x-aac",
aam: "application/x-authorware-map",
aas: "application/x-authorware-seg",
abw: "application/x-abiword",
ac: "application/pkix-attr-cert",
acc: "application/vnd.americandynamics.acc",
ace: "application/x-ace-compressed",
acu: "application/vnd.acucobol",
acutc: "application/vnd.acucorp",
adp: "audio/adpcm",
aep: "application/vnd.audiograph",
afm: "application/x-font-type1",
afp: "application/vnd.ibm.modcap",
ahead: "application/vnd.ahead.space",
ai: "application/postscript",
aif: "audio/x-aiff",
aifc: "audio/x-aiff",
aiff: "audio/x-aiff",
air: "application/vnd.adobe.air-application-installer-package+zip",
ait: "application/vnd.dvb.ait",
ami: "application/vnd.amiga.ami",
apk: "application/vnd.android.package-archive",
appcache: "text/cache-manifest",
application: "application/x-ms-application",
apr: "application/vnd.lotus-approach",
arc: "application/x-freearc",
asc: "application/pgp-signature",
asf: "video/x-ms-asf",
asm: "text/x-asm",
aso: "application/vnd.accpac.simply.aso",
asx: "video/x-ms-asf",
atc: "application/vnd.acucorp",
atom: "application/atom+xml",
atomcat: "application/atomcat+xml",
atomsvc: "application/atomsvc+xml",
atx: "application/vnd.antix.game-component",
au: "audio/basic",
avi: "video/x-msvideo",
avif: "image/avif",
aw: "application/applixware",
azf: "application/vnd.airzip.filesecure.azf",
azs: "application/vnd.airzip.filesecure.azs",
azw: "application/vnd.amazon.ebook",
bat: "application/x-msdownload",
bcpio: "application/x-bcpio",
bdf: "application/x-font-bdf",
bdm: "application/vnd.syncml.dm+wbxml",
bed: "application/vnd.realvnc.bed",
bh2: "application/vnd.fujitsu.oasysprs",
bin: "application/octet-stream",
blb: "application/x-blorb",
blorb: "application/x-blorb",
bmi: "application/vnd.bmi",
bmp: "image/bmp",
book: "application/vnd.framemaker",
box: "application/vnd.previewsystems.box",
boz: "application/x-bzip2",
bpk: "application/octet-stream",
btif: "image/prs.btif",
bz: "application/x-bzip",
bz2: "application/x-bzip2",
c: "text/x-c",
c11amc: "application/vnd.cluetrust.cartomobile-config",
c11amz: "application/vnd.cluetrust.cartomobile-config-pkg",
c4d: "application/vnd.clonk.c4group",
c4f: "application/vnd.clonk.c4group",
c4g: "application/vnd.clonk.c4group",
c4p: "application/vnd.clonk.c4group",
c4u: "application/vnd.clonk.c4group",
cab: "application/vnd.ms-cab-compressed",
caf: "audio/x-caf",
cap: "application/vnd.tcpdump.pcap",
car: "application/vnd.curl.car",
cat: "application/vnd.ms-pki.seccat",
cb7: "application/x-cbr",
cba: "application/x-cbr",
cbr: "application/x-cbr",
cbt: "application/x-cbr",
cbz: "application/x-cbr",
cc: "text/x-c",
cct: "application/x-director",
ccxml: "application/ccxml+xml",
cdbcmsg: "application/vnd.contact.cmsg",
cdf: "application/x-netcdf",
cdkey: "application/vnd.mediastation.cdkey",
cdmia: "application/cdmi-capability",
cdmic: "application/cdmi-container",
cdmid: "application/cdmi-domain",
cdmio: "application/cdmi-object",
cdmiq: "application/cdmi-queue",
cdx: "chemical/x-cdx",
cdxml: "application/vnd.chemdraw+xml",
cdy: "application/vnd.cinderella",
cer: "application/pkix-cert",
cfs: "application/x-cfs-compressed",
cgm: "image/cgm",
chat: "application/x-chat",
chm: "application/vnd.ms-htmlhelp",
chrt: "application/vnd.kde.kchart",
cif: "chemical/x-cif",
cii: "application/vnd.anser-web-certificate-issue-initiation",
cil: "application/vnd.ms-artgalry",
cla: "application/vnd.claymore",
class: "application/java-vm",
clkk: "application/vnd.crick.clicker.keyboard",
clkp: "application/vnd.crick.clicker.palette",
clkt: "application/vnd.crick.clicker.template",
clkw: "application/vnd.crick.clicker.wordbank",
clkx: "application/vnd.crick.clicker",
clp: "application/x-msclip",
cmc: "application/vnd.cosmocaller",
cmdf: "chemical/x-cmdf",
cml: "chemical/x-cml",
cmp: "application/vnd.yellowriver-custom-menu",
cmx: "image/x-cmx",
cod: "application/vnd.rim.cod",
com: "application/x-msdownload",
conf: "text/plain",
cpio: "application/x-cpio",
cpp: "text/x-c",
cpt: "application/mac-compactpro",
crd: "application/x-mscardfile",
crl: "application/pkix-crl",
crt: "application/x-x509-ca-cert",
cryptonote: "application/vnd.rig.cryptonote",
csh: "application/x-csh",
csml: "chemical/x-csml",
csp: "application/vnd.commonspace",
css: "text/css",
cst: "application/x-director",
csv: "text/csv",
cu: "application/cu-seeme",
curl: "text/vnd.curl",
cww: "application/prs.cww",
cxt: "application/x-director",
cxx: "text/x-c",
dae: "model/vnd.collada+xml",
daf: "application/vnd.mobius.daf",
dart: "application/vnd.dart",
dataless: "application/vnd.fdsn.seed",
davmount: "application/davmount+xml",
dbk: "application/docbook+xml",
dcr: "application/x-director",
dcurl: "text/vnd.curl.dcurl",
dd2: "application/vnd.oma.dd2+xml",
ddd: "application/vnd.fujixerox.ddd",
deb: "application/x-debian-package",
def: "text/plain",
deploy: "application/octet-stream",
der: "application/x-x509-ca-cert",
dfac: "application/vnd.dreamfactory",
dgc: "application/x-dgc-compressed",
dic: "text/x-c",
dir: "application/x-director",
dis: "application/vnd.mobius.dis",
dist: "application/octet-stream",
distz: "application/octet-stream",
djv: "image/vnd.djvu",
djvu: "image/vnd.djvu",
dll: "application/x-msdownload",
dmg: "application/x-apple-diskimage",
dmp: "application/vnd.tcpdump.pcap",
dms: "application/octet-stream",
dna: "application/vnd.dna",
doc: "application/msword",
docm: "application/vnd.ms-word.document.macroenabled.12",
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
dot: "application/msword",
dotm: "application/vnd.ms-word.template.macroenabled.12",
dotx: "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
dp: "application/vnd.osgi.dp",
dpg: "application/vnd.dpgraph",
dra: "audio/vnd.dra",
dsc: "text/prs.lines.tag",
dssc: "application/dssc+der",
dtb: "application/x-dtbook+xml",
dtd: "application/xml-dtd",
dts: "audio/vnd.dts",
dtshd: "audio/vnd.dts.hd",
dump: "application/octet-stream",
dvb: "video/vnd.dvb.file",
dvi: "application/x-dvi",
dwf: "model/vnd.dwf",
dwg: "image/vnd.dwg",
dxf: "image/vnd.dxf",
dxp: "application/vnd.spotfire.dxp",
dxr: "application/x-director",
ecelp4800: "audio/vnd.nuera.ecelp4800",
ecelp7470: "audio/vnd.nuera.ecelp7470",
ecelp9600: "audio/vnd.nuera.ecelp9600",
ecma: "application/ecmascript",
edm: "application/vnd.novadigm.edm",
edx: "application/vnd.novadigm.edx",
efif: "application/vnd.picsel",
ei6: "application/vnd.pg.osasli",
elc: "application/octet-stream",
emf: "application/x-msmetafile",
eml: "message/rfc822",
emma: "application/emma+xml",
emz: "application/x-msmetafile",
eol: "audio/vnd.digital-winds",
eot: "application/vnd.ms-fontobject",
eps: "application/postscript",
epub: "application/epub+zip",
es3: "application/vnd.eszigno3+xml",
esa: "application/vnd.osgi.subsystem",
esf: "application/vnd.epson.esf",
et3: "application/vnd.eszigno3+xml",
etx: "text/x-setext",
eva: "application/x-eva",
evy: "application/x-envoy",
exe: "application/x-msdownload",
exi: "application/exi",
ext: "application/vnd.novadigm.ext",
ez: "application/andrew-inset",
ez2: "application/vnd.ezpix-album",
ez3: "application/vnd.ezpix-package",
f: "text/x-fortran",
f4v: "video/x-f4v",
f77: "text/x-fortran",
f90: "text/x-fortran",
fbs: "image/vnd.fastbidsheet",
fcdt: "application/vnd.adobe.formscentral.fcdt",
fcs: "application/vnd.isac.fcs",
fdf: "application/vnd.fdf",
fe_launch: "application/vnd.denovo.fcselayout-link",
fg5: "application/vnd.fujitsu.oasysgp",
fgd: "application/x-director",
fh: "image/x-freehand",
fh4: "image/x-freehand",
fh5: "image/x-freehand",
fh7: "image/x-freehand",
fhc: "image/x-freehand",
fig: "application/x-xfig",
flac: "audio/x-flac",
fli: "video/x-fli",
flo: "application/vnd.micrografx.flo",
flv: "video/x-flv",
flw: "application/vnd.kde.kivio",
flx: "text/vnd.fmi.flexstor",
fly: "text/vnd.fly",
fm: "application/vnd.framemaker",
fnc: "application/vnd.frogans.fnc",
for: "text/x-fortran",
fpx: "image/vnd.fpx",
frame: "application/vnd.framemaker",
fsc: "application/vnd.fsc.weblaunch",
fst: "image/vnd.fst",
ftc: "application/vnd.fluxtime.clip",
fti: "application/vnd.anser-web-funds-transfer-initiation",
fvt: "video/vnd.fvt",
fxp: "application/vnd.adobe.fxp",
fxpl: "application/vnd.adobe.fxp",
fzs: "application/vnd.fuzzysheet",
g2w: "application/vnd.geoplan",
g3: "image/g3fax",
g3w: "application/vnd.geospace",
gac: "application/vnd.groove-account",
gam: "application/x-tads",
gbr: "application/rpki-ghostbusters",
gca: "application/x-gca-compressed",
gdl: "model/vnd.gdl",
geo: "application/vnd.dynageo",
gex: "application/vnd.geometry-explorer",
ggb: "application/vnd.geogebra.file",
ggs: "application/vnd.geogebra.slides",
ggt: "application/vnd.geogebra.tool",
ghf: "application/vnd.groove-help",
gif: "image/gif",
gim: "application/vnd.groove-identity-message",
gml: "application/gml+xml",
gmx: "application/vnd.gmx",
gnumeric: "application/x-gnumeric",
gph: "application/vnd.flographit",
gpx: "application/gpx+xml",
gqf: "application/vnd.grafeq",
gqs: "application/vnd.grafeq",
gram: "application/srgs",
gramps: "application/x-gramps-xml",
gre: "application/vnd.geometry-explorer",
grv: "application/vnd.groove-injector",
grxml: "application/srgs+xml",
gsf: "application/x-font-ghostscript",
gtar: "application/x-gtar",
gtm: "application/vnd.groove-tool-message",
gtw: "model/vnd.gtw",
gv: "text/vnd.graphviz",
gxf: "application/gxf",
gxt: "application/vnd.geonext",
h: "text/x-c",
h261: "video/h261",
h263: "video/h263",
h264: "video/h264",
hal: "application/vnd.hal+xml",
hbci: "application/vnd.hbci",
hdf: "application/x-hdf",
hh: "text/x-c",
hlp: "application/winhlp",
hpgl: "application/vnd.hp-hpgl",
hpid: "application/vnd.hp-hpid",
hps: "application/vnd.hp-hps",
hqx: "application/mac-binhex40",
htke: "application/vnd.kenameaapp",
htm: "text/html",
html: "text/html",
hvd: "application/vnd.yamaha.hv-dic",
hvp: "application/vnd.yamaha.hv-voice",
hvs: "application/vnd.yamaha.hv-script",
i2g: "application/vnd.intergeo",
icc: "application/vnd.iccprofile",
ice: "x-conference/x-cooltalk",
icm: "application/vnd.iccprofile",
ico: "image/x-icon",
ics: "text/calendar",
ief: "image/ief",
ifb: "text/calendar",
ifm: "application/vnd.shana.informed.formdata",
iges: "model/iges",
igl: "application/vnd.igloader",
igm: "application/vnd.insors.igm",
igs: "model/iges",
igx: "application/vnd.micrografx.igx",
iif: "application/vnd.shana.informed.interchange",
imp: "application/vnd.accpac.simply.imp",
ims: "application/vnd.ms-ims",
in: "text/plain",
ink: "application/inkml+xml",
inkml: "application/inkml+xml",
install: "application/x-install-instructions",
iota: "application/vnd.astraea-software.iota",
ipfix: "application/ipfix",
ipk: "application/vnd.shana.informed.package",
irm: "application/vnd.ibm.rights-management",
irp: "application/vnd.irepository.package+xml",
iso: "application/x-iso9660-image",
itp: "application/vnd.shana.informed.formtemplate",
ivp: "application/vnd.immervision-ivp",
ivu: "application/vnd.immervision-ivu",
jad: "text/vnd.sun.j2me.app-descriptor",
jam: "application/vnd.jam",
jar: "application/java-archive",
java: "text/x-java-source",
jisp: "application/vnd.jisp",
jlt: "application/vnd.hp-jlyt",
jnlp: "application/x-java-jnlp-file",
joda: "application/vnd.joost.joda-archive",
jpe: "image/jpeg",
jpeg: "image/jpeg",
jpg: "image/jpeg",
jpgm: "video/jpm",
jpgv: "video/jpeg",
jpm: "video/jpm",
js: "text/javascript",
json: "application/json",
jsonc: "application/json",
jsonml: "application/jsonml+json",
jxl: "image/jxl",
kar: "audio/midi",
karbon: "application/vnd.kde.karbon",
kfo: "application/vnd.kde.kformula",
kia: "application/vnd.kidspiration",
kml: "application/vnd.google-earth.kml+xml",
kmz: "application/vnd.google-earth.kmz",
kne: "application/vnd.kinar",
knp: "application/vnd.kinar",
kon: "application/vnd.kde.kontour",
kpr: "application/vnd.kde.kpresenter",
kpt: "application/vnd.kde.kpresenter",
kpxx: "application/vnd.ds-keypoint",
ksp: "application/vnd.kde.kspread",
ktr: "application/vnd.kahootz",
ktx: "image/ktx",
ktz: "application/vnd.kahootz",
kwd: "application/vnd.kde.kword",
kwt: "application/vnd.kde.kword",
lasxml: "application/vnd.las.las+xml",
latex: "application/x-latex",
lbd: "application/vnd.llamagraphics.life-balance.desktop",
lbe: "application/vnd.llamagraphics.life-balance.exchange+xml",
les: "application/vnd.hhe.lesson-player",
lha: "application/x-lzh-compressed",
link66: "application/vnd.route66.link66+xml",
list: "text/plain",
list3820: "application/vnd.ibm.modcap",
listafp: "application/vnd.ibm.modcap",
lnk: "application/x-ms-shortcut",
log: "text/plain",
lostxml: "application/lost+xml",
lrf: "application/octet-stream",
lrm: "application/vnd.ms-lrm",
ltf: "application/vnd.frogans.ltf",
lvp: "audio/vnd.lucent.voice",
lwp: "application/vnd.lotus-wordpro",
lzh: "application/x-lzh-compressed",
m13: "application/x-msmediaview",
m14: "application/x-msmediaview",
m1v: "video/mpeg",
m21: "application/mp21",
m2a: "audio/mpeg",
m2t: "video/mp2t",
m2ts: "video/mp2t",
m2v: "video/mpeg",
m3a: "audio/mpeg",
m3u: "audio/x-mpegurl",
m3u8: "application/vnd.apple.mpegurl",
m4a: "audio/mp4",
m4u: "video/vnd.mpegurl",
m4v: "video/x-m4v",
ma: "application/mathematica",
mads: "application/mads+xml",
mag: "application/vnd.ecowin.chart",
maker: "application/vnd.framemaker",
man: "text/troff",
mar: "application/octet-stream",
mathml: "application/mathml+xml",
mb: "application/mathematica",
mbk: "application/vnd.mobius.mbk",
mbox: "application/mbox",
mc1: "application/vnd.medcalcdata",
mcd: "application/vnd.mcd",
mcurl: "text/vnd.curl.mcurl",
mdb: "application/x-msaccess",
mdi: "image/vnd.ms-modi",
me: "text/troff",
mesh: "model/mesh",
meta4: "application/metalink4+xml",
metalink: "application/metalink+xml",
mets: "application/mets+xml",
mfm: "application/vnd.mfmp",
mft: "application/rpki-manifest",
mgp: "application/vnd.osgeo.mapguide.package",
mgz: "application/vnd.proteus.magazine",
mid: "audio/midi",
midi: "audio/midi",
mie: "application/x-mie",
mif: "application/vnd.mif",
mime: "message/rfc822",
mj2: "video/mj2",
mjp2: "video/mj2",
mjs: "text/javascript",
mk3d: "video/x-matroska",
mka: "audio/x-matroska",
mks: "video/x-matroska",
mkv: "video/x-matroska",
mlp: "application/vnd.dolby.mlp",
mmd: "application/vnd.chipnuts.karaoke-mmd",
mmf: "application/vnd.smaf",
mmr: "image/vnd.fujixerox.edmics-mmr",
mng: "video/x-mng",
mny: "application/x-msmoney",
mobi: "application/x-mobipocket-ebook",
mods: "application/mods+xml",
mov: "video/quicktime",
movie: "video/x-sgi-movie",
mp2: "audio/mpeg",
mp21: "application/mp21",
mp2a: "audio/mpeg",
mp3: "audio/mpeg",
mp4: "video/mp4",
mp4a: "audio/mp4",
mp4s: "application/mp4",
mp4v: "video/mp4",
mpc: "application/vnd.mophun.certificate",
mpe: "video/mpeg",
mpeg: "video/mpeg",
mpg: "video/mpeg",
mpg4: "video/mp4",
mpga: "audio/mpeg",
mpkg: "application/vnd.apple.installer+xml",
mpm: "application/vnd.blueice.multipass",
mpn: "application/vnd.mophun.application",
mpp: "application/vnd.ms-project",
mpt: "application/vnd.ms-project",
mpy: "application/vnd.ibm.minipay",
mqy: "application/vnd.mobius.mqy",
mrc: "application/marc",
mrcx: "application/marcxml+xml",
ms: "text/troff",
mscml: "application/mediaservercontrol+xml",
mseed: "application/vnd.fdsn.mseed",
mseq: "application/vnd.mseq",
msf: "application/vnd.epson.msf",
msh: "model/mesh",
msi: "application/x-msdownload",
msl: "application/vnd.mobius.msl",
msty: "application/vnd.muvee.style",
mts: "video/mp2t",
mus: "application/vnd.musician",
musicxml: "application/vnd.recordare.musicxml+xml",
mvb: "application/x-msmediaview",
mwf: "application/vnd.mfer",
mxf: "application/mxf",
mxl: "application/vnd.recordare.musicxml",
mxml: "application/xv+xml",
mxs: "application/vnd.triscape.mxs",
mxu: "video/vnd.mpegurl",
n: "gage application/vnd.nokia.n-gage.symbian.install",
n3: "text/n3",
nb: "application/mathematica",
nbp: "application/vnd.wolfram.player",
nc: "application/x-netcdf",
ncx: "application/x-dtbncx+xml",
nfo: "text/x-nfo",
ngdat: "application/vnd.nokia.n-gage.data",
nitf: "application/vnd.nitf",
nlu: "application/vnd.neurolanguage.nlu",
nml: "application/vnd.enliven",
nnd: "application/vnd.noblenet-directory",
nns: "application/vnd.noblenet-sealer",
nnw: "application/vnd.noblenet-web",
npx: "image/vnd.net-fpx",
nsc: "application/x-conference",
nsf: "application/vnd.lotus-notes",
ntf: "application/vnd.nitf",
nzb: "application/x-nzb",
oa2: "application/vnd.fujitsu.oasys2",
oa3: "application/vnd.fujitsu.oasys3",
oas: "application/vnd.fujitsu.oasys",
obd: "application/x-msbinder",
obj: "application/x-tgif",
oda: "application/oda",
odb: "application/vnd.oasis.opendocument.database",
odc: "application/vnd.oasis.opendocument.chart",
odf: "application/vnd.oasis.opendocument.formula",
odft: "application/vnd.oasis.opendocument.formula-template",
odg: "application/vnd.oasis.opendocument.graphics",
odi: "application/vnd.oasis.opendocument.image",
odm: "application/vnd.oasis.opendocument.text-master",
odp: "application/vnd.oasis.opendocument.presentation",
ods: "application/vnd.oasis.opendocument.spreadsheet",
odt: "application/vnd.oasis.opendocument.text",
oga: "audio/ogg",
ogg: "audio/ogg",
ogv: "video/ogg",
ogx: "application/ogg",
omdoc: "application/omdoc+xml",
onepkg: "application/onenote",
onetmp: "application/onenote",
onetoc: "application/onenote",
onetoc2: "application/onenote",
opf: "application/oebps-package+xml",
opml: "text/x-opml",
oprc: "application/vnd.palm",
opus: "audio/ogg",
org: "application/vnd.lotus-organizer",
osf: "application/vnd.yamaha.openscoreformat",
osfpvg: "application/vnd.yamaha.openscoreformat.osfpvg+xml",
otc: "application/vnd.oasis.opendocument.chart-template",
otf: "font/otf",
otg: "application/vnd.oasis.opendocument.graphics-template",
oth: "application/vnd.oasis.opendocument.text-web",
oti: "application/vnd.oasis.opendocument.image-template",
otp: "application/vnd.oasis.opendocument.presentation-template",
ots: "application/vnd.oasis.opendocument.spreadsheet-template",
ott: "application/vnd.oasis.opendocument.text-template",
oxps: "application/oxps",
oxt: "application/vnd.openofficeorg.extension",
p: "text/x-pascal",
p10: "application/pkcs10",
p12: "application/x-pkcs12",
p7b: "application/x-pkcs7-certificates",
p7c: "application/pkcs7-mime",
p7m: "application/pkcs7-mime",
p7r: "application/x-pkcs7-certreqresp",
p7s: "application/pkcs7-signature",
p8: "application/pkcs8",
pas: "text/x-pascal",
paw: "application/vnd.pawaafile",
pbd: "application/vnd.powerbuilder6",
pbm: "image/x-portable-bitmap",
pcap: "application/vnd.tcpdump.pcap",
pcf: "application/x-font-pcf",
pcl: "application/vnd.hp-pcl",
pclxl: "application/vnd.hp-pclxl",
pct: "image/x-pict",
pcurl: "application/vnd.curl.pcurl",
pcx: "image/x-pcx",
pdb: "application/vnd.palm",
pdf: "application/pdf",
pfa: "application/x-font-type1",
pfb: "application/x-font-type1",
pfm: "application/x-font-type1",
pfr: "application/font-tdpfr",
pfx: "application/x-pkcs12",
pgm: "image/x-portable-graymap",
pgn: "application/x-chess-pgn",
pgp: "application/pgp-encrypted",
pic: "image/x-pict",
pkg: "application/octet-stream",
pki: "application/pkixcmp",
pkipath: "application/pkix-pkipath",
plb: "application/vnd.3gpp.pic-bw-large",
plc: "application/vnd.mobius.plc",
plf: "application/vnd.pocketlearn",
pls: "application/pls+xml",
pml: "application/vnd.ctc-posml",
png: "image/png",
pnm: "image/x-portable-anymap",
portpkg: "application/vnd.macports.portpkg",
pot: "application/vnd.ms-powerpoint",
potm: "application/vnd.ms-powerpoint.template.macroenabled.12",
potx: "application/vnd.openxmlformats-officedocument.presentationml.template",
ppam: "application/vnd.ms-powerpoint.addin.macroenabled.12",
ppd: "application/vnd.cups-ppd",
ppm: "image/x-portable-pixmap",
pps: "application/vnd.ms-powerpoint",
ppsm: "application/vnd.ms-powerpoint.slideshow.macroenabled.12",
ppsx: "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
ppt: "application/vnd.ms-powerpoint",
pptm: "application/vnd.ms-powerpoint.presentation.macroenabled.12",
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
pqa: "application/vnd.palm",
prc: "application/x-mobipocket-ebook",
pre: "application/vnd.lotus-freelance",
prf: "application/pics-rules",
ps: "application/postscript",
psb: "application/vnd.3gpp.pic-bw-small",
psd: "image/vnd.adobe.photoshop",
psf: "application/x-font-linux-psf",
pskcxml: "application/pskc+xml",
ptid: "application/vnd.pvi.ptid1",
pub: "application/x-mspublisher",
pvb: "application/vnd.3gpp.pic-bw-var",
pwn: "application/vnd.3m.post-it-notes",
pya: "audio/vnd.ms-playready.media.pya",
pyv: "video/vnd.ms-playready.media.pyv",
qam: "application/vnd.epson.quickanime",
qbo: "application/vnd.intu.qbo",
qfx: "application/vnd.intu.qfx",
qps: "application/vnd.publishare-delta-tree",
qt: "video/quicktime",
qwd: "application/vnd.quark.quarkxpress",
qwt: "application/vnd.quark.quarkxpress",
qxb: "application/vnd.quark.quarkxpress",
qxd: "application/vnd.quark.quarkxpress",
qxl: "application/vnd.quark.quarkxpress",
qxt: "application/vnd.quark.quarkxpress",
ra: "audio/x-pn-realaudio",
ram: "audio/x-pn-realaudio",
rar: "application/x-rar-compressed",
ras: "image/x-cmu-raster",
rcprofile: "application/vnd.ipunplugged.rcprofile",
rdf: "application/rdf+xml",
rdz: "application/vnd.data-vision.rdz",
rep: "application/vnd.businessobjects",
res: "application/x-dtbresource+xml",
rgb: "image/x-rgb",
rif: "application/reginfo+xml",
rip: "audio/vnd.rip",
ris: "application/x-research-info-systems",
rl: "application/resource-lists+xml",
rlc: "image/vnd.fujixerox.edmics-rlc",
rld: "application/resource-lists-diff+xml",
rm: "application/vnd.rn-realmedia",
rmi: "audio/midi",
rmp: "audio/x-pn-realaudio-plugin",
rms: "application/vnd.jcp.javame.midlet-rms",
rmvb: "application/vnd.rn-realmedia-vbr",
rnc: "application/relax-ng-compact-syntax",
roa: "application/rpki-roa",
roff: "text/troff",
rp9: "application/vnd.cloanto.rp9",
rpss: "application/vnd.nokia.radio-presets",
rpst: "application/vnd.nokia.radio-preset",
rq: "application/sparql-query",
rs: "application/rls-services+xml",
rsd: "application/rsd+xml",
rss: "application/rss+xml",
rtf: "application/rtf",
rtx: "text/richtext",
s: "text/x-asm",
s3m: "audio/s3m",
saf: "application/vnd.yamaha.smaf-audio",
sbml: "application/sbml+xml",
sc: "application/vnd.ibm.secure-container",
scd: "application/x-msschedule",
scm: "application/vnd.lotus-screencam",
scq: "application/scvp-cv-request",
scs: "application/scvp-cv-response",
scurl: "text/vnd.curl.scurl",
sda: "application/vnd.stardivision.draw",
sdc: "application/vnd.stardivision.calc",
sdd: "application/vnd.stardivision.impress",
sdkd: "application/vnd.solent.sdkm+xml",
sdkm: "application/vnd.solent.sdkm+xml",
sdp: "application/sdp",
sdw: "application/vnd.stardivision.writer",
see: "application/vnd.seemail",
seed: "application/vnd.fdsn.seed",
sema: "application/vnd.sema",
semd: "application/vnd.semd",
semf: "application/vnd.semf",
ser: "application/java-serialized-object",
setpay: "application/set-payment-initiation",
setreg: "application/set-registration-initiation",
sfd: "hdstx application/vnd.hydrostatix.sof-data",
sfs: "application/vnd.spotfire.sfs",
sfv: "text/x-sfv",
sgi: "image/sgi",
sgl: "application/vnd.stardivision.writer-global",
sgm: "text/sgml",
sgml: "text/sgml",
sh: "application/x-sh",
shar: "application/x-shar",
shf: "application/shf+xml",
sid: "image/x-mrsid-image",
sig: "application/pgp-signature",
sil: "audio/silk",
silo: "model/mesh",
sis: "application/vnd.symbian.install",
sisx: "application/vnd.symbian.install",
sit: "application/x-stuffit",
sitx: "application/x-stuffitx",
skd: "application/vnd.koan",
skm: "application/vnd.koan",
skp: "application/vnd.koan",
skt: "application/vnd.koan",
sldm: "application/vnd.ms-powerpoint.slide.macroenabled.12",
sldx: "application/vnd.openxmlformats-officedocument.presentationml.slide",
slt: "application/vnd.epson.salt",
sm: "application/vnd.stepmania.stepchart",
smf: "application/vnd.stardivision.math",
smi: "application/smil+xml",
smil: "application/smil+xml",
smv: "video/x-smv",
smzip: "application/vnd.stepmania.package",
snd: "audio/basic",
snf: "application/x-font-snf",
so: "application/octet-stream",
spc: "application/x-pkcs7-certificates",
spf: "application/vnd.yamaha.smaf-phrase",
spl: "application/x-futuresplash",
spot: "text/vnd.in3d.spot",
spp: "application/scvp-vp-response",
spq: "application/scvp-vp-request",
spx: "audio/ogg",
sql: "application/x-sql",
src: "application/x-wais-source",
srt: "application/x-subrip",
sru: "application/sru+xml",
srx: "application/sparql-results+xml",
ssdl: "application/ssdl+xml",
sse: "application/vnd.kodak-descriptor",
ssf: "application/vnd.epson.ssf",
ssml: "application/ssml+xml",
st: "application/vnd.sailingtracker.track",
stc: "application/vnd.sun.xml.calc.template",
std: "application/vnd.sun.xml.draw.template",
stf: "application/vnd.wt.stf",
sti: "application/vnd.sun.xml.impress.template",
stk: "application/hyperstudio",
stl: "application/vnd.ms-pki.stl",
str: "application/vnd.pg.format",
stw: "application/vnd.sun.xml.writer.template",
// sub: 'image/vnd.dvb.subtitle',
sub: "text/vnd.dvb.subtitle",
sus: "application/vnd.sus-calendar",
susp: "application/vnd.sus-calendar",
sv4cpio: "application/x-sv4cpio",
sv4crc: "application/x-sv4crc",
svc: "application/vnd.dvb.service",
svd: "application/vnd.svd",
svg: "image/svg+xml",
svgz: "image/svg+xml",
swa: "application/x-director",
swf: "application/x-shockwave-flash",
swi: "application/vnd.aristanetworks.swi",
sxc: "application/vnd.sun.xml.calc",
sxd: "application/vnd.sun.xml.draw",
sxg: "application/vnd.sun.xml.writer.global",
sxi: "application/vnd.sun.xml.impress",
sxm: "application/vnd.sun.xml.math",
sxw: "application/vnd.sun.xml.writer",
t: "text/troff",
t3: "application/x-t3vm-image",
taglet: "application/vnd.mynfc",
tao: "application/vnd.tao.intent-module-archive",
tar: "application/x-tar",
tcap: "application/vnd.3gpp2.tcap",
tcl: "application/x-tcl",
teacher: "application/vnd.smart.teacher",
tei: "application/tei+xml",
teicorpus: "application/tei+xml",
tex: "application/x-tex",
texi: "application/x-texinfo",
texinfo: "application/x-texinfo",
text: "text/plain",
tfi: "application/thraud+xml",
tfm: "application/x-tex-tfm",
tga: "image/x-tga",
thmx: "application/vnd.ms-officetheme",
tif: "image/tiff",
tiff: "image/tiff",
tmo: "application/vnd.tmobile-livetv",
torrent: "application/x-bittorrent",
tpl: "application/vnd.groove-tool-template",
tpt: "application/vnd.trid.tpt",
tr: "text/troff",
tra: "application/vnd.trueapp",
trm: "application/x-msterminal",
ts: "video/mp2t",
tsd: "application/timestamped-data",
tsv: "text/tab-separated-values",
ttc: "font/collection",
ttf: "font/ttf",
ttl: "text/turtle",
twd: "application/vnd.simtech-mindmapper",
twds: "application/vnd.simtech-mindmapper",
txd: "application/vnd.genomatix.tuxedo",
txf: "application/vnd.mobius.txf",
txt: "text/plain",
u32: "application/x-authorware-bin",
udeb: "application/x-debian-package",
ufd: "application/vnd.ufdl",
ufdl: "application/vnd.ufdl",
ulx: "application/x-glulx",
umj: "application/vnd.umajin",
unityweb: "application/vnd.unity",
uoml: "application/vnd.uoml+xml",
uri: "text/uri-list",
uris: "text/uri-list",
urls: "text/uri-list",
ustar: "application/x-ustar",
utz: "application/vnd.uiq.theme",
uu: "text/x-uuencode",
uva: "audio/vnd.dece.audio",
uvd: "application/vnd.dece.data",
uvf: "application/vnd.dece.data",
uvg: "image/vnd.dece.graphic",
uvh: "video/vnd.dece.hd",
uvi: "image/vnd.dece.graphic",
uvm: "video/vnd.dece.mobile",
uvp: "video/vnd.dece.pd",
uvs: "video/vnd.dece.sd",
uvt: "application/vnd.dece.ttml+xml",
uvu: "video/vnd.uvvu.mp4",
uvv: "video/vnd.dece.video",
uvva: "audio/vnd.dece.audio",
uvvd: "application/vnd.dece.data",
uvvf: "application/vnd.dece.data",
uvvg: "image/vnd.dece.graphic",
uvvh: "video/vnd.dece.hd",
uvvi: "image/vnd.dece.graphic",
uvvm: "video/vnd.dece.mobile",
uvvp: "video/vnd.dece.pd",
uvvs: "video/vnd.dece.sd",
uvvt: "application/vnd.dece.ttml+xml",
uvvu: "video/vnd.uvvu.mp4",
uvvv: "video/vnd.dece.video",
uvvx: "application/vnd.dece.unspecified",
uvvz: "application/vnd.dece.zip",
uvx: "application/vnd.dece.unspecified",
uvz: "application/vnd.dece.zip",
vcard: "text/vcard",
vcd: "application/x-cdlink",
vcf: "text/x-vcard",
vcg: "application/vnd.groove-vcard",
vcs: "text/x-vcalendar",
vcx: "application/vnd.vcx",
vis: "application/vnd.visionary",
viv: "video/vnd.vivo",
vob: "video/x-ms-vob",
vor: "application/vnd.stardivision.writer",
vox: "application/x-authorware-bin",
vrml: "model/vrml",
vsd: "application/vnd.visio",
vsf: "application/vnd.vsf",
vss: "application/vnd.visio",
vst: "application/vnd.visio",
vsw: "application/vnd.visio",
vtu: "model/vnd.vtu",
vxml: "application/voicexml+xml",
w3d: "application/x-director",
wad: "application/x-doom",
wasm: "application/wasm",
wav: "audio/x-wav",
wax: "audio/x-ms-wax",
wbmp: "image/vnd.wap.wbmp",
wbs: "application/vnd.criticaltools.wbs+xml",
wbxml: "application/vnd.wap.wbxml",
wcm: "application/vnd.ms-works",
wdb: "application/vnd.ms-works",
wdp: "image/vnd.ms-photo",
weba: "audio/webm",
webm: "video/webm",
webp: "image/webp",
wg: "application/vnd.pmi.widget",
wgt: "application/widget",
wks: "application/vnd.ms-works",
wm: "video/x-ms-wm",
wma: "audio/x-ms-wma",
wmd: "application/x-ms-wmd",
wmf: "application/x-msmetafile",
wml: "text/vnd.wap.wml",
wmlc: "application/vnd.wap.wmlc",
wmls: "text/vnd.wap.wmlscript",
wmlsc: "application/vnd.wap.wmlscriptc",
wmv: "video/x-ms-wmv",
wmx: "video/x-ms-wmx",
wmz: "application/x-ms-wmz",
// wmz: 'application/x-msmetafile',
woff: "font/woff",
woff2: "font/woff2",
wpd: "application/vnd.wordperfect",
wpl: "application/vnd.ms-wpl",
wps: "application/vnd.ms-works",
wqd: "application/vnd.wqd",
wri: "application/x-mswrite",
wrl: "model/vrml",
wsdl: "application/wsdl+xml",
wspolicy: "application/wspolicy+xml",
wtb: "application/vnd.webturbo",
wvx: "video/x-ms-wvx",
x32: "application/x-authorware-bin",
x3d: "model/x3d+xml",
x3db: "model/x3d+binary",
x3dbz: "model/x3d+binary",
x3dv: "model/x3d+vrml",
x3dvz: "model/x3d+vrml",
x3dz: "model/x3d+xml",
xaml: "application/xaml+xml",
xap: "application/x-silverlight-app",
xar: "application/vnd.xara",
xbap: "application/x-ms-xbap",
xbd: "application/vnd.fujixerox.docuworks.binder",
xbm: "image/x-xbitmap",
xdf: "application/xcap-diff+xml",
xdm: "application/vnd.syncml.dm+xml",
xdp: "application/vnd.adobe.xdp+xml",
xdssc: "application/dssc+xml",
xdw: "application/vnd.fujixerox.docuworks",
xenc: "application/xenc+xml",
xer: "application/patch-ops-error+xml",
xfdf: "application/vnd.adobe.xfdf",
xfdl: "application/vnd.xfdl",
xht: "application/xhtml+xml",
xhtml: "application/xhtml+xml",
xhvml: "application/xv+xml",
xif: "image/vnd.xiff",
xla: "application/vnd.ms-excel",
xlam: "application/vnd.ms-excel.addin.macroenabled.12",
xlc: "application/vnd.ms-excel",
xlf: "application/x-xliff+xml",
xlm: "application/vnd.ms-excel",
xls: "application/vnd.ms-excel",
xlsb: "application/vnd.ms-excel.sheet.binary.macroenabled.12",
xlsm: "application/vnd.ms-excel.sheet.macroenabled.12",
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
xlt: "application/vnd.ms-excel",
xltm: "application/vnd.ms-excel.template.macroenabled.12",
xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
xlw: "application/vnd.ms-excel",
xm: "audio/xm",
xml: "application/xml",
xo: "application/vnd.olpc-sugar",
xop: "application/xop+xml",
xpi: "application/x-xpinstall",
xpl: "application/xproc+xml",
xpm: "image/x-xpixmap",
xpr: "application/vnd.is-xpr",
xps: "application/vnd.ms-xpsdocument",
xpw: "application/vnd.intercon.formnet",
xpx: "application/vnd.intercon.formnet",
xsl: "application/xml",
xslt: "application/xslt+xml",
xsm: "application/vnd.syncml+xml",
xspf: "application/xspf+xml",
xul: "application/vnd.mozilla.xul+xml",
xvm: "application/xv+xml",
xvml: "application/xv+xml",
xwd: "image/x-xwindowdump",
xyz: "chemical/x-xyz",
xz: "application/x-xz",
yang: "application/yang",
yin: "application/yin+xml",
z1: "application/x-zmachine",
z2: "application/x-zmachine",
z3: "application/x-zmachine",
z4: "application/x-zmachine",
z5: "application/x-zmachine",
z6: "application/x-zmachine",
z7: "application/x-zmachine",
z8: "application/x-zmachine",
zaz: "application/vnd.zzazz.deck+xml",
zip: "application/zip",
zir: "application/vnd.zul",
zirz: "application/vnd.zul",
zmm: "application/vnd.handheld-entertainment+xml"
};
function logLevelToTerminalColor$h(level) {
switch (level) {
case LogLevel$h.Error:
return TerminalColor.FG_RED;
case LogLevel$h.Warn:
return TerminalColor.FG_YELLOW;
case LogLevel$h.Info:
return TerminalColor.FG_BLUE;
case LogLevel$h.Verbose:
return TerminalColor.FG_GRAY;
case LogLevel$h.Debug:
return TerminalColor.FG_WHITE;
case LogLevel$h.Silly:
return TerminalColor.FG_MAGENTA;
default:
return TerminalColor.FG_WHITE;
}
}
var LogLevel$h = /* @__PURE__ */ ((LogLevel2) => {
LogLevel2["Error"] = "error";
LogLevel2["Warn"] = "warn";
LogLevel2["Info"] = "info";
LogLevel2["Verbose"] = "verbose";
LogLevel2["Debug"] = "debug";
LogLevel2["Silly"] = "silly";
return LogLevel2;
})(LogLevel$h || {});
function logRequest(request, response, performanceTime, message, color) {
const statusCode = response.headers[":status"];
const statusCodeText = String(statusCode).padStart(3, "0");
const methodText = (request.method ?? "<none>").padEnd(6, " ");
const url = request.url ?? "<none>";
const humanizedTime = humanizeTime(process.hrtime.bigint() - performanceTime);
const messageText = message ? " " + message : "";
const remoteAddress = request.session?.socket.remoteAddress ?? "<none>";
const ip = remoteAddress.replace("::ffff:", "").padEnd(16, " ");
const level = isSuccessfulStatusCode(statusCode) ? LogLevel$h.Info : LogLevel$h.Error;
logger$h[level](`${ip} ${statusCodeText} ${methodText} ${url} ${humanizedTime}${messageText}`, color);
}
function isSuccessfulStatusCode(statusCode) {
return statusCode >= 200 && statusCode < 300;
}
const logger$h = {
error: (message, color) => {
console.log(logFormat$h(LogLevel$h.Error, message, color).join(" "));
},
warn: (message, color) => {
console.log(logFormat$h(LogLevel$h.Warn, message, color).join(" "));
},
info: (message, color) => {
console.log(logFormat$h(LogLevel$h.Info, message, color).join(" "));
},
verbose: (message, color) => {
console.log(logFormat$h(LogLevel$h.Verbose, message, color).join(" "));