Skip to content

Commit bb858fe

Browse files
author
Guy Bedford
authored
feat: default enable allowDynamicBackends with better unsupported errors (#995)
1 parent c5986c2 commit bb858fe

File tree

20 files changed

+368
-167
lines changed

20 files changed

+368
-167
lines changed

documentation/docs/backend/Backend/Backend.mdx

Lines changed: 2 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,9 @@ import {Fiddle} from '@site/src/components/fiddle';
1010

1111
The **`Backend` constructor** lets you dynamically create new [Fastly Backends](https://developer.fastly.com/reference/api/services/backend/) for your Fastly Compute service.
1212

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.
13+
>**Note**: Dynamic backends are by default disabled at the Fastly service level. Contact [Fastly Support](https://support.fastly.com/hc/en-us/requests/new?ticket_form_id=360000269711) to request dynamic backends on Fastly Services.
1414
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**: Backend constructors can only be used when processing requests, not during build-time initialization.
15+
To disable the usage of dynamic backends, see [enforceExplicitBackends](../enforceExplicitBackends.mdx).
2516

2617
## Syntax
2718

@@ -122,58 +113,8 @@ A new `Backend` object.
122113

123114
## Examples
124115

125-
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.
126-
<Fiddle config={{
127-
"type": "javascript",
128-
"title": "Implicit Dynamic Backend Example",
129-
"origins": [
130-
"https://http-me.glitch.me"
131-
],
132-
"src": {
133-
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
134-
"main": `
135-
/// <reference types="@fastly/js-compute" />
136-
import { allowDynamicBackends } from "fastly:experimental";
137-
allowDynamicBackends(true);
138-
async function app() {
139-
// For any request, return the fastly homepage -- without defining a backend!
140-
return fetch('https://www.fastly.com/');
141-
}
142-
addEventListener("fetch", event => event.respondWith(app(event)));
143-
`
144-
},
145-
"requests": [
146-
{
147-
"enableCluster": true,
148-
"enableShield": false,
149-
"enableWAF": false,
150-
"method": "GET",
151-
"path": "/status=200",
152-
"useFreshCache": false,
153-
"followRedirects": false,
154-
"tests": "",
155-
"delay": 0
156-
}
157-
],
158-
"srcVersion": 1
159-
}}>
160-
161-
```js
162-
/// <reference types="@fastly/js-compute" />
163-
import { allowDynamicBackends } from "fastly:experimental";
164-
allowDynamicBackends(true);
165-
async function app() {
166-
// For any request, return the fastly homepage -- without defining a backend!
167-
return fetch('https://www.fastly.com/');
168-
}
169-
addEventListener("fetch", event => event.respondWith(app(event)));
170-
```
171-
172-
</Fiddle>
173-
174116
In this example an explicit Dynamic Backend is created and supplied to the fetch request, the response is then returned to the client.
175117

176-
177118
<Fiddle config={{
178119
"type": "javascript",
179120
"title": "Explicit Dynamic Backend Example",
@@ -184,9 +125,7 @@ In this example an explicit Dynamic Backend is created and supplied to the fetch
184125
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
185126
"main": `
186127
/// <reference types="@fastly/js-compute" />
187-
import { allowDynamicBackends } from "fastly:experimental";
188128
import { Backend } from "fastly:backend";
189-
allowDynamicBackends(true);
190129
async function app() {
191130
// For any request, return the fastly homepage -- without defining a backend!
192131
const backend = new Backend({
@@ -225,9 +164,7 @@ addEventListener("fetch", event => event.respondWith(app(event)));
225164

226165
```js
227166
/// <reference types="@fastly/js-compute" />
228-
import { allowDynamicBackends } from "fastly:experimental";
229167
import { Backend } from "fastly:backend";
230-
allowDynamicBackends(true);
231168
async function app() {
232169
// For any request, return the fastly homepage -- without defining a backend!
233170
const backend = new Backend({
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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+
# name
10+
11+
The read-only **`name`** property of the backend returns the backend name string.
12+
13+
## Value
14+
15+
A `string`.
16+
17+
## Description
18+
19+
Provides the name of the backend.
20+
21+
## Examples
22+
23+
### Using name
24+
25+
The following example logs the string value of a [Backend](../Backend.mdx) object:
26+
27+
<Fiddle config={{
28+
"type": "javascript",
29+
"title": "Backend.prototype.name Example",
30+
"origins": [
31+
"https://http-me.glitch.me"
32+
],
33+
"src": {
34+
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
35+
"main": `
36+
/// <reference types=\"@fastly/js-compute\" />
37+
import { Backend } from "fastly:backend";
38+
async function app() {
39+
const backend = new Backend({
40+
name: "fastly",
41+
target: "fastly.com",
42+
});
43+
console.log(backend.name); // "fastly"
44+
}
45+
addEventListener("fetch", event => event.respondWith(app(event)));
46+
`
47+
},
48+
"requests": [
49+
{
50+
"enableCluster": true,
51+
"enableShield": false,
52+
"enableWAF": false,
53+
"method": "GET",
54+
"path": "/status=200",
55+
"useFreshCache": false,
56+
"followRedirects": false,
57+
"tests": "",
58+
"delay": 0
59+
}
60+
],
61+
"srcVersion": 1
62+
}}>
63+
64+
```js
65+
import { Backend } from "fastly:backend";
66+
async function app() {
67+
const backend = new Backend({
68+
name: "fastly",
69+
target: "fastly.com",
70+
});
71+
console.log(backend.name); // "fastly"
72+
}
73+
addEventListener("fetch", event => event.respondWith(app(event)));
74+
```
75+
76+
</Fiddle>

documentation/docs/backend/Backend/prototype/toName.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ pagination_prev: null
77

88
# Backend.prototype.toName()
99

10+
:::info
11+
12+
This method is deprecated, use [`Backend.prototype.name`](./name.mdx) instead.
13+
14+
:::
15+
1016
The **`toName()`** method returns the name associated with the `Backend` instance.
1117

1218
## Syntax

documentation/docs/backend/Backend/prototype/toString.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ import {Fiddle} from '@site/src/components/fiddle';
88

99
# toString
1010

11+
:::info
12+
13+
This method is deprecated, use [`Backend.prototype.name`](./name.mdx) instead.
14+
15+
:::
16+
1117
The **`toString()`** method returns a string representing the specified Backend value.
1218

1319
## Syntax
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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+
# allowDynamicBackends
10+
11+
:::info
12+
13+
This method is deprecated, and dynamic backends are now always supported when enabled at the service level. See [`enforceExplicitBackends`](./enforceExplicitBackends.mdx) instead.
14+
15+
:::
16+
17+
The **`allowDynamicBackends()`** function is used to control whether or not Dynamic Backends should be allowed within this Fastly Compute Service.
18+
19+
By default, Dynamic Backends are enabled, but can be a potential security concern since third-party JavaScript code may send arbitrary requests, potentially including sensitive/secret data, off to destinations that the JavaScript project was not intending.
20+
21+
Using `allowDynamicBackends(false)` this security property can be restored to only use explicit backend definitions.
22+
23+
>**Note**: By default, while dynamic backends are allowed in the SDK, they are by default disabled at the Fastly service level.
24+
25+
## Syntax
26+
27+
```js
28+
allowDynamicBackends(enabledOrConfig)
29+
```
30+
31+
### Parameters
32+
33+
- `enabled` _: boolean_
34+
- Whether or not to allow Dynamic Backends
35+
36+
### Return value
37+
38+
`undefined`.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
hide_title: false
3+
hide_table_of_contents: false
4+
pagination_next: null
5+
pagination_prev: null
6+
---
7+
8+
# enforceExplicitBackends
9+
10+
Call this function to enforce the security property of explicitly-defined backends, even when dynamic backends are enabled at
11+
the Fastly service level.
12+
13+
By default, if dynamic backends are supported for the Fastly service, they will be automatically used when creating a new
14+
`fetch()` request. This default behaviour for dynamic backends can be a potential security concern since third-party JavaScript
15+
code may send arbitrary requests, including sensitive/secret data, off to destinations that the JavaScript project was not
16+
intending.
17+
18+
When calling this function, an optional default backend name can be provided.
19+
20+
>**Note**: This is a separate option to the service-level dynamic backend support for Fastly services, which is by deault disabled for Fastly services.
21+
22+
The **`enforceExplicitBackends()`** function is used to control whether or not Dynamic Backends should be allowed within this Fastly Compute Service.
23+
24+
By default, Dynamic Backends are enabled, but can be a potential security concern since third-party JavaScript code may send arbitrary requests, potentially including sensitive/secret data, off to destinations that the JavaScript project was not intending.
25+
26+
Using `allowDynamicBackends(false)` this security property can be restored to only use explicit backend definitions.
27+
28+
>**Note**: Dynamic Backends are 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 or disabled on Fastly Services.
29+
30+
## Syntax
31+
32+
```js
33+
enforceExplicitBackends(defaultBackend?)
34+
```
35+
36+
### Parameters
37+
38+
- `defaultBackend` _: string_ _**optional**_
39+
- An optional default backend string name to use in `fetch()` requests.
40+
41+
### Return value
42+
43+
`undefined`.

documentation/docs/globals/fetch.mdx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,26 @@ not_ reject on HTTP errors (`404`, etc.). Instead, a
2323
> **Note:** The `fetch()` method's parameters are identical to
2424
> those of the `Request()` constructor.
2525
26+
## Explicit Backends
27+
28+
Internally, Fastly uses named backends to handle fetch requests, which need to be explicitly defined to enable custom HTTP origins to be fetched by the service.
29+
30+
This `backend` option is then a special Fastly-specific fetch option that is provided to the `fetch()` call:
31+
32+
```js
33+
fetch('https://origin.com/path', { backend: 'origin' });
34+
```
35+
36+
Backends are configured using the Fastly service backend configuration, see the [Backend documentation](https://developer.fastly.com/reference/api/services/backend/) for more information.
37+
38+
## Dynamic Backends
39+
40+
Dynamic backends are a compute feature that allow services to define backends for themselves. This is a service-level Fastly feature that must be enabled through [Fastly Support](https://support.fastly.com/hc/en-us/requests/new?ticket_form_id=360000269711).
41+
42+
When dynamic backends are enabled at the service level, the explicit `backend` option is no longer required for `fetch()` requests, and will instead be automatically created.
43+
44+
In addition, custom backend confiuration options can then also be provided through the [`Backend()`](../fastly:backend/Backend/Backend.mdx) constructor.
45+
2646
## Syntax
2747

2848
```js

integration-tests/js-compute/fixtures/app/src/dynamic-backend.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
/// <reference path="../../../../../types/index.d.ts" />
2-
import { Backend, setDefaultDynamicBackendConfig } from 'fastly:backend';
3-
import { CacheOverride } from 'fastly:cache-override';
2+
import {
3+
Backend,
4+
setDefaultDynamicBackendConfig,
5+
enforceExplicitBackends,
6+
} from 'fastly:backend';
47
import { allowDynamicBackends } from 'fastly:experimental';
8+
import { CacheOverride } from 'fastly:cache-override';
59
import {
610
assert,
711
assertDoesNotThrow,
@@ -55,6 +59,10 @@ routes.set('/backend/timeout', async () => {
5559
allowDynamicBackends(true);
5660
await assertResolves(() => fetch('https://http-me.glitch.me/headers'));
5761
await assertResolves(() => fetch('https://www.fastly.com'));
62+
enforceExplicitBackends();
63+
await assertRejects(() => fetch('https://www.fastly.com'));
64+
enforceExplicitBackends('TheOrigin');
65+
await assertResolves(() => fetch('https://www.fastly.com'));
5866
});
5967
routes.set(
6068
'/implicit-dynamic-backend/dynamic-backends-enabled-called-twice',
@@ -225,6 +233,7 @@ routes.set('/backend/timeout', async () => {
225233
actual = Reflect.ownKeys(Backend.prototype);
226234
expected = [
227235
'constructor',
236+
'name',
228237
'isDynamic',
229238
'target',
230239
'hostOverride',
@@ -2432,6 +2441,9 @@ routes.set('/backend/timeout', async () => {
24322441
{
24332442
const backend = createValidFastlyBackend() ?? validFastlyBackend;
24342443
strictEqual(backend.isDynamic, true, 'isDymamic');
2444+
strictEqual(backend.name, 'fastly');
2445+
strictEqual(backend.toString(), 'fastly');
2446+
strictEqual(backend.toName(), 'fastly');
24352447
strictEqual(backend.target, 'www.fastly.com', 'target');
24362448
strictEqual(backend.hostOverride, 'www.fastly.com', 'override');
24372449
strictEqual(backend.port, 443, 'port');
@@ -2466,6 +2478,9 @@ routes.set('/backend/timeout', async () => {
24662478
{
24672479
const backend = createValidHttpMeBackend() ?? validHttpMeBackend;
24682480
strictEqual(backend.isDynamic, true, 'isDynamic');
2481+
strictEqual(backend.name, 'http-me');
2482+
strictEqual(backend.toString(), 'http-me');
2483+
strictEqual(backend.toName(), 'http-me');
24692484
strictEqual(backend.target, 'http-me.glitch.me', 'target');
24702485
strictEqual(backend.hostOverride, 'http-me.glitch.me', 'hostOverride');
24712486
strictEqual(backend.port, 443, 'port');

0 commit comments

Comments
 (0)