← Cloudflare Workers / workers / configuration
Bindings (env)
Bindings umožňují vašemu Workeru interagovat se zdroji na Cloudflare Developer Platform. Bindings nabízejí lepší výkon a méně omezení při přístupu ke zdrojům z Workers než REST API které jsou určené pro aplikace mimo Workers.
Při lokálním vývoji se vazby (bindings) ve výchozím nastavení připojují k lokálně simulovaným prostředkům. Můžete je také nakonfigurovat tak, aby se připojovaly ke skutečným produkčním prostředkům pomocí vzdálené bindings.
V současné době jsou k dispozici následující bindings:
- AI
- Analytics Engine
- Assets
- Browser Run
- D1
- Dispatcher (Workers for Platforms)
- Durable Objects
- Dynamic Worker Loaders
- Proměnné prostředí
- Hyperdrive
- Obrázky
- KV
- Media Transformations
- mTLS
- Queues
- R2
- Rate Limiting
- Tajné klíče
- Secrets Store
- Service bindings
- Stream
- Vectorize
- Metadata verze
- Workflows
Co je binding?
Když ve svém Workeru deklarujete binding, udělíte mu tím konkrétní schopnost, například možnost číst a zapisovat soubory do R2 bucket. Například:
{
"main": "./src/index.js",
"r2_buckets": [
{
"binding": "MY_BUCKET",
"bucket_name": "<MY_BUCKET_NAME>"
}
]
}main = "./src/index.js"
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "<MY_BUCKET_NAME>"export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
await env.MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
},
};from workers import WorkerEntrypoint, Response
from urllib.parse import urlparse
class Default(WorkerEntrypoint):
async def fetch(self, request):
url = urlparse(request.url)
key = url.path.slice(1)
await self.env.MY_BUCKET.put(key, request.body)
return Response(f"Put {key} successfully!")Binding si můžete představit jako oprávnění a API v jednom. Díky bindingům nikdy nemusíte do svého Workeru přidávat tajné klíče ani tokeny, abyste získali přístup k prostředkům ve svém účtu Cloudflare: oprávnění je vestavěno přímo v samotném API. Podkladové tajemství se ke kódu vašeho Workeru nikdy nedostane, takže nemůže dojít k jeho náhodnému úniku.
Úprava vazeb
When you deploy a change to your Worker, and only change its bindings (i.e. you don't change the Worker's code), Cloudflare may reuse existing isolates that are already running your Worker. This improves performance, you can change an environment variable or other binding without unnecessarily reloading your code.
Proto musíte být opatrní, když do globálního rozsahu „znečišťujete“ deriváty svých bindings. Cokoli tam vytvoříte, může přetrvat i po změnách v podkladových bindings. Uvažujme instanci externího klienta, která používá tajný API klíč získaný z env: pokud tuto instanci klienta umístíte do globálního rozsahu a poté provedete změny tajného klíče, instance klienta s původní hodnotou může nadále existovat. Správným postupem je vytvořit novou instanci klienta pro každý požadavek.
Následující přístup je vhodný:
export default {
fetch(request, env) {
let client = new Client(env.MY_SECRET); // `client` is guaranteed to be up-to-date with the latest value of `env.MY_SECRET` since a new instance is constructed with every incoming request
// ... do things with `client`
},
};Ve srovnání s touto alternativou, která může mít překvapivé a nechtěné chování:
let client = undefined;
export default {
fetch(request, env) {
client ??= new Client(env.MY_SECRET); // `client` here might not be updated when `env.MY_SECRET` changes, since it may already exist in global scope
// ... do things with `client`
},
};Pokud máte pokročilejší požadavky, prozkoumejte AsyncLocalStorage API, který poskytuje mechanismus pro zpřístupnění hodnot podřízeným obslužným rutinám provádění.
Jak přistupovat k env
Bindings najdete na env objekt, ke kterému lze přistupovat několika způsoby:
-
Jde o argument obslužných rutin vstupního bodu, jako je
fetch:export default { async fetch(request, env) { return new Response(`Hi, ${env.NAME}`); }, };
-
Jde o vlastnost třídy na WorkerEntrypoint, DurableObject, a Workflow:
export class MyDurableObject extends DurableObject { async sayHello() { return `Hi, ${this.env.NAME}!`; } }from workers import WorkerEntrypoint, Response class Default(WorkerEntrypoint): async def fetch(self, request): return Response(f"Hi {self.env.NAME}") -
Lze jej importovat z
cloudflare:workers:import { env } from "cloudflare:workers"; console.log(`Hi, ${env.Name}`);from workers import env print(f"Hi, {env.NAME}")
Import env jako globální
Import env z cloudflare:workers je užitečné, když potřebujete přistupovat k bindingu,
jako je secrets nebo proměnné prostředí
v globálním rozsahu nejvyšší úrovně. Například pro inicializaci klienta API:
import { env } from "cloudflare:workers";
import ApiClient from "example-api-client";
// API_KEY and LOG_LEVEL now usable in top-level scope
let apiClient = ApiClient.new({ apiKey: env.API_KEY });
const LOG_LEVEL = env.LOG_LEVEL || "info";
export default {
fetch(req) {
// you can use apiClient or LOG_LEVEL, configured before any request is handled
},
};from workers import WorkerEntrypoint, env
from example_api_client import ApiClient
api_client = ApiClient(api_key=env.API_KEY)
LOG_LEVEL = getattr(env, "LOG_LEVEL", "info")
class Default(WorkerEntrypoint):
async def fetch(self, request):
# ...Workers neumožňují I/O mimo kontext požadavku. To znamená, že i
přesto, že env je přístupná z top-level scope, nebudete mít přístup
ke všem metodám jednotlivých bindingů.
Máte tak například přístup k proměnným prostředí a secrets a můžete
volat env.NAMESPACE.get k získání Stub Durable Object v
kontextu nejvyšší úrovně. Avšak volání metod na stubu Durable Object, jako je provádění volání do úložiště KV,
a volání jiných Workerů nebude fungovat.
import { env } from "cloudflare:workers";
// This would error!
// env.KV.get('my-key')
export default {
async fetch(req) {
// This works
let myVal = await env.KV.get("my-key");
Response.new(myVal);
},
};from workers import Response, WorkerEntrypoint, env
# This would fail!
# env.KV.get('my-key')
class Default(WorkerEntrypoint):
async def fetch(self, request):
# This works
mv_val = await env.KV.get("my-key")
return Response(my_val)Kromě toho import env z cloudflare:workers vám umožňuje vyhnout se předávání env
jako argument napříč mnoha voláními funkcí, pokud potřebujete přistupovat k bindingu z hluboce vnořené
funkce. To může být užitečné ve složité kódové základně.
import { env } from "cloudflare:workers";
export default {
fetch(req) {
Response.new(sayHello());
},
};
// env is not an argument to sayHello...
function sayHello() {
let myName = getName();
return `Hello, ${myName}`;
}
// ...nor is it an argument to getName
function getName() {
return env.MY_NAME;
}from workers import Response, WorkerEntrypoint, env
class Default(WorkerEntrypoint):
def fetch(req):
return Response(say_hello())
# env is not an argument to say_hello...
def say_hello():
my_name = get_name()
return f"Hello, {myName}"
# ...nor is it an argument to getName
def get_name():
return env.MY_NAMEPřepisování env hodnoty
withEnv funkce poskytuje mechanismus pro přepsání hodnot env.
Představte si, že uživatel definoval proměnná prostředí
„NAME“ na „Alice“ v konfiguračním souboru Wrangler a nasadili Worker. Ve výchozím nastavení protokolování
env.NAME by vypsalo „Alice“. Pomocí withEnv funkci můžete přepsat hodnotu
"NAME".
import { env, withEnv } from "cloudflare:workers";
function logName() {
console.log(env.NAME);
}
export default {
fetch(req) {
// this will log "Alice"
logName();
withEnv({ NAME: "Bob" }, () => {
// this will log "Bob"
logName();
});
// ...etc...
},
};from workers import Response, WorkerEntrypoint, env, patch_env
def log_name():
print(env.NAME)
class Default(WorkerEntrypoint):
async def fetch(req):
# this will log "Alice"
log_name()
with patch_env(NAME="Bob"):
# this will log "Bob"
log_name()
# ...etc...To může být užitečné při testování kódu, který se spoléhá na importovaný env objekt.