← Dynamic Workers / dynamic-workers / usage
Řízení odchozího provozu
Když v dynamickém Workeru spouštíte nedůvěryhodný nebo AI generovaný kód, musíte mít kontrolu nad tím, k čemu má v síti přístup. Můžete například chtít:
- blokovat veškerý odchozí přístup, aby dynamický Worker mohl používat pouze vazby který mu předáte
- omezit odchozí požadavky na konkrétní sadu povolených cílů
- vkládat přihlašovací údaje do odchozích požadavků, aniž by byly tajné údaje vystaveny dynamickému Workeru
- protokolovat nebo auditovat každý odchozí požadavek pro účely observability
globalOutbound možnost v WorkerCode objekt vrácený get() nebo předán do load() to vše řídí. Zachytává každé fetch() a connect() volání, které dynamic Worker provede.
Blokování veškerého odchozího přístupu
Nastavte globalOutbound na null k úplné izolaci dynamic Workeru od sítě:
return {
mainModule: "index.js",
modules: { "index.js": code },
globalOutbound: null,
};Tím se způsobí, že jakýkoli fetch() nebo connect() požadavku z dynamic Workeru vyvolat výjimku.
I v tomto režimu můžete Dynamic Workeru dát přímý přístup ke konkrétním prostředkům a službám pomocí vazby. Toto je nejčistší a nejbezpečnější způsob návrhu sandboxu: nejprve zablokujte přístup k internetu a poté cíleně povolte konkrétní schopnosti prostřednictvím bindingů.
Pokud však potřebujete zajistit kompatibilitu se stávajícími HTTP klientskými knihovnami běžícími přímo ve vašem sandboxu Dynamic Workeru, pak blokující fetch() nemusí být proveditelné a je možné, že budete raději zachytávat požadavky.
Zachytávání odchozích požadavků
Chcete-li zachytávat odchozí požadavky, definujte WorkerEntrypoint třídu v loader Workeru, která funguje jako brána. Každé fetch() a connect() volání, které dynamic Worker provede, prochází touto bránou místo přímého přístupu k síti. Bránu dynamic Workeru předáte pomocí globalOutbound a ctx.exports:
import { WorkerEntrypoint } from "cloudflare:workers";
export class HttpGateway extends WorkerEntrypoint {
async fetch(request) {
// Every outbound fetch() from the dynamic Worker arrives here.
// Inspect, modify, block, or forward the request.
return fetch(request);
}
}
export default {
async fetch(request, env, ctx) {
const worker = env.LOADER.get("my-worker", async () => {
return {
compatibilityDate: "$today",
mainModule: "index.js",
modules: { "index.js": code },
// Pass the gateway as a service binding.
// The dynamic Worker's fetch() and connect() calls
// are routed through HttpGateway instead of going
// to the network directly.
globalOutbound: ctx.exports.HttpGateway(),
};
});
return worker.getEntrypoint().fetch(request);
},
};Odtud můžete do brány přidat libovolnou logiku, například omezení cílů, vkládání přihlašovacích údajů nebo logování požadavků.
Vložení přihlašovacích údajů
Běžným postupem je připojit přihlašovací údaje k odchozím požadavkům tak, aby dynamický Worker nikdy neviděl tajný údaj. Podobně jako u vlastní bindingy, můžete použít ctx.props k předání kontextu pro jednotlivé tenanty nebo požadavky do gateway.
Dynamický Worker zavolá fetch() běžným způsobem. HttpGateway zachytí požadavek, připojí token z prostředí loader Workeru a přepošle ho dál. Dynamic Worker nikdy nemá přístup k API_TOKEN.
import { WorkerEntrypoint } from "cloudflare:workers";
export class HttpGateway extends WorkerEntrypoint {
async fetch(request) {
let url = new URL(request.url);
const headers = new Headers(request.headers);
// For requests to api.example.com, inject credentials.
if (url.hostname === "api.example.com") {
headers.set("Authorization", `Bearer ${this.env.API_TOKEN}`);
headers.set("X-Tenant-Id", this.ctx.props.tenantId);
}
return fetch(request, { headers });
}
}
export default {
async fetch(request, env, ctx) {
const tenantId = getTenantFromRequest(request);
const worker = env.LOADER.get(`tenant:${tenantId}`, async () => {
return {
mainModule: "index.js",
modules: {
"index.js": `
export default {
async fetch() {
const resp = await fetch("https://api.example.com/data");
return new Response(await resp.text());
},
};
`,
},
globalOutbound: ctx.exports.HttpGateway({
props: { tenantId },
}),
};
});
return worker.getEntrypoint().fetch(request);
},
};