Page MenuHomeSealhub

No OneTemporary

diff --git a/src/back/proxy.ts b/src/back/proxy.ts
index 61e5cbe..1256978 100644
--- a/src/back/proxy.ts
+++ b/src/back/proxy.ts
@@ -1,102 +1,104 @@
import express from "express";
import type { Server } from "node:http";
import type { Request, Response, Express } from "express";
import { createProxyMiddleware, responseInterceptor } from "http-proxy-middleware";
import { HTMLRewriter } from "html-rewriter-wasm";
import type TheApp from "./app.js";
import { htmlUnescape } from "escape-goat";
import { promisify } from "util";
import { PROXY_TARGET } from "src/back/config.js";
const encoder = new TextEncoder();
const decoder = new TextDecoder();
export default class Proxy {
express_app: Express;
server: Server;
constructor(public app: TheApp) {}
async start() {
this.express_app = express();
console.log("Starting proxy...");
const { items: rules } = await this.app.collections.rules
.suList()
.format({ code: "original" })
.filter({ active: true })
.fetch();
const code = rules
.map((rule) => `{${htmlUnescape(rule.get("code") || "")}}`)
.join("\n");
console.log("The code to run is");
console.log(code);
const proxyMiddleware = createProxyMiddleware<Request, Response>({
target: PROXY_TARGET,
changeOrigin: true,
selfHandleResponse: true,
on: {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
- proxyRes: responseInterceptor(async (responseBuffer, proxyRes) => {
+ proxyRes: responseInterceptor(async (responseBuffer, proxyRes, req) => {
if (!proxyRes.headers["content-type"]?.includes("html")) {
// only rewrite html
return responseBuffer;
}
const response = responseBuffer.toString("utf8"); // convert buffer to string
let output = "";
const rewriter = new HTMLRewriter((outputChunk) => {
output += decoder.decode(outputChunk);
});
try {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const url = req.url; // to make it available in eval
eval(code);
} catch (e) {
console.error(e);
rewriter.free();
return responseBuffer;
}
try {
await rewriter.write(encoder.encode(response));
await rewriter.end();
} catch (e) {
console.error(e);
return responseBuffer;
} finally {
rewriter.free(); // Remember to free memory
}
return output;
}),
},
});
this.express_app.use("/", proxyMiddleware);
const port = 3000;
this.server = this.express_app.listen(port);
console.log(
`Proxy started. Target URL is ${PROXY_TARGET}. Listening on :${port}`
);
}
stop() {
console.log("Stopping proxy...");
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-argument, @typescript-eslint/consistent-type-assertions
return promisify(this.server.close.bind(this.server)).bind(
this.server
)() as Promise<void>;
}
}
let instance: Proxy;
export function getProxy(app: TheApp): Proxy {
if (!instance) {
instance = new Proxy(app);
}
return instance;
}
diff --git a/src/back/routes/admin/rules/index.page.ts b/src/back/routes/admin/rules/index.page.ts
index a500375..8c7bdeb 100644
--- a/src/back/routes/admin/rules/index.page.ts
+++ b/src/back/routes/admin/rules/index.page.ts
@@ -1,107 +1,107 @@
import { CRUD } from "@sealcode/crud-ui";
import type { Context } from "koa";
import type { CollectionItem } from "sealious";
import type { ListFilterRender } from "@sealcode/sealgen";
import { Controls, DefaultListFilters, Fields } from "@sealcode/sealgen";
import { Rules } from "src/back/collections/collections.js";
import html from "src/back/html.js";
import { getProxy } from "src/back/proxy.js";
export const actionName = "RulesCRUD";
const edit_fields = <const>{
name: new Fields.CollectionField(Rules.fields.name.required, Rules.fields.name),
code: new Fields.CollectionField(Rules.fields.code.required, Rules.fields.code),
active: new Fields.Boolean(Rules.fields.active.required),
};
const edit_controls = [
new Controls.SimpleInput(edit_fields.name, { label: "name" }),
new Controls.Checkbox(edit_fields.active, { label: "active" }),
new Controls.Textarea(edit_fields.code, {
label: "code",
cols: 80,
rows: 15,
autogrow: true,
placeholder: ``,
}),
new Controls.HTML(
"decoration",
/* HTML */ `<div>
Examples:
<h3>Change contents of all paragraphs to "p"</h3>
<pre><code>
rewriter.on("p", {
element(element) {
element.setInnerContent("new");
},
});
</code></pre>
<h3>Add an attribute to all links within a div with a class 'footer'</h3>
<pre><code>
-rewriter.on(".footer a", {
+rewriter.on("footer a", {
element(element) {
element.setAttribute("rel", "nofollow")
},
});
</code></pre>
</div>`
),
];
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const fields_for_display = [
{ field: "name", label: "name" },
{ field: "code", label: "code" },
{
field: "active",
label: "active",
format: (v: boolean) => (v ? "YES" : "NO"),
},
] as {
field: keyof (typeof Rules)["fields"];
label: string;
format?: (
value: unknown,
item: CollectionItem<typeof Rules>
) => string | Promise<string>;
}[];
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const fields_for_filters = [
{ field: "name", ...DefaultListFilters["text"] },
{ field: "code", ...DefaultListFilters["text"] },
{ field: "active", ...DefaultListFilters["boolean"] },
] as {
field: keyof (typeof Rules)["fields"];
render?: ListFilterRender;
prepareValue?: (filter_value: unknown) => unknown; // set this function to change what filter value is passed to Sealious
}[];
async function restart_proxy(ctx: Context) {
console.log("RESTARTING PROXY");
const proxy = getProxy(ctx.$app);
await proxy.stop();
await proxy.start();
}
export default new CRUD({
collection: Rules,
nice_collection_name: "Rules",
fields_for_display,
fields_for_filters,
html,
list_title: "Rules list",
edit_title: "Edit",
edit_button_text: "Edit",
delete_button_text: "Delete",
back_to_list_button_text: "← Back to Rules list",
edit_fields,
edit_controls,
form_value_to_sealious_value: {},
sealious_value_to_form_value: {},
post_edit: restart_proxy,
post_create: restart_proxy,
});

File Metadata

Mime Type
text/x-diff
Expires
Tue, Feb 25, 03:45 (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
610433
Default Alt Text
(6 KB)

Event Timeline