Skip to content

Commit

Permalink
fix: replace URLs on the response to self hostname
Browse files Browse the repository at this point in the history
  • Loading branch information
esroyo committed May 15, 2023
1 parent 522f301 commit 6823b3d
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 36 deletions.
22 changes: 22 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions importmap.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"imports": {
"@rollup/plugin-terser": "https://esm.sh/@rollup/plugin-terser",
"@rollup/plugin-virtual": "https://esm.sh/@rollup/plugin-virtual",
"rollup": "https://esm.sh/rollup",
"testing/asserts": "https://deno.land/std/testing/asserts.ts",
"testing/mock": "https://deno.land/std/testing/mock.ts",
"http": "https://deno.land/std/http/mod.ts"

}
}
44 changes: 26 additions & 18 deletions src/esm-proxy-request-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,32 @@ import { assertEquals } from 'testing/asserts';
import { assertSpyCallArg, returnsNext, stub } from 'testing/mock';
import { esmProxyRequestHandler } from './esm-proxy-request-handler.ts';

Deno.test('should return an string of code in systemjs format', async () => {
const fetchStub = stub(globalThis, 'fetch', returnsNext([
Promise.resolve({ text: () => Promise.resolve('export * from "https://esm.sh/stable/vue@3.3.2/es2022/vue.mjs";') } as unknown as Response),
]));
const req = new Request('https://systemjs.sh/vue');
const res = await esmProxyRequestHandler(req);
const systemjsCode = await res.text();
assertEquals(systemjsCode.startsWith('System.register('), true);
fetchStub.restore();
});
Deno.test('esmProxyRequestHandler', async (t) => {

const ESM_SERVICE_HOST = 'esm.sh';
const SELF_HOST = 'systemjs.sh';
const fetchReturn = Promise.resolve({ text: () => Promise.resolve(`export * from "https://${ESM_SERVICE_HOST}/stable/vue@3.3.2/es2022/vue.mjs";`) } as unknown as Response);
const fetchStub = stub(globalThis, 'fetch', returnsNext([fetchReturn, fetchReturn, fetchReturn]));

await t.step('should forward the request to ESM_SERVICE_HOST keeping the parameters', async () => {
const req = new Request(`https://${SELF_HOST}/foo?bundle`);
await esmProxyRequestHandler(req);
assertSpyCallArg(fetchStub, 0, 0, `https://${ESM_SERVICE_HOST}/foo?bundle`);
});

await t.step('should return an string of code in systemjs format', async () => {
const req = new Request(`https://${SELF_HOST}/vue`);
const res = await esmProxyRequestHandler(req);
const systemjsCode = await res.text();
assertEquals(systemjsCode.startsWith('System.register('), true);
});

await t.step('should replace the ESM_SERVICE_HOST by the self host', async () => {
const req = new Request(`https://${SELF_HOST}/vue`);
const res = await esmProxyRequestHandler(req);
const systemjsCode = await res.text();
assertEquals(!!systemjsCode.match(new RegExp(`https://${SELF_HOST}/stable/vue@3.3.2/es2022/vue.mjs`)), true);
});

Deno.test('should forward the request to host "esm.sh" keeping the parameters', async () => {
const fetchStub = stub(globalThis, 'fetch', returnsNext([
Promise.resolve({ text: () => Promise.resolve('export default "foo"') } as unknown as Response),
]));
const req = new Request('https://systemjs.sh/foo?bundle');
const res = await esmProxyRequestHandler(req);
const systemjsCode = await res.text();
assertSpyCallArg(fetchStub, 0, 0, 'https://esm.sh/foo?bundle');
fetchStub.restore();
});
25 changes: 10 additions & 15 deletions src/esm-proxy-request-handler.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import { toSystemjs } from './to-systemjs.ts';

const ESM_SERVICE_HOST = 'esm.sh';

export async function esmProxyRequestHandler(req: Request): Promise<Response | never> {
let modifiedUrl: URL;
let esmCode: string;
try {
modifiedUrl = new URL(req.url);
modifiedUrl.hostname = 'esm.sh';
esmCode = await fetch(modifiedUrl.toString(), { headers: req.headers }).then((res) => res.text());
const systemjsCode = await toSystemjs(esmCode);
return new Response(systemjsCode);
} catch (error) {
// @ts-ignore
console.log(modifiedUrl?.toString());
// @ts-ignore
console.log(esmCode);
throw error;
}
const modifiedUrl = new URL(req.url);
const selfHost = modifiedUrl.host;
modifiedUrl.host = ESM_SERVICE_HOST;
const esmCode = await fetch(modifiedUrl.toString(), { headers: req.headers }).then((res) => res.text());
const systemjsCode = await toSystemjs(esmCode);
return new Response(
systemjsCode.replace(new RegExp(`//${ESM_SERVICE_HOST}/`, 'ig'), `//${selfHost}/`)
);
}
6 changes: 3 additions & 3 deletions src/to-systemjs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ModuleFormat, rollup } from 'rollup';
//import terser from '@rollup/plugin-terser';
import virtual from '@rollup/plugin-virtual';
//import { minify } from 'npm:rollup-plugin-esbuild';

export const toSystemjs = async (esmCode: string): Promise<string> => {

Expand All @@ -9,7 +9,7 @@ export const toSystemjs = async (esmCode: string): Promise<string> => {
input: 'esmCode',
plugins: [
virtual({ esmCode }),
//minify(),
//terser(),
],
treeshake: false,
};
Expand All @@ -23,5 +23,5 @@ export const toSystemjs = async (esmCode: string): Promise<string> => {
const bundle = await rollup(inputOptions);
const { output } = await bundle.generate(outputOptions);
await bundle.close();
return output[0].code.replace(/https:\/\/esm\.sh\//g, 'https://systemjs.sh/');
return output[0].code;
}

0 comments on commit 6823b3d

Please sign in to comment.