Skip to content

Instantly share code, notes, and snippets.

@spookyuser
Last active February 18, 2025 12:33
Show Gist options
  • Save spookyuser/b40407dfe7474a49a0f72552fcd071e6 to your computer and use it in GitHub Desktop.
Save spookyuser/b40407dfe7474a49a0f72552fcd071e6 to your computer and use it in GitHub Desktop.
a fetch proxy for chrome extensions
import { defineProxyService } from "@webext-core/proxy-service"
interface SerializedResponse {
status: number
statusText: string
headers: Record<string, string>
data: number[]
ok: boolean
type: ResponseType
redirected: boolean
url: string
}
function reconstructResponse(serialized: SerializedResponse): Response {
const uint8Array = new Uint8Array(serialized.data)
const response = new Response(uint8Array, {
status: serialized.status,
statusText: serialized.statusText,
headers: new Headers(serialized.headers)
})
Object.defineProperty(response, "ok", {
get: () => serialized.ok
})
Object.defineProperty(response, "type", {
get: () => serialized.type
})
Object.defineProperty(response, "redirected", {
get: () => serialized.redirected
})
Object.defineProperty(response, "url", {
get: () => serialized.url
})
return response
}
class ProxyFetch {
async fetch(url: RequestInfo | URL, init?: RequestInit) {
const cleanInit: RequestInit = init ? { ...init } : {}
if ("signal" in cleanInit) {
cleanInit.signal = undefined
}
if (cleanInit?.body && typeof cleanInit.body === "string") {
try {
JSON.parse(cleanInit.body)
} catch (e) {
console.warn("Invalid JSON in request body:", e)
}
}
const response = await fetch(url, cleanInit)
const buffer = await response.arrayBuffer()
const uint8Array = new Uint8Array(buffer)
const array = Array.from(uint8Array)
return {
status: response.status,
statusText: response.statusText,
headers: Object.fromEntries(response.headers.entries()),
data: array,
ok: response.ok,
type: response.type,
redirected: response.redirected,
url: response.url
}
}
}
export const [registerFetchProxy, getFetchProxy] = defineProxyService(
"FetchProxy",
() => new ProxyFetch()
)
export function getProxiedFetch(): typeof fetch {
const proxy = getFetchProxy()
return async (
url: RequestInfo | URL,
init?: RequestInit
): Promise<Response> => {
const serialized = await proxy.fetch(url, init)
return reconstructResponse(serialized)
}
}
const [trpcClient] = useState(() =>
api.createClient({
links: [
loggerLink({
enabled: (op) =>
process.env.NODE_ENV === "development" ||
(op.direction === "down" && op.result instanceof Error)
}),
unstable_httpBatchStreamLink({
url: apiUrl,
transformer: SuperJSON,
fetch: proxiedFetch,
maxItems: 10
})
]
})
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment