elegance-js 1.15.1 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build.mjs +55 -25
- package/dist/compile_docs.mjs +55 -25
- package/dist/server/server.mjs +55 -25
- package/package.json +1 -1
package/dist/build.mjs
CHANGED
|
@@ -627,6 +627,10 @@ import { createServer as createHttpServer } from "http";
|
|
|
627
627
|
import { promises as fs2 } from "fs";
|
|
628
628
|
import { join, normalize, extname, dirname, resolve } from "path";
|
|
629
629
|
import { pathToFileURL } from "url";
|
|
630
|
+
import { gzip, deflate } from "zlib";
|
|
631
|
+
import { promisify } from "util";
|
|
632
|
+
var gzipAsync = promisify(gzip);
|
|
633
|
+
var deflateAsync = promisify(deflate);
|
|
630
634
|
var MIME_TYPES = {
|
|
631
635
|
".html": "text/html; charset=utf-8",
|
|
632
636
|
".css": "text/css; charset=utf-8",
|
|
@@ -652,8 +656,7 @@ function startServer({
|
|
|
652
656
|
const requestHandler = async (req, res) => {
|
|
653
657
|
try {
|
|
654
658
|
if (!req.url) {
|
|
655
|
-
res
|
|
656
|
-
res.end("Bad Request");
|
|
659
|
+
await sendResponse(req, res, 400, { "Content-Type": "text/plain; charset=utf-8" }, "Bad Request");
|
|
657
660
|
return;
|
|
658
661
|
}
|
|
659
662
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -678,8 +681,7 @@ function startServer({
|
|
|
678
681
|
}
|
|
679
682
|
} catch (err) {
|
|
680
683
|
log.error(err);
|
|
681
|
-
res
|
|
682
|
-
res.end("Internal Server Error");
|
|
684
|
+
await sendResponse(req, res, 500, { "Content-Type": "text/plain; charset=utf-8" }, "Internal Server Error");
|
|
683
685
|
}
|
|
684
686
|
};
|
|
685
687
|
function attemptListen(p) {
|
|
@@ -702,8 +704,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
702
704
|
const originalPathname = pathname;
|
|
703
705
|
let filePath = normalize(join(root, decodeURIComponent(pathname))).replace(/[\\/]+$/, "");
|
|
704
706
|
if (!filePath.startsWith(root)) {
|
|
705
|
-
res
|
|
706
|
-
res.end("Forbidden");
|
|
707
|
+
await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
|
|
707
708
|
return;
|
|
708
709
|
}
|
|
709
710
|
let stats;
|
|
@@ -777,7 +778,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
777
778
|
}
|
|
778
779
|
const finalHandler = async (req2, res2) => {
|
|
779
780
|
if (!hasHandler) {
|
|
780
|
-
await respondWithErrorPage(root, pathname, 404, res2);
|
|
781
|
+
await respondWithErrorPage(root, pathname, 404, req2, res2);
|
|
781
782
|
return;
|
|
782
783
|
}
|
|
783
784
|
if (isDynamic) {
|
|
@@ -786,8 +787,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
786
787
|
if (resultHTML === false) {
|
|
787
788
|
return;
|
|
788
789
|
}
|
|
789
|
-
res2
|
|
790
|
-
res2.end(resultHTML);
|
|
790
|
+
await sendResponse(req2, res2, 200, { "Content-Type": MIME_TYPES[".html"] }, resultHTML);
|
|
791
791
|
} catch (err) {
|
|
792
792
|
log.error("Error building dynamic page -", err);
|
|
793
793
|
}
|
|
@@ -795,8 +795,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
795
795
|
const ext = extname(handlerPath).toLowerCase();
|
|
796
796
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
797
797
|
const data = await fs2.readFile(handlerPath);
|
|
798
|
-
res2
|
|
799
|
-
res2.end(data);
|
|
798
|
+
await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
|
|
800
799
|
}
|
|
801
800
|
};
|
|
802
801
|
const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
|
|
@@ -822,7 +821,7 @@ async function handleApiRequest(root, pathname, req, res) {
|
|
|
822
821
|
fn = module[req.method];
|
|
823
822
|
} catch (err) {
|
|
824
823
|
console.error(err);
|
|
825
|
-
return respondWithJsonError(res, 500, "Internal Server Error");
|
|
824
|
+
return respondWithJsonError(req, res, 500, "Internal Server Error");
|
|
826
825
|
}
|
|
827
826
|
}
|
|
828
827
|
const middlewareDirs = [];
|
|
@@ -853,10 +852,10 @@ async function handleApiRequest(root, pathname, req, res) {
|
|
|
853
852
|
}
|
|
854
853
|
const finalHandler = async (req2, res2) => {
|
|
855
854
|
if (!hasRoute) {
|
|
856
|
-
return respondWithJsonError(res2, 404, "Not Found");
|
|
855
|
+
return respondWithJsonError(req2, res2, 404, "Not Found");
|
|
857
856
|
}
|
|
858
857
|
if (typeof fn !== "function") {
|
|
859
|
-
return respondWithJsonError(res2, 405, "Method Not Allowed");
|
|
858
|
+
return respondWithJsonError(req2, res2, 405, "Method Not Allowed");
|
|
860
859
|
}
|
|
861
860
|
await fn(req2, res2);
|
|
862
861
|
};
|
|
@@ -869,9 +868,9 @@ function composeMiddlewares(mws, final, options2) {
|
|
|
869
868
|
async function dispatch(err) {
|
|
870
869
|
if (err) {
|
|
871
870
|
if (options2.isApi) {
|
|
872
|
-
return respondWithJsonError(res, 500, err.message || "Internal Server Error");
|
|
871
|
+
return respondWithJsonError(req, res, 500, err.message || "Internal Server Error");
|
|
873
872
|
} else {
|
|
874
|
-
return await respondWithErrorPage(options2.root, options2.pathname, 500, res);
|
|
873
|
+
return await respondWithErrorPage(options2.root, options2.pathname, 500, req, res);
|
|
875
874
|
}
|
|
876
875
|
}
|
|
877
876
|
if (index >= mws.length) {
|
|
@@ -899,11 +898,11 @@ function composeMiddlewares(mws, final, options2) {
|
|
|
899
898
|
await dispatch();
|
|
900
899
|
};
|
|
901
900
|
}
|
|
902
|
-
function respondWithJsonError(res, code, message) {
|
|
903
|
-
|
|
904
|
-
res
|
|
901
|
+
async function respondWithJsonError(req, res, code, message) {
|
|
902
|
+
const body2 = JSON.stringify({ error: message });
|
|
903
|
+
await sendResponse(req, res, code, { "Content-Type": "application/json; charset=utf-8" }, body2);
|
|
905
904
|
}
|
|
906
|
-
async function respondWithErrorPage(root, pathname, code, res) {
|
|
905
|
+
async function respondWithErrorPage(root, pathname, code, req, res) {
|
|
907
906
|
let currentPath = normalize(join(root, decodeURIComponent(pathname)));
|
|
908
907
|
let tried = /* @__PURE__ */ new Set();
|
|
909
908
|
let errorFilePath = null;
|
|
@@ -932,15 +931,46 @@ async function respondWithErrorPage(root, pathname, code, res) {
|
|
|
932
931
|
}
|
|
933
932
|
if (errorFilePath) {
|
|
934
933
|
try {
|
|
935
|
-
const html = await fs2.readFile(errorFilePath);
|
|
936
|
-
res
|
|
937
|
-
res.end(html);
|
|
934
|
+
const html = await fs2.readFile(errorFilePath, "utf8");
|
|
935
|
+
await sendResponse(req, res, code, { "Content-Type": "text/html; charset=utf-8" }, html);
|
|
938
936
|
return;
|
|
939
937
|
} catch {
|
|
940
938
|
}
|
|
941
939
|
}
|
|
942
|
-
res
|
|
943
|
-
|
|
940
|
+
await sendResponse(req, res, code, { "Content-Type": "text/plain; charset=utf-8" }, `${code} Error`);
|
|
941
|
+
}
|
|
942
|
+
function isCompressible(contentType) {
|
|
943
|
+
if (!contentType) return false;
|
|
944
|
+
return /text\/|javascript|json|xml|svg/.test(contentType);
|
|
945
|
+
}
|
|
946
|
+
async function sendResponse(req, res, status, headers, body2) {
|
|
947
|
+
if (typeof body2 === "string") {
|
|
948
|
+
body2 = Buffer.from(body2);
|
|
949
|
+
}
|
|
950
|
+
const accept = req.headers["accept-encoding"] || "";
|
|
951
|
+
let encoding = null;
|
|
952
|
+
if (accept.match(/\bgzip\b/)) {
|
|
953
|
+
encoding = "gzip";
|
|
954
|
+
} else if (accept.match(/\bdeflate\b/)) {
|
|
955
|
+
encoding = "deflate";
|
|
956
|
+
}
|
|
957
|
+
if (!encoding || !isCompressible(headers["Content-Type"] || "")) {
|
|
958
|
+
res.writeHead(status, headers);
|
|
959
|
+
res.end(body2);
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
const compressor = encoding === "gzip" ? gzipAsync : deflateAsync;
|
|
963
|
+
try {
|
|
964
|
+
const compressed = await compressor(body2);
|
|
965
|
+
headers["Content-Encoding"] = encoding;
|
|
966
|
+
headers["Vary"] = "Accept-Encoding";
|
|
967
|
+
res.writeHead(status, headers);
|
|
968
|
+
res.end(compressed);
|
|
969
|
+
} catch (err) {
|
|
970
|
+
log.error("Compression error:", err);
|
|
971
|
+
res.writeHead(status, headers);
|
|
972
|
+
res.end(body2);
|
|
973
|
+
}
|
|
944
974
|
}
|
|
945
975
|
|
|
946
976
|
// src/build.ts
|
package/dist/compile_docs.mjs
CHANGED
|
@@ -630,6 +630,10 @@ import { createServer as createHttpServer } from "http";
|
|
|
630
630
|
import { promises as fs2 } from "fs";
|
|
631
631
|
import { join, normalize, extname, dirname, resolve } from "path";
|
|
632
632
|
import { pathToFileURL } from "url";
|
|
633
|
+
import { gzip, deflate } from "zlib";
|
|
634
|
+
import { promisify } from "util";
|
|
635
|
+
var gzipAsync = promisify(gzip);
|
|
636
|
+
var deflateAsync = promisify(deflate);
|
|
633
637
|
var MIME_TYPES = {
|
|
634
638
|
".html": "text/html; charset=utf-8",
|
|
635
639
|
".css": "text/css; charset=utf-8",
|
|
@@ -655,8 +659,7 @@ function startServer({
|
|
|
655
659
|
const requestHandler = async (req, res) => {
|
|
656
660
|
try {
|
|
657
661
|
if (!req.url) {
|
|
658
|
-
res
|
|
659
|
-
res.end("Bad Request");
|
|
662
|
+
await sendResponse(req, res, 400, { "Content-Type": "text/plain; charset=utf-8" }, "Bad Request");
|
|
660
663
|
return;
|
|
661
664
|
}
|
|
662
665
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -681,8 +684,7 @@ function startServer({
|
|
|
681
684
|
}
|
|
682
685
|
} catch (err) {
|
|
683
686
|
log.error(err);
|
|
684
|
-
res
|
|
685
|
-
res.end("Internal Server Error");
|
|
687
|
+
await sendResponse(req, res, 500, { "Content-Type": "text/plain; charset=utf-8" }, "Internal Server Error");
|
|
686
688
|
}
|
|
687
689
|
};
|
|
688
690
|
function attemptListen(p) {
|
|
@@ -705,8 +707,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
705
707
|
const originalPathname = pathname;
|
|
706
708
|
let filePath = normalize(join(root, decodeURIComponent(pathname))).replace(/[\\/]+$/, "");
|
|
707
709
|
if (!filePath.startsWith(root)) {
|
|
708
|
-
res
|
|
709
|
-
res.end("Forbidden");
|
|
710
|
+
await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
|
|
710
711
|
return;
|
|
711
712
|
}
|
|
712
713
|
let stats;
|
|
@@ -780,7 +781,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
780
781
|
}
|
|
781
782
|
const finalHandler = async (req2, res2) => {
|
|
782
783
|
if (!hasHandler) {
|
|
783
|
-
await respondWithErrorPage(root, pathname, 404, res2);
|
|
784
|
+
await respondWithErrorPage(root, pathname, 404, req2, res2);
|
|
784
785
|
return;
|
|
785
786
|
}
|
|
786
787
|
if (isDynamic) {
|
|
@@ -789,8 +790,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
789
790
|
if (resultHTML === false) {
|
|
790
791
|
return;
|
|
791
792
|
}
|
|
792
|
-
res2
|
|
793
|
-
res2.end(resultHTML);
|
|
793
|
+
await sendResponse(req2, res2, 200, { "Content-Type": MIME_TYPES[".html"] }, resultHTML);
|
|
794
794
|
} catch (err) {
|
|
795
795
|
log.error("Error building dynamic page -", err);
|
|
796
796
|
}
|
|
@@ -798,8 +798,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
798
798
|
const ext = extname(handlerPath).toLowerCase();
|
|
799
799
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
800
800
|
const data = await fs2.readFile(handlerPath);
|
|
801
|
-
res2
|
|
802
|
-
res2.end(data);
|
|
801
|
+
await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
|
|
803
802
|
}
|
|
804
803
|
};
|
|
805
804
|
const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
|
|
@@ -825,7 +824,7 @@ async function handleApiRequest(root, pathname, req, res) {
|
|
|
825
824
|
fn = module[req.method];
|
|
826
825
|
} catch (err) {
|
|
827
826
|
console.error(err);
|
|
828
|
-
return respondWithJsonError(res, 500, "Internal Server Error");
|
|
827
|
+
return respondWithJsonError(req, res, 500, "Internal Server Error");
|
|
829
828
|
}
|
|
830
829
|
}
|
|
831
830
|
const middlewareDirs = [];
|
|
@@ -856,10 +855,10 @@ async function handleApiRequest(root, pathname, req, res) {
|
|
|
856
855
|
}
|
|
857
856
|
const finalHandler = async (req2, res2) => {
|
|
858
857
|
if (!hasRoute) {
|
|
859
|
-
return respondWithJsonError(res2, 404, "Not Found");
|
|
858
|
+
return respondWithJsonError(req2, res2, 404, "Not Found");
|
|
860
859
|
}
|
|
861
860
|
if (typeof fn !== "function") {
|
|
862
|
-
return respondWithJsonError(res2, 405, "Method Not Allowed");
|
|
861
|
+
return respondWithJsonError(req2, res2, 405, "Method Not Allowed");
|
|
863
862
|
}
|
|
864
863
|
await fn(req2, res2);
|
|
865
864
|
};
|
|
@@ -872,9 +871,9 @@ function composeMiddlewares(mws, final, options2) {
|
|
|
872
871
|
async function dispatch(err) {
|
|
873
872
|
if (err) {
|
|
874
873
|
if (options2.isApi) {
|
|
875
|
-
return respondWithJsonError(res, 500, err.message || "Internal Server Error");
|
|
874
|
+
return respondWithJsonError(req, res, 500, err.message || "Internal Server Error");
|
|
876
875
|
} else {
|
|
877
|
-
return await respondWithErrorPage(options2.root, options2.pathname, 500, res);
|
|
876
|
+
return await respondWithErrorPage(options2.root, options2.pathname, 500, req, res);
|
|
878
877
|
}
|
|
879
878
|
}
|
|
880
879
|
if (index >= mws.length) {
|
|
@@ -902,11 +901,11 @@ function composeMiddlewares(mws, final, options2) {
|
|
|
902
901
|
await dispatch();
|
|
903
902
|
};
|
|
904
903
|
}
|
|
905
|
-
function respondWithJsonError(res, code, message) {
|
|
906
|
-
|
|
907
|
-
res
|
|
904
|
+
async function respondWithJsonError(req, res, code, message) {
|
|
905
|
+
const body2 = JSON.stringify({ error: message });
|
|
906
|
+
await sendResponse(req, res, code, { "Content-Type": "application/json; charset=utf-8" }, body2);
|
|
908
907
|
}
|
|
909
|
-
async function respondWithErrorPage(root, pathname, code, res) {
|
|
908
|
+
async function respondWithErrorPage(root, pathname, code, req, res) {
|
|
910
909
|
let currentPath = normalize(join(root, decodeURIComponent(pathname)));
|
|
911
910
|
let tried = /* @__PURE__ */ new Set();
|
|
912
911
|
let errorFilePath = null;
|
|
@@ -935,15 +934,46 @@ async function respondWithErrorPage(root, pathname, code, res) {
|
|
|
935
934
|
}
|
|
936
935
|
if (errorFilePath) {
|
|
937
936
|
try {
|
|
938
|
-
const html = await fs2.readFile(errorFilePath);
|
|
939
|
-
res
|
|
940
|
-
res.end(html);
|
|
937
|
+
const html = await fs2.readFile(errorFilePath, "utf8");
|
|
938
|
+
await sendResponse(req, res, code, { "Content-Type": "text/html; charset=utf-8" }, html);
|
|
941
939
|
return;
|
|
942
940
|
} catch {
|
|
943
941
|
}
|
|
944
942
|
}
|
|
945
|
-
res
|
|
946
|
-
|
|
943
|
+
await sendResponse(req, res, code, { "Content-Type": "text/plain; charset=utf-8" }, `${code} Error`);
|
|
944
|
+
}
|
|
945
|
+
function isCompressible(contentType) {
|
|
946
|
+
if (!contentType) return false;
|
|
947
|
+
return /text\/|javascript|json|xml|svg/.test(contentType);
|
|
948
|
+
}
|
|
949
|
+
async function sendResponse(req, res, status, headers, body2) {
|
|
950
|
+
if (typeof body2 === "string") {
|
|
951
|
+
body2 = Buffer.from(body2);
|
|
952
|
+
}
|
|
953
|
+
const accept = req.headers["accept-encoding"] || "";
|
|
954
|
+
let encoding = null;
|
|
955
|
+
if (accept.match(/\bgzip\b/)) {
|
|
956
|
+
encoding = "gzip";
|
|
957
|
+
} else if (accept.match(/\bdeflate\b/)) {
|
|
958
|
+
encoding = "deflate";
|
|
959
|
+
}
|
|
960
|
+
if (!encoding || !isCompressible(headers["Content-Type"] || "")) {
|
|
961
|
+
res.writeHead(status, headers);
|
|
962
|
+
res.end(body2);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const compressor = encoding === "gzip" ? gzipAsync : deflateAsync;
|
|
966
|
+
try {
|
|
967
|
+
const compressed = await compressor(body2);
|
|
968
|
+
headers["Content-Encoding"] = encoding;
|
|
969
|
+
headers["Vary"] = "Accept-Encoding";
|
|
970
|
+
res.writeHead(status, headers);
|
|
971
|
+
res.end(compressed);
|
|
972
|
+
} catch (err) {
|
|
973
|
+
log.error("Compression error:", err);
|
|
974
|
+
res.writeHead(status, headers);
|
|
975
|
+
res.end(body2);
|
|
976
|
+
}
|
|
947
977
|
}
|
|
948
978
|
|
|
949
979
|
// src/build.ts
|
package/dist/server/server.mjs
CHANGED
|
@@ -619,6 +619,10 @@ var log = {
|
|
|
619
619
|
};
|
|
620
620
|
|
|
621
621
|
// src/server/server.ts
|
|
622
|
+
import { gzip, deflate } from "zlib";
|
|
623
|
+
import { promisify } from "util";
|
|
624
|
+
var gzipAsync = promisify(gzip);
|
|
625
|
+
var deflateAsync = promisify(deflate);
|
|
622
626
|
var MIME_TYPES = {
|
|
623
627
|
".html": "text/html; charset=utf-8",
|
|
624
628
|
".css": "text/css; charset=utf-8",
|
|
@@ -644,8 +648,7 @@ function startServer({
|
|
|
644
648
|
const requestHandler = async (req, res) => {
|
|
645
649
|
try {
|
|
646
650
|
if (!req.url) {
|
|
647
|
-
res
|
|
648
|
-
res.end("Bad Request");
|
|
651
|
+
await sendResponse(req, res, 400, { "Content-Type": "text/plain; charset=utf-8" }, "Bad Request");
|
|
649
652
|
return;
|
|
650
653
|
}
|
|
651
654
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -670,8 +673,7 @@ function startServer({
|
|
|
670
673
|
}
|
|
671
674
|
} catch (err) {
|
|
672
675
|
log.error(err);
|
|
673
|
-
res
|
|
674
|
-
res.end("Internal Server Error");
|
|
676
|
+
await sendResponse(req, res, 500, { "Content-Type": "text/plain; charset=utf-8" }, "Internal Server Error");
|
|
675
677
|
}
|
|
676
678
|
};
|
|
677
679
|
function attemptListen(p) {
|
|
@@ -694,8 +696,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
694
696
|
const originalPathname = pathname;
|
|
695
697
|
let filePath = normalize(join(root, decodeURIComponent(pathname))).replace(/[\\/]+$/, "");
|
|
696
698
|
if (!filePath.startsWith(root)) {
|
|
697
|
-
res
|
|
698
|
-
res.end("Forbidden");
|
|
699
|
+
await sendResponse(req, res, 403, { "Content-Type": "text/plain; charset=utf-8" }, "Forbidden");
|
|
699
700
|
return;
|
|
700
701
|
}
|
|
701
702
|
let stats;
|
|
@@ -769,7 +770,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
769
770
|
}
|
|
770
771
|
const finalHandler = async (req2, res2) => {
|
|
771
772
|
if (!hasHandler) {
|
|
772
|
-
await respondWithErrorPage(root, pathname, 404, res2);
|
|
773
|
+
await respondWithErrorPage(root, pathname, 404, req2, res2);
|
|
773
774
|
return;
|
|
774
775
|
}
|
|
775
776
|
if (isDynamic) {
|
|
@@ -778,8 +779,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
778
779
|
if (resultHTML === false) {
|
|
779
780
|
return;
|
|
780
781
|
}
|
|
781
|
-
res2
|
|
782
|
-
res2.end(resultHTML);
|
|
782
|
+
await sendResponse(req2, res2, 200, { "Content-Type": MIME_TYPES[".html"] }, resultHTML);
|
|
783
783
|
} catch (err) {
|
|
784
784
|
log.error("Error building dynamic page -", err);
|
|
785
785
|
}
|
|
@@ -787,8 +787,7 @@ async function handleStaticRequest(root, pathname, req, res, DIST_DIR) {
|
|
|
787
787
|
const ext = extname(handlerPath).toLowerCase();
|
|
788
788
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
789
789
|
const data = await fs2.readFile(handlerPath);
|
|
790
|
-
res2
|
|
791
|
-
res2.end(data);
|
|
790
|
+
await sendResponse(req2, res2, 200, { "Content-Type": contentType }, data);
|
|
792
791
|
}
|
|
793
792
|
};
|
|
794
793
|
const composed = composeMiddlewares(middlewares, finalHandler, { isApi: false, root, pathname });
|
|
@@ -814,7 +813,7 @@ async function handleApiRequest(root, pathname, req, res) {
|
|
|
814
813
|
fn = module[req.method];
|
|
815
814
|
} catch (err) {
|
|
816
815
|
console.error(err);
|
|
817
|
-
return respondWithJsonError(res, 500, "Internal Server Error");
|
|
816
|
+
return respondWithJsonError(req, res, 500, "Internal Server Error");
|
|
818
817
|
}
|
|
819
818
|
}
|
|
820
819
|
const middlewareDirs = [];
|
|
@@ -845,10 +844,10 @@ async function handleApiRequest(root, pathname, req, res) {
|
|
|
845
844
|
}
|
|
846
845
|
const finalHandler = async (req2, res2) => {
|
|
847
846
|
if (!hasRoute) {
|
|
848
|
-
return respondWithJsonError(res2, 404, "Not Found");
|
|
847
|
+
return respondWithJsonError(req2, res2, 404, "Not Found");
|
|
849
848
|
}
|
|
850
849
|
if (typeof fn !== "function") {
|
|
851
|
-
return respondWithJsonError(res2, 405, "Method Not Allowed");
|
|
850
|
+
return respondWithJsonError(req2, res2, 405, "Method Not Allowed");
|
|
852
851
|
}
|
|
853
852
|
await fn(req2, res2);
|
|
854
853
|
};
|
|
@@ -861,9 +860,9 @@ function composeMiddlewares(mws, final, options) {
|
|
|
861
860
|
async function dispatch(err) {
|
|
862
861
|
if (err) {
|
|
863
862
|
if (options.isApi) {
|
|
864
|
-
return respondWithJsonError(res, 500, err.message || "Internal Server Error");
|
|
863
|
+
return respondWithJsonError(req, res, 500, err.message || "Internal Server Error");
|
|
865
864
|
} else {
|
|
866
|
-
return await respondWithErrorPage(options.root, options.pathname, 500, res);
|
|
865
|
+
return await respondWithErrorPage(options.root, options.pathname, 500, req, res);
|
|
867
866
|
}
|
|
868
867
|
}
|
|
869
868
|
if (index >= mws.length) {
|
|
@@ -891,11 +890,11 @@ function composeMiddlewares(mws, final, options) {
|
|
|
891
890
|
await dispatch();
|
|
892
891
|
};
|
|
893
892
|
}
|
|
894
|
-
function respondWithJsonError(res, code, message) {
|
|
895
|
-
|
|
896
|
-
res
|
|
893
|
+
async function respondWithJsonError(req, res, code, message) {
|
|
894
|
+
const body2 = JSON.stringify({ error: message });
|
|
895
|
+
await sendResponse(req, res, code, { "Content-Type": "application/json; charset=utf-8" }, body2);
|
|
897
896
|
}
|
|
898
|
-
async function respondWithErrorPage(root, pathname, code, res) {
|
|
897
|
+
async function respondWithErrorPage(root, pathname, code, req, res) {
|
|
899
898
|
let currentPath = normalize(join(root, decodeURIComponent(pathname)));
|
|
900
899
|
let tried = /* @__PURE__ */ new Set();
|
|
901
900
|
let errorFilePath = null;
|
|
@@ -924,15 +923,46 @@ async function respondWithErrorPage(root, pathname, code, res) {
|
|
|
924
923
|
}
|
|
925
924
|
if (errorFilePath) {
|
|
926
925
|
try {
|
|
927
|
-
const html = await fs2.readFile(errorFilePath);
|
|
928
|
-
res
|
|
929
|
-
res.end(html);
|
|
926
|
+
const html = await fs2.readFile(errorFilePath, "utf8");
|
|
927
|
+
await sendResponse(req, res, code, { "Content-Type": "text/html; charset=utf-8" }, html);
|
|
930
928
|
return;
|
|
931
929
|
} catch {
|
|
932
930
|
}
|
|
933
931
|
}
|
|
934
|
-
res
|
|
935
|
-
|
|
932
|
+
await sendResponse(req, res, code, { "Content-Type": "text/plain; charset=utf-8" }, `${code} Error`);
|
|
933
|
+
}
|
|
934
|
+
function isCompressible(contentType) {
|
|
935
|
+
if (!contentType) return false;
|
|
936
|
+
return /text\/|javascript|json|xml|svg/.test(contentType);
|
|
937
|
+
}
|
|
938
|
+
async function sendResponse(req, res, status, headers, body2) {
|
|
939
|
+
if (typeof body2 === "string") {
|
|
940
|
+
body2 = Buffer.from(body2);
|
|
941
|
+
}
|
|
942
|
+
const accept = req.headers["accept-encoding"] || "";
|
|
943
|
+
let encoding = null;
|
|
944
|
+
if (accept.match(/\bgzip\b/)) {
|
|
945
|
+
encoding = "gzip";
|
|
946
|
+
} else if (accept.match(/\bdeflate\b/)) {
|
|
947
|
+
encoding = "deflate";
|
|
948
|
+
}
|
|
949
|
+
if (!encoding || !isCompressible(headers["Content-Type"] || "")) {
|
|
950
|
+
res.writeHead(status, headers);
|
|
951
|
+
res.end(body2);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
const compressor = encoding === "gzip" ? gzipAsync : deflateAsync;
|
|
955
|
+
try {
|
|
956
|
+
const compressed = await compressor(body2);
|
|
957
|
+
headers["Content-Encoding"] = encoding;
|
|
958
|
+
headers["Vary"] = "Accept-Encoding";
|
|
959
|
+
res.writeHead(status, headers);
|
|
960
|
+
res.end(compressed);
|
|
961
|
+
} catch (err) {
|
|
962
|
+
log.error("Compression error:", err);
|
|
963
|
+
res.writeHead(status, headers);
|
|
964
|
+
res.end(body2);
|
|
965
|
+
}
|
|
936
966
|
}
|
|
937
967
|
export {
|
|
938
968
|
startServer
|