docs/src/lib/path-redirect.ts 1.5 K raw
1
// Cloudflare Workers compatibility patches for @atproto libraries.
2
//
3
// 1. Workers don't support `redirect: 'error'` — simulate it with 'manual'.
4
// 2. Workers don't support the standard `cache` option in Request — strip it.
5
6
function sanitizeInit(init?: RequestInit): RequestInit | undefined {
7
	if (!init) return init;
8
	const { cache, redirect, ...rest } = init;
9
	return {
10
		...rest,
11
		// Workers only support 'follow' and 'manual'
12
		redirect: redirect === "error" ? "manual" : redirect,
13
		// Workers don't support standard cache modes — omit entirely
14
		...(cache ? {} : {}),
15
	};
16
}
17
18
const errorRedirectRequests = new WeakSet<Request>();
19
const OriginalRequest = globalThis.Request;
20
21
globalThis.Request = class extends OriginalRequest {
22
	constructor(input: RequestInfo | URL, init?: RequestInit) {
23
		super(input, sanitizeInit(init));
24
		if (init?.redirect === "error") {
25
			errorRedirectRequests.add(this);
26
		}
27
	}
28
} as typeof Request;
29
30
const originalFetch = globalThis.fetch;
31
globalThis.fetch = (async (
32
	input: RequestInfo | URL,
33
	init?: RequestInit,
34
): Promise<Response> => {
35
	const cleanInit = sanitizeInit(init);
36
	const response = await originalFetch(input, cleanInit);
37
38
	// Simulate redirect: 'error' — throw on 3xx
39
	const wantsRedirectError =
40
		init?.redirect === "error" ||
41
		(input instanceof Request && errorRedirectRequests.has(input));
42
43
	if (wantsRedirectError && response.status >= 300 && response.status < 400) {
44
		throw new TypeError("unexpected redirect");
45
	}
46
47
	return response;
48
}) as typeof fetch;