Files
wasm-http-server/sw.js

95 lines
2.3 KiB
JavaScript
Raw Normal View History

class WasmHTTP {
#listeners = new Map();
setHandler(path, handler) {
const listener = this.#listeners.get(path);
if (!listener) {
throw new Error(`no listener for path "${path}"`);
2021-01-22 00:58:30 +01:00
}
listener.setHandler(handler);
}
handle(e) {
const { pathname } = new URL(e.request.url);
for (const [path, listener] of this.#listeners) {
if (pathname.startsWith(path)) {
listener.handle(e);
return;
}
}
}
addListener({ wasm, base = '', cacheName, passthrough, args = [], env = {} }) {
const path = new URL(trimStart(base, '/'), registration.scope).pathname;
if (this.#listeners.has(path)) {
throw new Error(`a listener is already registered for path "${path}"`);
}
2021-01-21 23:07:42 +01:00
this.#listeners.set(path, new WasmHTTPListener({ wasm, path, cacheName, passthrough, args, env }));
}
2021-01-21 23:23:27 +01:00
}
class WasmHTTPListener {
#handlerPromise;
#resolveHandler;
#passthrough;
constructor({ wasm, path, cacheName, passthrough, args, env }) {
this.#handlerPromise = new Promise((resolve) => {
this.#resolveHandler = resolve;
});
this.#passthrough = passthrough;
this.#run({ wasm, path, cacheName, passthrough, args, env });
}
async #run({ wasm, path, cacheName, args, env }) {
try {
const go = new Go();
go.argv = [wasm, ...args];
go.env = { ...env, WASM_HTTP_PATH: path };
const cache = cacheName ? await caches.open(cacheName) : caches;
const source = (await cache.match(wasm)) ?? (await fetch(wasm));
const { instance } = await WebAssembly.instantiateStreaming(source, go.importObject);
await go.run(instance);
} catch (err) {
console.error(`error while running ${wasm} for path "${path}"`, err);
}
}
setHandler(handler) {
this.#resolveHandler(handler);
}
handle(e) {
if (this.#passthrough?.(e.request)) return;
// FIXME return 500 if run has thrown
e.respondWith(this.#handlerPromise.then((handler) => handler(e.request)));
}
}
self.wasmhttp = new WasmHTTP();
addEventListener('fetch', (e) => {
self.wasmhttp.handle(e);
});
function registerWasmHTTPListener(wasm, { base, cacheName, passthrough, args, env } = {}) {
self.wasmhttp.addListener({ wasm, base, cacheName, passthrough, args, env });
2021-01-21 23:23:27 +01:00
}
function trimStart(s, c) {
let r = s;
while (r.startsWith(c)) r = r.slice(c.length);
return r;
2021-01-21 23:23:27 +01:00
}