Skip to content

Commit 3ccb4c0

Browse files
authored
chore(main): release 2.2.0 (#553)
1 parent a1f4517 commit 3ccb4c0

File tree

622 files changed

+23383
-7
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

622 files changed

+23383
-7
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Changelog
22

33

4+
## 2.2.0 (2023-06-08)
5+
6+
7+
### Added
8+
9+
* Implement SimpleCache.getOrSet method ([a1f4517](https://github.com/fastly/js-compute-runtime/commit/a1f4517e5e377354254ee2a635f97a562c87e13c))
10+
411
## 2.1.0 (2023-06-02)
512

613

documentation/docs/fastly:cache/SimpleCache/SimpleCache.mdx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ addEventListener('fetch', event => event.respondWith(app(event)));
2424

2525
async function app(event) {
2626
const path = new URL(event.request).pathname;
27-
let page = SimpleCache.get(path);
28-
if (!page) {
29-
page = await render(path);
30-
// Store the page in the cache for 1 minute.
31-
SimpleCache.set(path, page, 60);
32-
}
27+
let page = SimpleCache.getOrSet(path, async () => {
28+
return {
29+
value: await render(path),
30+
// Store the page in the cache for 1 minute.
31+
ttl: 60
32+
}
33+
});
3334
return new Response(page, {
3435
headers: {
3536
'content-type': 'text/plain;charset=UTF-8'
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
hide_title: false
3+
hide_table_of_contents: false
4+
pagination_next: null
5+
pagination_prev: null
6+
---
7+
# SimpleCache.getOrSet
8+
9+
The **`getOrSet()`** method attempts to get an entry from the cache for the supplied `key` if no entry is found (or has expired), the supplied `set` function is executed and it's result is inserted into the cache under the supplied `key` and for the supplied `ttl` (Time-To-Live) duration, provided in seconds.
10+
11+
## Syntax
12+
13+
```js
14+
getOrSet(key, set)
15+
getOrSet(key, set, length)
16+
```
17+
18+
### Parameters
19+
20+
- `key` _: string_
21+
- The key to lookup and/or store the supplied entry under within the cache.
22+
- `set` _: Function_
23+
- : A function to execute when the cache does not have a usable entry for the supplied `key`.
24+
The function should return a Promise which resolves with the following interface:
25+
- `value` _: ArrayBuffer | TypedArray | DataView| ReadableStream | URLSearchParams | String | string literal_
26+
- The value to store within the cache.
27+
- `ttl` _: number_
28+
- The number of seconds to store the supplied entry within the cache for.
29+
- `length` _: number_ __optional__
30+
- The length of value being stored within the cache. This is only used when the `value` is a ReadableStream.
31+
32+
### Return value
33+
34+
Returns a `SimpleCacheEntry`.
35+
36+
### Exceptions
37+
38+
- If the provided `key`:
39+
- Cannot be coerced to a string
40+
- Is an empty string
41+
- Is longer than 8135 characters
42+
- If the provided `ttl`:
43+
- Cannot be coerced to a number
44+
- Is a negative number
45+
- Is `NaN`
46+
- Is Inifinity
47+
48+
## Examples
49+
50+
In this example we attempt to retrieve an entry from the Fastly Cache, if the entry does not exist, we create the content and insert it into the Fastly Cache before finally returning.
51+
52+
```js
53+
/// <reference types="@fastly/js-compute" />
54+
55+
import { SimpleCache } from 'fastly:cache';
56+
57+
addEventListener('fetch', event => event.respondWith(app(event)));
58+
59+
async function app(event) {
60+
const path = new URL(event.request).pathname;
61+
let page = SimpleCache.getOrSet(path, async () => {
62+
return {
63+
value: await render(path),
64+
// Store the page in the cache for 1 minute.
65+
ttl: 60
66+
}
67+
});
68+
return new Response(page, {
69+
headers: {
70+
'content-type': 'text/plain;charset=UTF-8'
71+
}
72+
});
73+
}
74+
75+
async function render(path) {
76+
// expensive/slow function which constructs and returns the contents for a given path
77+
await new Promise(resolve => setTimeout(resolve, 10_000));
78+
return path;
79+
}
80+
81+
```
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
---
2+
hide_title: false
3+
hide_table_of_contents: false
4+
pagination_next: null
5+
pagination_prev: null
6+
---
7+
import {Fiddle} from '@site/src/components/fiddle';
8+
9+
# `Backend()`
10+
11+
The **`Backend` constructor** lets you dynamically create new [Fastly Backends](https://developer.fastly.com/reference/api/services/backend/) for your Compute@Edge service.
12+
13+
Dynamically creating new [Fastly Backends](https://developer.fastly.com/reference/api/services/backend/) is disabled by default for Fastly Services. Please contact [Fastly Support](https://support.fastly.com/hc/requests/new?ticket_form_id=360000269711) to request the feature be enabled on the Fastly Services which require Dynamic Backends.
14+
15+
By default, Dynamic Backends are disabled within a JavaScript application as it can be a potential avenue for third-party JavaScript code to send requests, potentially including sensitive/secret data, off to destinations that the JavaScript project was not intending, which could be a security issue.
16+
17+
To enable Dynamic Backends the application will need to explicitly allow Dynamic Backends via:
18+
19+
```js
20+
import { allowDynamicBackends } from "fastly:experimental";
21+
allowDynamicBackends(true);
22+
```
23+
24+
**Note**: Can only be used when processing requests, not during build-time initialization.
25+
26+
## Syntax
27+
28+
```js
29+
new Backend(backendConfiguration)
30+
```
31+
32+
> **Note:** `Backend()` can only be constructed with `new`. Attempting to call it without `new` throws a [`TypeError`](../../globals/TypeError/TypeError.mdx).
33+
34+
### Parameters
35+
36+
- `backendConfiguration`
37+
38+
- : An Object which contains all the configuration options to apply to the newly created Backend.
39+
40+
- `name` _: string_
41+
- The name of the backend.
42+
- The name has to be between 1 and 254 characters inclusive.
43+
- The name can be whatever you would like, as long as it does not match the name of any of the static service backends nor match any other dynamic backends built during a single execution of the application.
44+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is not valid. I.E. The value is null, undefined, an empty string or a string with more than 254 characters.
45+
- `target` _: string_
46+
- A hostname, IPv4, or IPv6 address for the backend as well as an optional port.
47+
- The target has to be at-least 1 character.
48+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is not valid. I.E. Is null, undefined, an empty string, not a valid IP address or host, or is the string `::`
49+
- `hostOverride` _: string_ _**optional**_
50+
- If set, will force the HTTP Host header on connections to this backend to be the supplied value.
51+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
52+
- `connectTimeout` _: number_ _**optional**_
53+
- Maximum duration in milliseconds to wait for a connection to this backend to be established.
54+
- If exceeded, the connection is aborted and a 503 response will be presented instead.
55+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is negative or greater than or equal to 2^32
56+
- `firstByteTimeout` _: number_ _**optional**_
57+
- Maximum duration in milliseconds to wait for the server response to begin after a TCP connection is established and the request has been sent.
58+
- If exceeded, the connection is aborted and a 503 response will be presented instead.
59+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is negative or greater than or equal to 2^32
60+
- `betweenBytesTimeout` _: number_ _**optional**_
61+
- Maximum duration in milliseconds that Fastly will wait while receiving no data on a download from a backend.
62+
- If exceeded, the response received so far will be considered complete and the fetch will end.
63+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is negative or greater than or equal to 2^32
64+
- `useSSL` _: boolean_ _**optional**_
65+
- Whether or not to require TLS for connections to this backend.
66+
- `tlsMinVersion` _: 1 | 1.1 | 1.2 | 1.3_ _**optional**_
67+
- Minimum allowed TLS version on SSL connections to this backend.
68+
- If the backend server is not able to negotiate a connection meeting this constraint, a 503 response will be presented instead.
69+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is not 1, 1.1, 1.2, or 1.3
70+
- `tlsMaxVersion` _: 1 | 1.1 | 1.2 | 1.3_ _**optional**_
71+
- Maximum allowed TLS version on SSL connections to this backend.
72+
- If the backend server is not able to negotiate a connection meeting this constraint, a 503 response will be presented instead.
73+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is not 1, 1.1, 1.2, or 1.3
74+
- `certificateHostname` _: string_ _**optional**_
75+
- Define the hostname that the server certificate should declare.
76+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
77+
- `caCertificate` _: string_ _**optional**_
78+
- The CA certificate to use when checking the validity of the backend.
79+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
80+
- `ciphers` _: string_ _**optional**_
81+
- List of OpenSSL ciphers to support for connections to this origin.
82+
- If the backend server is not able to negotiate a connection meeting this constraint, a 503 response will be presented instead.
83+
- [List of ciphers supported by Fastly](https://developer.fastly.com/learning/concepts/routing-traffic-to-fastly/#use-a-tls-configuration).
84+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
85+
- `sniHostname` _: string_ _**optional**_
86+
- The SNI hostname to use on connections to this backend.
87+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
88+
89+
### Return value
90+
91+
A new `Backend` object.
92+
93+
## Examples
94+
95+
In this example an implicit Dynamic Backend is created when making the fetch request to <https://www.fastly.com/> and the response is then returned to the client.
96+
<Fiddle config={{
97+
"type": "javascript",
98+
"title": "Implicit Dynamic Backend Example",
99+
"origins": [
100+
"https://http-me.glitch.me"
101+
],
102+
"src": {
103+
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
104+
"main": `
105+
/// <reference types="@fastly/js-compute" />
106+
import { allowDynamicBackends } from "fastly:experimental";
107+
allowDynamicBackends(true);
108+
async function app() {
109+
// For any request, return the fastly homepage -- without defining a backend!
110+
return fetch('https://www.fastly.com/');
111+
}
112+
addEventListener("fetch", event => event.respondWith(app(event)));
113+
`
114+
},
115+
"requests": [
116+
{
117+
"enableCluster": true,
118+
"enableShield": false,
119+
"enableWAF": false,
120+
"method": "GET",
121+
"path": "/status=200",
122+
"useFreshCache": false,
123+
"followRedirects": false,
124+
"tests": "",
125+
"delay": 0
126+
}
127+
],
128+
"srcVersion": 1
129+
}}>
130+
131+
```js
132+
/// <reference types="@fastly/js-compute" />
133+
import { allowDynamicBackends } from "fastly:experimental";
134+
allowDynamicBackends(true);
135+
async function app() {
136+
// For any request, return the fastly homepage -- without defining a backend!
137+
return fetch('https://www.fastly.com/');
138+
}
139+
addEventListener("fetch", event => event.respondWith(app(event)));
140+
```
141+
142+
</Fiddle>
143+
144+
In this example an explicit Dynamic Backend is created and supplied to the fetch request, the response is then returned to the client.
145+
146+
147+
<Fiddle config={{
148+
"type": "javascript",
149+
"title": "Explicit Dynamic Backend Example",
150+
"origins": [
151+
"https://http-me.glitch.me"
152+
],
153+
"src": {
154+
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
155+
"main": `
156+
/// <reference types="@fastly/js-compute" />
157+
import { allowDynamicBackends } from "fastly:experimental";
158+
import { Backend } from "fastly:backend";
159+
allowDynamicBackends(true);
160+
async function app() {
161+
// For any request, return the fastly homepage -- without defining a backend!
162+
const backend = new Backend({
163+
name: 'fastly',
164+
target: 'fastly.com',
165+
hostOverride: "www.fastly.com",
166+
connectTimeout: 1000,
167+
firstByteTimeout: 15000,
168+
betweenBytesTimeout: 10000,
169+
useSSL: true,
170+
sslMinVersion: 1.3,
171+
sslMaxVersion: 1.3,
172+
});
173+
return fetch('https://www.fastly.com/', {
174+
backend // Here we are configuring this request to use the backend from above.
175+
});
176+
}
177+
addEventListener("fetch", event => event.respondWith(app(event)));
178+
`
179+
},
180+
"requests": [
181+
{
182+
"enableCluster": true,
183+
"enableShield": false,
184+
"enableWAF": false,
185+
"method": "GET",
186+
"path": "/status=200",
187+
"useFreshCache": false,
188+
"followRedirects": false,
189+
"tests": "",
190+
"delay": 0
191+
}
192+
],
193+
"srcVersion": 1
194+
}}>
195+
196+
```js
197+
/// <reference types="@fastly/js-compute" />
198+
import { allowDynamicBackends } from "fastly:experimental";
199+
import { Backend } from "fastly:backend";
200+
allowDynamicBackends(true);
201+
async function app() {
202+
// For any request, return the fastly homepage -- without defining a backend!
203+
const backend = new Backend({
204+
name: 'fastly',
205+
target: 'fastly.com',
206+
hostOverride: "www.fastly.com",
207+
connectTimeout: 1000,
208+
firstByteTimeout: 15000,
209+
betweenBytesTimeout: 10000,
210+
useSSL: true,
211+
sslMinVersion: 1.3,
212+
sslMaxVersion: 1.3,
213+
});
214+
return fetch('https://www.fastly.com/', {
215+
backend // Here we are configuring this request to use the backend from above.
216+
});
217+
}
218+
addEventListener("fetch", event => event.respondWith(app(event)));
219+
```
220+
221+
</Fiddle>

0 commit comments

Comments
 (0)