Skip to content

Commit 9764dd3

Browse files
committed
initial import
1 parent 46a6792 commit 9764dd3

29 files changed

+2449
-0
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
order: 8
3+
title: "📅 Compatibility Dates"
4+
---
5+
6+
- [Compatibility Dates Reference](https://developers.cloudflare.com/workers/platform/compatibility-dates)
7+
8+
## Compatibility Dates
9+
10+
Miniflare uses compatibility dates to opt-into backwards-incompatible changes
11+
from a specific date. If one isn't set, it will default to some time far in the
12+
past.
13+
14+
import ConfigTabs from "../components/mdx/config-tabs";
15+
16+
```js
17+
const mf = new Miniflare({
18+
compatibilityDate: "2021-11-12",
19+
});
20+
```
21+
22+
## Compatibility Flags
23+
24+
Miniflare also lets you opt-in/out of specific changes using compatibility
25+
flags:
26+
27+
```js
28+
const mf = new Miniflare({
29+
compatibilityFlags: [
30+
"formdata_parser_supports_files",
31+
"durable_object_fetch_allows_relative_url",
32+
],
33+
});
34+
```
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
order: 0
3+
title: "📨 Fetch Events"
4+
---
5+
6+
- [`FetchEvent` Reference](https://developers.cloudflare.com/workers/runtime-apis/fetch-event)
7+
- [`FetchEvent` Lifecycle](https://developers.cloudflare.com/workers/learning/fetch-event-lifecycle)
8+
- [`addEventListener` Reference](https://developers.cloudflare.com/workers/runtime-apis/add-event-listener)
9+
10+
## HTTP Requests
11+
12+
Whenever an HTTP request is made, a `Request` object is dispatched to your worker, then the generated `Response` is returned. The
13+
`Request` object will include a
14+
[`cf` object](https://developers.cloudflare.com/workers/runtime-apis/request#incomingrequestcfproperties).
15+
Miniflare will log the method, path, status, and the time it took to respond.
16+
17+
If the worker throws an error whilst generating a response, an error page
18+
containing the stack trace is returned instead. You can use
19+
[🗺 Source Maps](/developing/source-maps) to make these point to your source
20+
files.
21+
22+
## Dispatching Events
23+
24+
When using the API, the `dispatchFetch` function can be used to dispatch `fetch`
25+
events to your worker. This can be used for testing responses. `dispatchFetch`
26+
has the same API as the regular `fetch` method: it either takes a `Request`
27+
object, or a URL and optional `RequestInit` object:
28+
29+
```js
30+
import { Miniflare, Request } from "miniflare";
31+
32+
const mf = new Miniflare({
33+
modules: true,
34+
script: `
35+
export default {
36+
async fetch(request, env, ctx) {
37+
const body = JSON.stringify({
38+
url: event.request.url,
39+
header: event.request.headers.get("X-Message"),
40+
});
41+
return new Response(body, {
42+
headers: { "Content-Type": "application/json" },
43+
});
44+
})
45+
}
46+
`,
47+
});
48+
49+
let res = await mf.dispatchFetch("http://localhost:8787/");
50+
console.log(await res.json()); // { url: "http://localhost:8787/", header: null }
51+
52+
res = await mf.dispatchFetch("http://localhost:8787/1", {
53+
headers: { "X-Message": "1" },
54+
});
55+
console.log(await res.json()); // { url: "http://localhost:8787/1", header: "1" }
56+
57+
res = await mf.dispatchFetch(
58+
new Request("http://localhost:8787/2", {
59+
headers: { "X-Message": "2" },
60+
}),
61+
);
62+
console.log(await res.json()); // { url: "http://localhost:8787/2", header: "2" }
63+
```
64+
65+
When dispatching events, you are responsible for adding
66+
[`CF-*` headers](https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-)
67+
and the
68+
[`cf` object](https://developers.cloudflare.com/workers/runtime-apis/request#incomingrequestcfproperties).
69+
This lets you control their values for testing:
70+
71+
```js
72+
const res = await mf.dispatchFetch("http://localhost:8787", {
73+
headers: {
74+
"CF-IPCountry": "GB",
75+
},
76+
cf: {
77+
country: "GB",
78+
},
79+
});
80+
```
81+
82+
## Upstream
83+
84+
Miniflare will call each `fetch` listener until a response is returned. If no
85+
response is returned, or an exception is thrown and `passThroughOnException()`
86+
has been called, the response will be fetched from the specified upstream
87+
instead:
88+
89+
```js
90+
import { Miniflare } from "miniflare";
91+
92+
const mf = new Miniflare({
93+
script: `
94+
addEventListener("fetch", (event) => {
95+
event.passThroughOnException();
96+
throw new Error();
97+
});
98+
`,
99+
upstream: "https://miniflare.dev",
100+
});
101+
// If you don't use the same upstream URL when dispatching, Miniflare will
102+
// rewrite it to match the upstream
103+
const res = await mf.dispatchFetch("https://miniflare.dev/core/fetch");
104+
console.log(await res.text()); // Source code of this page
105+
```
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
title: Core
3+
order: 2
4+
---
5+
6+
<DirectoryListing path="/core" />
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
order: 3
3+
title: "📚 Modules"
4+
---
5+
6+
- [Modules Reference](https://developers.cloudflare.com/workers/cli-wrangler/configuration#modules)
7+
8+
## Enabling Modules
9+
10+
Miniflare supports both the traditional `service-worker` and newer `modules`
11+
formats for writing workers. To use the `modules` format, enable it with:
12+
13+
```js
14+
const mf = new Miniflare({
15+
modules: true,
16+
});
17+
```
18+
19+
You can now use `modules` worker scripts like the following:
20+
21+
```js
22+
export default {
23+
async fetch(request, env, ctx) {
24+
// - `request` is the incoming `Request` instance
25+
// - `env` contains bindings, KV namespaces, Durable Objects, etc
26+
// - `ctx` contains `waitUntil` and `passThroughOnException` methods
27+
return new Response("Hello Miniflare!");
28+
},
29+
async scheduled(controller, env, ctx) {
30+
// - `controller` contains `scheduledTime` and `cron` properties
31+
// - `env` contains bindings, KV namespaces, Durable Objects, etc
32+
// - `ctx` contains the `waitUntil` method
33+
console.log("Doing something scheduled...");
34+
},
35+
};
36+
```
37+
38+
<Aside type="warning" header="Warning">
39+
40+
String scripts via the `script` option are supported using
41+
the `modules` format, but you cannot import other modules using them. You must
42+
use a script file via the `scriptPath` option for this.
43+
44+
</Aside>
45+
46+
## Module Rules
47+
48+
Miniflare supports all module types: `ESModule`, `CommonJS`, `Text`, `Data` and
49+
`CompiledWasm`. You can specify additional module resolution rules as follows:
50+
51+
```js
52+
const mf = new Miniflare({
53+
modulesRules: [
54+
{ type: "ESModule", include: ["**/*.js"], fallthrough: true },
55+
{ type: "Text", include: ["**/*.txt"] },
56+
],
57+
});
58+
```
59+
60+
### Default Rules
61+
62+
The following rules are automatically added to the end of your modules rules
63+
list. You can override them by specifying rules matching the same `globs`:
64+
65+
```toml
66+
[[build.upload.rules]]
67+
type = "ESModule"
68+
globs = ["**/*.mjs"]
69+
[[build.upload.rules]]
70+
type = "CommonJS"
71+
globs = ["**/*.js", "**/*.cjs"]
72+
```
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
order: 9
3+
title: "🔌 Multiple Workers"
4+
---
5+
6+
Miniflare allows you to run multiple workers in the same instance. All Workers can be defined at the same level, using the `workers` option.
7+
8+
Here's an example that uses a service binding to increment a value in a shared KV namespace:
9+
10+
```js
11+
import { Miniflare, Response } from "miniflare";
12+
13+
const message = "The count is ";
14+
const mf = new Miniflare({
15+
// Options shared between workers such as HTTP and persistence configuration
16+
// should always be defined at the top level.
17+
host: "0.0.0.0",
18+
port: 8787,
19+
kvPersist: true,
20+
21+
workers: [
22+
{
23+
name: "worker",
24+
kvNamespaces: { COUNTS: "counts" },
25+
serviceBindings: {
26+
INCREMENTER: "incrementer",
27+
// Service bindings can also be defined as custom functions, with access
28+
// to anything defined outside Miniflare.
29+
async CUSTOM(request) {
30+
// `request` is the incoming `Request` object.
31+
return new Response(message);
32+
},
33+
},
34+
modules: true,
35+
script: `export default {
36+
async fetch(request, env, ctx) {
37+
// Get the message defined outside
38+
const response = await env.CUSTOM.fetch("http://host/");
39+
const message = await response.text();
40+
41+
// Increment the count 3 times
42+
await env.INCREMENTER.fetch("http://host/");
43+
await env.INCREMENTER.fetch("http://host/");
44+
await env.INCREMENTER.fetch("http://host/");
45+
const count = await env.COUNTS.get("count");
46+
47+
return new Response(message + count);
48+
}
49+
}`,
50+
},
51+
{
52+
name: "incrementer",
53+
// Note we're using the same `COUNTS` namespace as before, but binding it
54+
// to `NUMBERS` instead.
55+
kvNamespaces: { NUMBERS: "counts" },
56+
// Worker formats can be mixed-and-matched
57+
script: `addEventListener("fetch", (event) => {
58+
event.respondWith(handleRequest());
59+
})
60+
async function handleRequest() {
61+
const count = parseInt((await NUMBERS.get("count")) ?? "0") + 1;
62+
await NUMBERS.put("count", count.toString());
63+
return new Response(count.toString());
64+
}`,
65+
},
66+
],
67+
});
68+
const res = await mf.dispatchFetch("http://localhost");
69+
console.log(await res.text()); // "The count is 3"
70+
await mf.dispose();
71+
```
72+
73+
## Routing
74+
75+
You can enable routing by specifying `routes` via the API,
76+
using the
77+
[standard route syntax](https://developers.cloudflare.com/workers/platform/routes#matching-behavior).
78+
Note port numbers are ignored:
79+
80+
```js
81+
const mf = new Miniflare({
82+
workers: [
83+
{
84+
scriptPath: "./api/worker.js",
85+
routes: ["http://127.0.0.1/api*", "api.mf/*"],
86+
},
87+
],
88+
});
89+
```
90+
91+
When using hostnames that aren't `localhost` or `127.0.0.1`, you
92+
may need to edit your computer's `hosts` file, so those hostnames resolve to
93+
`localhost`. On Linux and macOS, this is usually at `/etc/hosts`. On Windows,
94+
it's at `C:\Windows\System32\drivers\etc\hosts`. For the routes above, we would
95+
need to append the following entries to the file:
96+
97+
```
98+
127.0.0.1 miniflare.test
99+
127.0.0.1 api.mf
100+
```
101+
102+
Alternatively, you can customise the `Host` header when sending the request:
103+
104+
```sh
105+
# Dispatches to the "api" worker
106+
$ curl "http://localhost:8787/todos/update/1" -H "Host: api.mf"
107+
```
108+
109+
When using the API, Miniflare will use the request's URL to determine which
110+
worker to dispatch to.
111+
112+
```js
113+
// Dispatches to the "api" worker
114+
const res = await mf.dispatchFetch("http://api.mf/todos/update/1", { ... });
115+
```
116+
117+
## Durable Objects
118+
119+
Miniflare supports the `script_name` option for accessing Durable Objects
120+
exported by other scripts. See
121+
[📌 Durable Objects](/storage/durable-objects#using-a-class-exported-by-another-script)
122+
for more details.

0 commit comments

Comments
 (0)