This commit is contained in:
Rizky
2024-02-10 15:58:04 +07:00
parent 18d389b73e
commit aa6cdbf539
9 changed files with 127 additions and 251 deletions
+38 -8
View File
@@ -1,4 +1,4 @@
import { g } from "../utils/global";
import { gzipSync } from "bun";
const parseQueryParams = (ctx: any) => {
const pageHref = ctx.req.url;
@@ -19,8 +19,8 @@ export const apiContext = (ctx: any) => {
req: ctx.req as Request & { params: any; query_parameters: any },
res: {
...ctx.res,
send: (body) => {
ctx.res = createResponse(ctx.res, body);
send: (body, cache_accept?: string) => {
ctx.res = createResponse(ctx.res, body, cache_accept);
},
sendStatus: (code: number) => {
ctx.res._status = code;
@@ -29,19 +29,38 @@ export const apiContext = (ctx: any) => {
ctx.res.headers.append(key, value);
},
} as Response & {
send: (body?: string | object) => void;
send: (body?: string | object, cache_accept?: string) => void;
setHeader: (key: string, value: string) => void;
sendStatus: (code: number) => void;
},
};
};
export const createResponse = (existingRes: any, body: any) => {
const cache = { gz: {} as Record<string, Uint8Array> };
export const createResponse = (
existingRes: any,
body: any,
cache_accept?: string
) => {
const status =
typeof existingRes._status === "number" ? existingRes._status : undefined;
let content: any = typeof body === "string" ? body : JSON.stringify(body);
const headers = {} as Record<string, string>;
if (cache_accept && cache_accept.toLowerCase().includes("gz")) {
const content_hash = simpleHash(content);
if (content_hash) {
content = cache.gz[content_hash];
} else {
cache.gz[content_hash] = gzipSync(content);
content = cache.gz[content_hash];
}
headers["content-encoding"] = "gz";
}
let res = new Response(
typeof body === "string" ? body : JSON.stringify(body),
content,
status
? {
status,
@@ -52,11 +71,22 @@ export const createResponse = (existingRes: any, body: any) => {
if (typeof body === "object") {
res.headers.append("content-type", "application/json");
}
for (const [k, v] of Object.entries(headers)) {
res.headers.append(k, v);
}
const cur = existingRes as Response;
for (const [key, value] of cur.headers.entries()) {
cur.headers.forEach((value, key) => {
res.headers.append(key, value);
}
});
return res;
};
function simpleHash(str: string) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0;
}
return (hash >>> 0).toString(36);
}
+9 -46
View File
@@ -60,56 +60,19 @@ export const createServer = async () => {
async fetch(req) {
const url = new URL(req.url);
const web = await serveWeb(url, req);
let index = ["", ""];
if (web) {
if (Array.isArray(web)) index = web;
else {
return web;
}
}
const api = await serveAPI(url, req);
if (api) {
return api;
}
if (index) {
let status: any = {};
if (!["", "index.html"].includes(trim(url.pathname, " /"))) {
status = {
status: 404,
statusText: "Not Found",
};
const handle = async (req: Request) => {
const api = await serveAPI(url, req);
if (api) {
return api;
}
const [site_id, body] = index;
if (g.web[site_id]) {
const router = g.web[site_id].router;
if (router) {
let found = router.lookup(url.pathname);
if (!found) {
found = router.lookup(url.pathname + "/");
}
if (found) {
status = {};
}
}
}
return new Response(body, {
...status,
headers: {
"content-type": "text/html",
},
return new Response(`404 Not Found`, {
status: 404,
statusText: "Not Found",
});
}
};
return new Response(`404 Not Found`, {
status: 404,
statusText: "Not Found",
});
return handle(req);
},
});
+2 -35
View File
@@ -8,15 +8,12 @@ import {
removeAsync,
writeAsync,
} from "fs-jetpack";
import { createRouter } from "radix3";
import { gunzipSync } from "zlib";
import { downloadFile } from "../api/_deploy";
import { dir } from "../utils/dir";
import { g } from "../utils/global";
export const loadWeb = async () => {
g.web = {};
await dirAsync(dir(`app/static`));
const siteZip = `${
g.mode === "dev" ? "http://localhost:4550" : "https://prasi.app"
@@ -53,39 +50,14 @@ export const loadWeb = async () => {
if (!deploy) {
await dirAsync(dir(`app/web/${web.name}/deploys`));
}
g.web[web.name] = {
current: parseInt(
(await readAsync(dir(`app/web/${web.name}/current`))) || "0"
),
deploys: deploy ? deploy.children.map((e) => parseInt(e.name)) : [],
domains:
(await readAsync(dir(`app/web/${web.name}/domains.json`), "json")) ||
[],
site_id: web.name,
deploying: null,
cacheKey: 0,
router: null,
cache: null,
};
const cur = g.web[web.name];
if (!cur.deploys.includes(cur.current)) {
cur.current = 0;
}
if (cur.current) {
await loadWebCache(cur.site_id, cur.current);
}
}
};
const decoder = new TextDecoder();
export const loadWebCache = async (site_id: string, ts: number | string) => {
const web = g.web[site_id];
const web = g.web;
if (web) {
const path = dir(`app/web/${site_id}/deploys/${ts}`);
const path = dir(`app/web/deploys/${ts}`);
if (await existsAsync(path)) {
const fileContent = await readAsync(path, "buffer");
if (fileContent) {
@@ -94,11 +66,6 @@ export const loadWebCache = async (site_id: string, ts: number | string) => {
);
const res = gunzipSync(fileContent);
web.cache = JSON.parse(decoder.decode(res));
web.router = createRouter();
for (const p of web.cache?.pages || []) {
web.router.insert(p.url, p);
}
}
}
}
+1 -21
View File
@@ -1,6 +1,5 @@
import { statSync } from "fs";
import { join } from "path";
import { g } from "../utils/global";
import { dir } from "utils/dir";
const index = {
@@ -13,28 +12,13 @@ const index = {
};
export const serveWeb = async (url: URL, req: Request) => {
const domain = url.hostname;
let site_id = "";
if (!g.domains) {
g.domains = {};
for (const web of Object.values(g.web)) {
for (const d of web.domains) {
const durl = new URL(d);
g.domains[durl.hostname] = web.site_id;
}
}
}
if (typeof g.domains[domain] === "undefined") {
g.domains[domain] = "";
}
site_id = g.domains[domain];
if (!site_id) {
return false;
}
const base = dir(`app/static/site`);
// const base = `/Users/r/Developer/prasi/.output/app/srv/site`;
let path = join(base, url.pathname);
@@ -73,7 +57,7 @@ export const serveWeb = async (url: URL, req: Request) => {
index.html = generateIndexHtml("", site_id);
}
return [site_id, index.html];
return { site_id, index: index.html };
};
export const generateIndexHtml = (base_url: string, site_id: string) => {
@@ -95,10 +79,6 @@ export const generateIndexHtml = (base_url: string, site_id: string) => {
<div id="root"></div>
<script src="${base}/site.js" type="module"></script>
<script>window.id_site = "${site_id}";</script>
<script
src="https://js.sentry-cdn.com/a2dfb8b1128f4018b83bdc9c08d18da2.min.js"
crossorigin="anonymous"
></script>
</body>
</html>`;
};