Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions documentation/docs/globals/FetchEvent/FetchEvent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,7 @@ It provides the [`event.respondWith()`](./prototype/respondWith.mdx) method, whi

- [`FetchEvent.respondWith()`](./prototype/respondWith.mdx)
- : Provide (a promise for) a response for this request.
- [`FetchEvent.sendEarlyHint()`](./prototype/sendEarlyHint.mdx)
- : Send a [103 Early Hints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/103) response for this request.
- [`FetchEvent.waitUntil()`](./prototype/waitUntil.mdx)
- : Extends the lifetime of the event. Used to notify the host environment of tasks that extend beyond the returning of a response, such as streaming and caching.
37 changes: 37 additions & 0 deletions documentation/docs/globals/FetchEvent/prototype/sendEarlyHints.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
hide_title: false
hide_table_of_contents: false
pagination_next: null
pagination_prev: null
---
# FetchEvent.sendEarlyHints()

The **`sendEarlyHints()`** method allows you to send a [103 Early Hints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/103) response back to the client which made the incoming request to your application.

## Syntax

```js
sendEarlyHints(headers)
```

### Parameters

- `headers`
- : Any headers you want to add to your response, contained
within a [`Headers`](../../globals/Headers/Headers.mdx) object or object literal of
[`String`](../../globals/String/String.mdx) key/value pairs.

### Return value

Always returns `undefined`.

### Examples

```js
event.sendEarlyHints({ link: '</style.css>; rel=preload; as=style' });

event.sendEarlyHints([
['link', '</style.css>; rel=preload; as=style'],
['link', '</style2.css>; rel=preload; as=style']
]);
```
25 changes: 25 additions & 0 deletions integration-tests/js-compute/fixtures/app/src/early-hints.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { pass, ok, strictEqual, assertThrows } from './assertions.js';
import { routes } from './routes.js';

routes.set('/early-hints/manual-response', (event) => {
event.respondWith(
new Response(null, {
status: 103,
headers: { link: '</style.css>; rel=preload; as=style' },
}),
);
event.respondWith(new Response('ok'));
});

routes.set('/early-hints/send-early-hints', (event) => {
event.sendEarlyHints({ link: '</style.css>; rel=preload; as=style' });
event.respondWith(new Response('ok'));
});

routes.set('/early-hints/send-early-hints-multiple-headers', (event) => {
event.sendEarlyHints([
['link', '</style.css>; rel=preload; as=style'],
['link', '</style2.css>; rel=preload; as=style'],
]);
event.respondWith(new Response('ok'));
});
1 change: 1 addition & 0 deletions integration-tests/js-compute/fixtures/app/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import './config-store.js';
import './crypto.js';
import './device.js';
import './dictionary.js';
import './early-hints.js';
import './edge-rate-limiter.js';
import './env.js';
import './fanout.js';
Expand Down
210 changes: 167 additions & 43 deletions integration-tests/js-compute/fixtures/app/tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,72 @@
"GET /cache-override/fetch/mode-pass": {
"flake": true
},
"GET /secret-store/exposed-as-global": { "flake": true },
"GET /secret-store/interface": { "flake": true },
"GET /secret-store/constructor/called-as-regular-function": { "flake": true },
"GET /secret-store/exposed-as-global": {
"flake": true
},
"GET /secret-store/interface": {
"flake": true
},
"GET /secret-store/constructor/called-as-regular-function": {
"flake": true
},
"GET /secret-store/constructor/parameter-calls-7.1.17-ToString": {
"flake": true
},
"GET /secret-store/constructor/empty-parameter": { "flake": true },
"GET /secret-store/constructor/found-store": { "flake": true },
"GET /secret-store/constructor/missing-store": { "flake": true },
"GET /secret-store/constructor/invalid-name": { "flake": true },
"GET /secret-store/get/called-as-constructor": { "flake": true },
"GET /secret-store/get/called-unbound": { "flake": true },
"GET /secret-store/constructor/empty-parameter": {
"flake": true
},
"GET /secret-store/constructor/found-store": {
"flake": true
},
"GET /secret-store/constructor/missing-store": {
"flake": true
},
"GET /secret-store/constructor/invalid-name": {
"flake": true
},
"GET /secret-store/get/called-as-constructor": {
"flake": true
},
"GET /secret-store/get/called-unbound": {
"flake": true
},
"GET /secret-store/get/key-parameter-calls-7.1.17-ToString": {
"flake": true
},
"GET /secret-store/get/key-parameter-not-supplied": { "flake": true },
"GET /secret-store/get/key-parameter-empty-string": { "flake": true },
"GET /secret-store/get/key-parameter-255-character-string": { "flake": true },
"GET /secret-store/get/key-parameter-256-character-string": { "flake": true },
"GET /secret-store/get/key-parameter-invalid-string": { "flake": true },
"GET /secret-store/get/key-does-not-exist-returns-null": { "flake": true },
"GET /secret-store/get/key-exists": { "flake": true },
"GET /secret-store/from-bytes/invalid": { "flake": true },
"GET /secret-store/from-bytes/valid": { "flake": true },
"GET /secret-store-entry/interface": { "flake": true },
"GET /secret-store-entry/plaintext": { "flake": true },
"GET /secret-store/get/key-parameter-not-supplied": {
"flake": true
},
"GET /secret-store/get/key-parameter-empty-string": {
"flake": true
},
"GET /secret-store/get/key-parameter-255-character-string": {
"flake": true
},
"GET /secret-store/get/key-parameter-256-character-string": {
"flake": true
},
"GET /secret-store/get/key-parameter-invalid-string": {
"flake": true
},
"GET /secret-store/get/key-does-not-exist-returns-null": {
"flake": true
},
"GET /secret-store/get/key-exists": {
"flake": true
},
"GET /secret-store/from-bytes/invalid": {
"flake": true
},
"GET /secret-store/from-bytes/valid": {
"flake": true
},
"GET /secret-store-entry/interface": {
"flake": true
},
"GET /secret-store-entry/plaintext": {
"flake": true
},
"GET /simple-cache/interface": {},
"GET /simple-store/constructor/called-as-regular-function": {
"flake": true,
Expand Down Expand Up @@ -409,7 +449,9 @@
"GET /client/tlsClientCertificate": {},
"GET /client/tlsCipherOpensslName": {},
"GET /client/tlsProtocol": {},
"GET /config-store": { "flake": true },
"GET /config-store": {
"flake": true
},
"GET /crypto": {
"downstream_response": {
"status": 200,
Expand Down Expand Up @@ -980,24 +1022,54 @@
"body": "ok"
}
},
"GET /dictionary/exposed-as-global": { "flake": true },
"GET /dictionary/interface": { "flake": true },
"GET /dictionary/constructor/called-as-regular-function": { "flake": true },
"GET /dictionary/exposed-as-global": {
"flake": true
},
"GET /dictionary/interface": {
"flake": true
},
"GET /dictionary/constructor/called-as-regular-function": {
"flake": true
},
"GET /dictionary/constructor/parameter-calls-7.1.17-ToString": {
"flake": true
},
"GET /dictionary/constructor/empty-parameter": { "flake": true },
"GET /dictionary/constructor/found": { "flake": true },
"GET /dictionary/constructor/invalid-name": { "flake": true },
"GET /dictionary/get/called-as-constructor": { "flake": true },
"GET /dictionary/get/called-unbound": { "flake": true },
"GET /dictionary/get/key-parameter-calls-7.1.17-ToString": { "flake": true },
"GET /dictionary/get/key-parameter-not-supplied": { "flake": true },
"GET /dictionary/get/key-parameter-empty-string": { "flake": true },
"GET /dictionary/get/key-parameter-255-character-string": { "flake": true },
"GET /dictionary/get/key-parameter-256-character-string": { "flake": true },
"GET /dictionary/get/key-does-not-exist-returns-null": { "flake": true },
"GET /dictionary/get/key-exists": { "flake": true },
"GET /dictionary/constructor/empty-parameter": {
"flake": true
},
"GET /dictionary/constructor/found": {
"flake": true
},
"GET /dictionary/constructor/invalid-name": {
"flake": true
},
"GET /dictionary/get/called-as-constructor": {
"flake": true
},
"GET /dictionary/get/called-unbound": {
"flake": true
},
"GET /dictionary/get/key-parameter-calls-7.1.17-ToString": {
"flake": true
},
"GET /dictionary/get/key-parameter-not-supplied": {
"flake": true
},
"GET /dictionary/get/key-parameter-empty-string": {
"flake": true
},
"GET /dictionary/get/key-parameter-255-character-string": {
"flake": true
},
"GET /dictionary/get/key-parameter-256-character-string": {
"flake": true
},
"GET /dictionary/get/key-does-not-exist-returns-null": {
"flake": true
},
"GET /dictionary/get/key-exists": {
"flake": true
},
"GET /env": {
"environments": ["viceroy"]
},
Expand Down Expand Up @@ -1148,7 +1220,9 @@
"flake": true,
"downstream_response": {
"status": 200,
"headers": { "content-type": "text/html" },
"headers": {
"content-type": "text/html"
},
"body": ["<h1>blob</h1>"]
}
},
Expand Down Expand Up @@ -1206,7 +1280,9 @@
"body": ["START\nEND\n"]
}
},
"GET /setTimeout/fetch-timeout": { "flake": true },
"GET /setTimeout/fetch-timeout": {
"flake": true
},
"GET /clearInterval/exposed-as-global": {},
"GET /clearInterval/interface": {},
"GET /clearInterval/called-as-constructor-function": {},
Expand Down Expand Up @@ -1318,7 +1394,9 @@
"downstream_response": {
"status": 200,
"body": "meow",
"headers": { "content-length": "4" }
"headers": {
"content-length": "4"
}
}
},
"GET /override-content-length/response/init/object-literal/false": {
Expand All @@ -1333,7 +1411,9 @@
"downstream_response": {
"status": 200,
"body": "meow",
"headers": { "content-length": "4" }
"headers": {
"content-length": "4"
}
}
},
"GET /override-content-length/response/init/response-instance/false": {
Expand All @@ -1350,7 +1430,9 @@
"environments": ["compute"],
"downstream_response": {
"status": 200,
"headers": { "content-length": "11" }
"headers": {
"content-length": "11"
}
}
},
"GET /headers/getsetcookie": {
Expand All @@ -1374,7 +1456,9 @@
"headers": [["cuStom", "test"]]
}
},
"GET /headers/from-response/delete-invalid": { "flake": true },
"GET /headers/from-response/delete-invalid": {
"flake": true
},
"GET /headers/from-response/set-delete": {
"flake": true,
"downstream_response": {
Expand Down Expand Up @@ -3007,5 +3091,45 @@
"GET /html-rewriter/throw-in-handler": {},
"GET /html-rewriter/invalid-html": {},
"GET /html-rewriter/insertion-order": {},
"GET /html-rewriter/escape-html": {}
"GET /html-rewriter/escape-html": {},
"GET /early-hints/manual-response": {
"environments": ["compute"],
"downstream_response": {
"body": "ok",
"status": 200
},
"downstream_info": {
"status": 103,
"headers": {
"link": "</style.css>; rel=preload; as=style"
}
}
},
"GET /early-hints/send-early-hints": {
"environments": ["compute"],
"downstream_response": {
"body": "ok",
"status": 200
},
"downstream_info": {
"status": 103,
"headers": {
"link": "</style.css>; rel=preload; as=style"
}
}
},
"GET /early-hints/send-early-hints-multiple-headers": {
"environments": ["compute"],
"downstream_response": {
"body": "ok",
"status": 200
},
"downstream_info": {
"status": 103,
"headers": [
["link", "</style.css>; rel=preload; as=style"],
["link", "</style2.css>; rel=preload; as=style"]
]
}
}
}
Loading
Loading