You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform. Bindings provide better performance and less restrictions when accessing resources from Workers than the [REST APIs](/api/) which are intended for non-Workers applications.
12
11
@@ -31,12 +30,12 @@ r2_buckets = [
31
30
32
31
```js
33
32
exportdefault {
34
-
asyncfetch(request, env) {
35
-
constkey=url.pathname.slice(1);
36
-
awaitenv.MY_BUCKET.put(key, request.body);
37
-
returnnewResponse(`Put ${key} successfully!`);
38
-
}
39
-
}
33
+
asyncfetch(request, env) {
34
+
constkey=url.pathname.slice(1);
35
+
awaitenv.MY_BUCKET.put(key, request.body);
36
+
returnnewResponse(`Put ${key} successfully!`);
37
+
},
38
+
};
40
39
```
41
40
42
41
You can think of a binding as a permission and an API in one piece. With bindings, you never have to add secret keys or tokens to your Worker in order to access resources on your Cloudflare account — the permission is embedded within the API itself. The underlying secret is never exposed to your Worker's code, and therefore can't be accidentally leaked.
@@ -51,12 +50,12 @@ The following is a good approach:
51
50
52
51
```ts
53
52
exportdefault {
54
-
fetch(request, env) {
55
-
let client =newClient(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
53
+
fetch(request, env) {
54
+
let client =newClient(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
56
55
57
-
// ... do things with `client`
58
-
}
59
-
}
56
+
// ... do things with `client`
57
+
},
58
+
};
60
59
```
61
60
62
61
Compared to this alternative, which might have surprising and unwanted behavior:
@@ -65,12 +64,148 @@ Compared to this alternative, which might have surprising and unwanted behavior:
65
64
let client =undefined;
66
65
67
66
exportdefault {
68
-
fetch(request, env) {
69
-
client??=newClient(env.MY_SECRET); // `client` here might not be updated when `env.MY_SECRET` changes, since it may already exist in global scope
67
+
fetch(request, env) {
68
+
client??=newClient(env.MY_SECRET); // `client` here might not be updated when `env.MY_SECRET` changes, since it may already exist in global scope
69
+
70
+
// ... do things with `client`
71
+
},
72
+
};
73
+
```
74
+
75
+
If you have more advanced needs, explore the [AsyncLocalStorage API](/workers/runtime-apis/nodejs/asynclocalstorage/), which provides a mechanism for exposing values down to child execution handlers.
76
+
77
+
## How to access `env`
78
+
79
+
Bindings are located on the `env` object, which can be accessed in several ways:
80
+
81
+
- It is an argument to entrypoint handlers such as [`fetch`](/workers/runtime-apis/fetch/):
82
+
83
+
```js
84
+
exportdefault {
85
+
asyncfetch(request, env) {
86
+
returnnewResponse(`Hi, ${env.NAME}`);
87
+
},
88
+
};
89
+
```
70
90
71
-
// ... do things with `client`
91
+
* It is as class property on [WorkerEntrypoint](/workers/runtime-apis/bindings/service-bindings/rpc/#bindings-env),
92
+
[DurableObject](/durable-objects/), and [Workflow](/workflows/):
93
+
94
+
```js
95
+
exportclassMyDurableObjectextendsDurableObject {
96
+
asyncsayHello() {
97
+
return`Hi, ${this.env.NAME}!`;
98
+
}
72
99
}
100
+
```
101
+
102
+
* It can be imported from `cloudflare:workers`:
103
+
104
+
```js
105
+
import { env } from"cloudflare:workers";
106
+
console.log(`Hi, ${this.env.Name}`);
107
+
```
108
+
109
+
### Importing `env`
110
+
111
+
Importing `env` from `cloudflare:workers` is useful when you need to access a binding
112
+
such as [secrets](/workers/configuration/secrets/) or [environment variables](/workers/configuration/environment-variables/)
113
+
to do initial Worker configuration.
114
+
115
+
```js
116
+
import { env } from"cloudflare:workers";
117
+
importApiClientfrom"example-api-client";
118
+
119
+
// API_KEY and LOG_LEVEL now usable in top-level scope
120
+
let apiClient =ApiClient.new({ apiKey:env.API_KEY });
121
+
constLOG_LEVEL=env.LOG_LEVEL||"info";
122
+
123
+
exportdefault {
124
+
fetch(req) {
125
+
// you can use apiClient or LOG_LEVEL, configured before any request is handled
126
+
},
127
+
};
128
+
```
129
+
130
+
Workers do not allow I/O outside of a request context. This means that certain bindings will
131
+
not work from the top-level context. For instance, making a call to the [KV binding](/kv/concepts/kv-bindings/)
132
+
will error, but making it from within a request will work.
133
+
134
+
```js
135
+
import { env } from"cloudflare:workers";
136
+
137
+
// This would error!
138
+
// env.KV.get('my-key')
139
+
140
+
exportdefault {
141
+
asyncfetch(req) {
142
+
// This works
143
+
let myVal =awaitenv.KV.get("my-key");
144
+
Response.new(myVal);
145
+
},
146
+
};
147
+
```
148
+
149
+
Additionally, importing `env` from `cloudflare:workers` lets you avoid passing `env`
150
+
as an argument through many function calls if you need to access a binding from a deeply-nested
151
+
function. This can be helpful in a complex codebase.
152
+
153
+
```js
154
+
import { env } from"cloudflare:workers";
155
+
156
+
exportdefault {
157
+
fetch(req) {
158
+
Response.new(sayHello());
159
+
},
160
+
};
161
+
162
+
// env is not an argument to sayHello...
163
+
functionsayHello() {
164
+
let myName =getName();
165
+
return`Hello, ${myName}`;
166
+
}
167
+
168
+
// ...nor is it an argument to getName
169
+
functiongetName() {
170
+
returnenv.MY_NAME;
73
171
}
74
172
```
75
173
76
-
If you have more advanced needs, explore the [AsyncLocalStorage API](/workers/runtime-apis/nodejs/asynclocalstorage/), which provides a mechanism for exposing values down to child execution handlers.
174
+
:::note
175
+
While using `env` from `cloudflare:workers` may be simpler to write than passing it
176
+
through a series of function calls, passing `env` as an argument is a helpful pattern
177
+
for dependency injection and testing.
178
+
:::
179
+
180
+
### Overriding `env` values
181
+
182
+
The `withEnv` function provides a mechanism for overriding values of `env`.
183
+
184
+
Imagine a user has defined the [environment variable](/workers/configuration/environment-variables/)
185
+
"NAME" to be "Alice" in their Wrangler configuration file and deployed a worker. By default, logging
186
+
`env.NAME` would print "Alice". Using the `withEnv` function, you can override the value of
187
+
"NAME".
188
+
189
+
```js
190
+
import { env, withEnv } from"cloudflare:workers";
191
+
192
+
functionlogName() {
193
+
console.log(env.NAME);
194
+
}
195
+
196
+
exportdefault {
197
+
fetch(req) {
198
+
// this will log "Alice"
199
+
logName();
200
+
201
+
withEnv({ NAME:"Bob" }, () => {
202
+
// this will log "Bob"
203
+
logName();
204
+
});
205
+
206
+
// ...etc...
207
+
},
208
+
};
209
+
```
210
+
211
+
This can be useful when testing code that relies on an imported `env` object.
0 commit comments