Skip to content

Commit

Permalink
feat(core): add viaProxy Utility to rewrite requests to proxy (motion…
Browse files Browse the repository at this point in the history
  • Loading branch information
WaldemarLehner committed Feb 16, 2023
1 parent 39443c4 commit 15264ba
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/2d/src/components/Image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SignalValue,
SimpleSignal,
} from '@motion-canvas/core/lib/signals';
import {viaProxy} from '@motion-canvas/core/lib/utils';

export interface ImageProps extends RectProps {
src?: SignalValue<string>;
Expand Down Expand Up @@ -54,7 +55,7 @@ export class Image extends Rect {

@computed()
protected image(): HTMLImageElement {
const src = this.src();
const src = viaProxy(this.src());
if (Image.pool[src]) {
return Image.pool[src];
}
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export * from './useThread';
export * from './useTime';
export * from './useContext';
export * from './useDuration';
export * from './viaProxy';
64 changes: 64 additions & 0 deletions packages/core/src/utils/viaProxy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {afterEach, describe, expect, test, vi} from 'vitest';
import {viaProxy} from './viaProxy';

const windowMock = {
location: {
toString: () => 'https://mockhostname:1234',
},
};

describe('viaProxy()', () => {
afterEach(() => {
vi.clearAllMocks();
});

vi.mock('virtual:proxysettings', () => ({enabled: false}));

describe('Pass requests as-is if proxying is disabled', () => {
test.each([
['Remote Address', 'https://example.com/image'],
['Local Address', 'https://mockhostname:1234/image'],
['Local Address No Host', '/image'],
])('%s', (_, val) => {
expect(viaProxy(val, false)).toEqual(val);
});
});

describe('Pass requests as-is if proxying is enabled, but requests go to local host', () => {
vi.stubGlobal('window', windowMock);

test.each([
['Local Address', 'https://mockhostname:1234/image'],
['Local Address No Host', '/image'],
])('%s', (_, val) => {
expect(viaProxy(val, true)).toEqual(val);
});
});

test('Transform request if proxying is enabled and request is remote', () => {
vi.stubGlobal('window', windowMock);

const address = 'https://example.com/some/image_resource.png?with_query';
expect(viaProxy(address, true)).toEqual(
`/cors-proxy/${encodeURIComponent(address)}`,
);
});

test('Unusual formats like base64 are to be ignored', () => {
vi.stubGlobal('window', windowMock); //

const address =
'data:image/png;base64,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';

expect(viaProxy(address, true)).toEqual(address);
});

test('Calling viaProxy multiple times should not break the result', () => {
vi.stubGlobal('window', windowMock);
const address = 'https://example.com/some/image_resource.png?with_query';

expect(viaProxy(address, true)).toEqual(
viaProxy(viaProxy(viaProxy(address, true), true), true),
);
});
});
57 changes: 57 additions & 0 deletions packages/core/src/utils/viaProxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Utility to redirect remote sources via Proxy
*
* This utility is used to rewrite a request to be routed through
* the Proxy instead.
*/

/**
* Virtual Module provided by the Motion Canvas
* Plugin. Returns `false` if proxy is set to `false`, else `true`
*/
//@ts-ignore
import {enabled} from 'virtual:proxysettings';

/**
* Helper-Function to route remote requests through a local proxy.
*
* @example This rewrites a remote url like `https://via.placeholder.com/300.png/09f/fff` into a URI-Component-Encoded string like `/cors-proxy/https%3A%2F%2Fvia.placeholder.com%2F300.png%2F09f%2Ffff`
*/
export function viaProxy(url: string, overrideProxySetting?: boolean) {
const isEnabled = overrideProxySetting ?? enabled;
if (!isEnabled) {
// Proxy is disabled, so we just pass as-is.
return url;
}

if (url.startsWith('/cors-proxy/')) {
// Already proxied, return as-is
return url;
}

// window.location.hostname is being passed here to ensure that
// this does not throw an Error for same-origin requests
// e.g. /some/image -> localhost:9000/some/image

const selfUrl = new URL(window.location.toString());
// inside a try-catch in case the URL cannot be understood
try {
const expandedUrl = new URL(url, selfUrl);
if (!expandedUrl.protocol.startsWith('http')) {
// this is probably some embedded image (e.g. image/png;base64).
// don't touch and pass as is
return url;
}
if (selfUrl.host === expandedUrl.host) {
// This is a request to a "local" resource.
// No need to rewrite
return url;
}
} catch (_) {
// in case of error just silently pass as-is
return url;
}

// Everything else is a "remote" resource and requires a rewrite.
return `/cors-proxy/${encodeURIComponent(url)}`;
}
1 change: 1 addition & 0 deletions packages/core/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {vi} from 'vitest';

vi.stubGlobal('AudioContext', class {});
vi.mock('virtual:proxysettings', () => ({enabled: true}));
13 changes: 13 additions & 0 deletions packages/vite-plugin/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ export default ({
const createHtml = (src: string) => htmlParts[0] + src + htmlParts[1];

const resolvedEditorId = '\0virtual:editor';
const proxySettingsKey = 'virtual:proxysettings';

const timeStamps: Record<string, number> = {};
const outputPath = path.resolve(output);
const projects: ProjectData[] = [];
Expand Down Expand Up @@ -136,6 +138,11 @@ export default ({
async configResolved(resolvedConfig) {
viteConfig = resolvedConfig;
},
resolveId(id) {
if (id === proxySettingsKey) {
return '\0' + proxySettingsKey;
}
},
async load(id) {
const [base, query] = id.split('?');
const {name, dir} = path.posix.parse(base);
Expand Down Expand Up @@ -167,6 +174,12 @@ export default ({
);
}

if (id.startsWith('\0' + proxySettingsKey)) {
return source(
`export const enabled = "${proxy === false ? 'false' : 'true'}" `,
);
}

if (query) {
const params = new URLSearchParams(query);
if (params.has('scene')) {
Expand Down

0 comments on commit 15264ba

Please sign in to comment.