Skip to content

Commit 1847924

Browse files
author
Guy Bedford
authored
feat: setDefaultDynamicBackendConfig with all backend configuration options (#993)
1 parent 8810c4c commit 1847924

File tree

17 files changed

+1104
-1161
lines changed

17 files changed

+1104
-1161
lines changed

documentation/docs/backend/Backend/Backend.mdx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,25 @@ new Backend(backendConfiguration)
9797
- The PEM certificate string.
9898
- `key` _: SecretStoreEntry_
9999
- The `SecretStoreEntry` to use for the key, created via [`SecretStore.prototype.get`](../../fastly:secret-store/SecretStore/prototype/get.mdx) or alteratively via [`SecretStore.fromBytes`](../../fastly:secret-store/SecretStore/fromBytes.mdx).
100+
- `httpKeepalive` _: number_ _**optional**_
101+
- Enable HTTP keepalive, setting the timout in milliseconds.
102+
- `tcpKeepalive` _: boolean | object_ _**optional**_
103+
- Enable TCP keepalive. When an object, optionally setting the keepalive configuration options.
104+
- `timeSecs` _: number_ _**optional**_
105+
- Configure how long to wait after the last sent data over the TCP connection before starting to send TCP keepalive probes.
106+
- `intervalSecs` _: number_ _**optional**_
107+
- Configure how long to wait between each TCP keepalive probe sent to the backend to determine if it is still active.
108+
- `probes` _: number_ _**optional**_
109+
- Number of probes to send to the backend before it is considered dead.
100110
- `grpc` _: boolean_ _**optional**_
101111
- **_Experimental feature_**
102112
- When enabled, sets that this backend is to be used for gRPC traffic.
103113
- _Warning: When using this experimental feature, no guarantees are provided for behaviours for backends that do not provide gRPC traffic._
104114

115+
All optional generic options can have their defaults set via [`setDefaultDynamicBackendConfig()`](../setDefaultDynamicBackendConfig.mdx).
116+
117+
This includes all configuration options above except for `name`, `target`, `hostOverride`, `sniHostname` and `grpc`.
118+
105119
### Return value
106120

107121
A new `Backend` object.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
hide_title: false
3+
hide_table_of_contents: false
4+
pagination_next: null
5+
pagination_prev: null
6+
---
7+
8+
# setDefaultDynamicBackendConfig()
9+
10+
The **`setDefaultDynamicBackendConfig()`** allows setting backend configuration defaults that should apply to any newly created dynamic backends via the `new Backend()` constructor.
11+
12+
### Parameters
13+
14+
- `defaultDynamicBackendConfig`
15+
16+
- : An Object which contains the generic configuration options to apply to newly created Backends.
17+
- `connectTimeout` _: number_ _**optional**_
18+
- Maximum duration in milliseconds to wait for a connection to this backend to be established.
19+
- If exceeded, the connection is aborted and a 503 response will be presented instead.
20+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is negative or greater than or equal to 2^32
21+
- `firstByteTimeout` _: number_ _**optional**_
22+
- Maximum duration in milliseconds to wait for the server response to begin after a TCP connection is established and the request has been sent.
23+
- If exceeded, the connection is aborted and a 503 response will be presented instead.
24+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is negative or greater than or equal to 2^32
25+
- `betweenBytesTimeout` _: number_ _**optional**_
26+
- Maximum duration in milliseconds that Fastly will wait while receiving no data on a download from a backend.
27+
- If exceeded, the response received so far will be considered complete and the fetch will end.
28+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is negative or greater than or equal to 2^32
29+
- `useSSL` _: boolean_ _**optional**_
30+
- Whether or not to require TLS for connections to this backend.
31+
- `dontPool` _: boolean_ _**optional**_
32+
- Determine whether or not connections to the same backend should be pooled across different sessions.
33+
- Fastly considers two backends “the same” if they're registered with the same name and the exact same settings.
34+
- In those cases, when pooling is enabled, if Session 1 opens a connection to this backend it will be left open, and can be re-used by Session 2.
35+
- This can help improve backend latency, by removing the need for the initial network / TLS handshake(s).
36+
- By default, pooling is enabled for dynamic backends.
37+
- `tlsMinVersion` _: 1 | 1.1 | 1.2 | 1.3_ _**optional**_
38+
- Minimum allowed TLS version on SSL connections to this backend.
39+
- If the backend server is not able to negotiate a connection meeting this constraint, a 503 response will be presented instead.
40+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is not 1, 1.1, 1.2, or 1.3
41+
- `tlsMaxVersion` _: 1 | 1.1 | 1.2 | 1.3_ _**optional**_
42+
- Maximum allowed TLS version on SSL connections to this backend.
43+
- If the backend server is not able to negotiate a connection meeting this constraint, a 503 response will be presented instead.
44+
- Throws a [`RangeError`](../../globals/RangeError/RangeError.mdx) if the value is not 1, 1.1, 1.2, or 1.3
45+
- `certificateHostname` _: string_ _**optional**_
46+
- Define the hostname that the server certificate should declare.
47+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
48+
- `caCertificate` _: string_ _**optional**_
49+
- The CA certificate to use when checking the validity of the backend.
50+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
51+
- `ciphers` _: string_ _**optional**_
52+
- List of OpenSSL ciphers to support for connections to this origin.
53+
- If the backend server is not able to negotiate a connection meeting this constraint, a 503 response will be presented instead.
54+
- [List of ciphers supported by Fastly](https://developer.fastly.com/learning/concepts/routing-traffic-to-fastly/#use-a-tls-configuration).
55+
- Throws a [`TypeError`](../../globals/TypeError/TypeError.mdx) if the value is an empty string.
56+
- `clientCertificate` _: object_ _**optional**_
57+
- The client certificate to provide for the TLS handshake
58+
- `certificate` _: string_
59+
- The PEM certificate string.
60+
- `key` _: SecretStoreEntry_
61+
- The `SecretStoreEntry` to use for the key, created via [`SecretStore.prototype.get`](../../fastly:secret-store/SecretStore/prototype/get.mdx) or alteratively via [`SecretStore.fromBytes`](../../fastly:secret-store/SecretStore/fromBytes.mdx).
62+
- `httpKeepalive` _: number_ _**optional**_
63+
- Enable HTTP keepalive, setting the timout in milliseconds.
64+
- `tcpKeepalive` _: boolean | object_ _**optional**_
65+
- Enable TCP keepalive. When an object, optionally setting the keepalive configuration options.
66+
- `timeSecs` _: number_ _**optional**_
67+
- Configure how long to wait after the last sent data over the TCP connection before starting to send TCP keepalive probes.
68+
- `intervalSecs` _: number_ _**optional**_
69+
- Configure how long to wait between each TCP keepalive probe sent to the backend to determine if it is still active.
70+
- `probes` _: number_ _**optional**_
71+
- Number of probes to send to the backend before it is considered dead.
72+
73+
## Syntax
74+
75+
```js
76+
setDefaultDynamicBackendConfig(defaultConfig)
77+
```
78+
79+
### Return value
80+
81+
None.
82+
83+
## Examples
84+
85+
In this example an explicit Dynamic Backend is created and supplied to the fetch request, with timeouts and TLS options provided from the default backend configuration options.
86+
87+
88+
<Fiddle config={{
89+
"type": "javascript",
90+
"title": "Explicit Dynamic Backend Example",
91+
"origins": [
92+
"https://http-me.glitch.me"
93+
],
94+
"src": {
95+
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
96+
"main": `
97+
/// <reference types="@fastly/js-compute" />
98+
import { allowDynamicBackends } from "fastly:experimental";
99+
import { Backend, setDefaultDynamicBackendConfig } from "fastly:backend";
100+
allowDynamicBackends(true);
101+
setDefaultDynamicBackendConfig({
102+
connectTimeout: 1000,
103+
firstByteTimeout: 15_000,
104+
betweenBytesTimeout: 10_000,
105+
useSSL: true,
106+
sslMinVersion: 1.3,
107+
sslMaxVersion: 1.3
108+
});
109+
async function app() {
110+
// For any request, return the fastly homepage -- without defining a backend!
111+
// Timeouts and TLS configuration still get set from the default backend configuration above.
112+
const backend = new Backend({
113+
name: 'fastly',
114+
target: 'fastly.com',
115+
hostOverride: "www.fastly.com"
116+
});
117+
return fetch('https://www.fastly.com/', {
118+
backend // Here we are configuring this request to use the backend from above.
119+
});
120+
}
121+
addEventListener("fetch", event => event.respondWith(app(event)));
122+
`
123+
},
124+
"requests": [
125+
{
126+
"enableCluster": true,
127+
"enableShield": false,
128+
"enableWAF": false,
129+
"method": "GET",
130+
"path": "/status=200",
131+
"useFreshCache": false,
132+
"followRedirects": false,
133+
"tests": "",
134+
"delay": 0
135+
}
136+
],
137+
"srcVersion": 1
138+
}}>
139+
140+
```js
141+
/// <reference types="@fastly/js-compute" />
142+
import { allowDynamicBackends } from "fastly:experimental";
143+
import { Backend } from "fastly:backend";
144+
allowDynamicBackends(true);
145+
setDefaultDynamicBackendConfig({
146+
connectTimeout: 1000,
147+
firstByteTimeout: 15_000,
148+
betweenBytesTimeout: 10_000,
149+
useSSL: true,
150+
sslMinVersion: 1.3,
151+
sslMaxVersion: 1.3
152+
});
153+
async function app() {
154+
// For any request, return the fastly homepage -- without defining a backend!
155+
const backend = new Backend({
156+
name: 'fastly',
157+
target: 'fastly.com',
158+
hostOverride: "www.fastly.com"
159+
});
160+
return fetch('https://www.fastly.com/', {
161+
backend // Here we are configuring this request to use the backend from above.
162+
});
163+
}
164+
addEventListener("fetch", event => event.respondWith(app(event)));
165+
```
166+
167+
</Fiddle>

integration-tests/js-compute/compare-downstream-response.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import compareHeaders from './compare-headers.js';
1616
function maybeUint8Array(body) {
1717
if (Array.isArray(body) && typeof body[0] === 'number')
1818
return new Uint8Array(body);
19+
if (typeof body === 'string') return new TextEncoder().encode(body);
1920
return body;
2021
}
2122

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

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/// <reference path="../../../../../types/index.d.ts" />
2-
import { Backend } from 'fastly:backend';
2+
import { Backend, setDefaultDynamicBackendConfig } from 'fastly:backend';
33
import { CacheOverride } from 'fastly:cache-override';
44
import { allowDynamicBackends } from 'fastly:experimental';
55
import {
@@ -1309,6 +1309,19 @@ routes.set('/backend/timeout', async () => {
13091309
});
13101310
},
13111311
);
1312+
1313+
routes.set(
1314+
'/backend/constructor/parameter-firstByteTimeout-property-invalid-number',
1315+
async () => {
1316+
assertThrows(() => {
1317+
new Backend({
1318+
name: 'firstByteTimeout-property-valid-number',
1319+
target: 'a',
1320+
firstByteTimeout: 'zzz',
1321+
});
1322+
}, RangeError);
1323+
},
1324+
);
13121325
}
13131326

13141327
// betweenBytesTimeout property
@@ -2075,6 +2088,100 @@ routes.set('/backend/timeout', async () => {
20752088
);
20762089
});
20772090
}
2091+
2092+
// httpKeepalive
2093+
{
2094+
routes.set('/backend/constructor/http-keepalive-invalid', async () => {
2095+
await assertRejects(async () => {
2096+
await fetch('https://http-me.glitch.me/anything', {
2097+
backend: new Backend({
2098+
name: 'grpc-grpc-invalid',
2099+
target: 'http-me.glitch.me',
2100+
httpKeepalive: NaN,
2101+
}),
2102+
cacheOverride: new CacheOverride('pass'),
2103+
});
2104+
}, RangeError);
2105+
});
2106+
routes.set('/backend/constructor/http-keepalive', async () => {
2107+
await fetch('https://http-me.glitch.me/anything', {
2108+
backend: new Backend({
2109+
name: 'grpc-grpc-invalid',
2110+
target: 'http-me.glitch.me',
2111+
httpKeepalive: 500,
2112+
}),
2113+
cacheOverride: new CacheOverride('pass'),
2114+
});
2115+
});
2116+
}
2117+
2118+
// tcpKeepalive
2119+
{
2120+
routes.set('/backend/constructor/tcp-keepalive-invalid', async () => {
2121+
await assertRejects(async () => {
2122+
await fetch('https://http-me.glitch.me/anything', {
2123+
backend: new Backend({
2124+
name: 'grpc-grpc-invalid',
2125+
target: 'http-me.glitch.me',
2126+
tcpKeepalive: 'blah',
2127+
}),
2128+
cacheOverride: new CacheOverride('pass'),
2129+
});
2130+
}, TypeError);
2131+
await assertRejects(async () => {
2132+
await fetch('https://http-me.glitch.me/anything', {
2133+
backend: new Backend({
2134+
name: 'grpc-grpc-invalid',
2135+
target: 'http-me.glitch.me',
2136+
tcpKeepalive: {
2137+
intervalSecs: 'boo',
2138+
},
2139+
}),
2140+
cacheOverride: new CacheOverride('pass'),
2141+
});
2142+
}, RangeError);
2143+
});
2144+
routes.set('/backend/constructor/tcp-keepalive', async () => {
2145+
await fetch('https://http-me.glitch.me/anything', {
2146+
backend: new Backend({
2147+
name: 'grpc-grpc-invalid',
2148+
target: 'http-me.glitch.me',
2149+
tcpKeepalive: {
2150+
intervalSecs: 1000,
2151+
probes: 4,
2152+
},
2153+
}),
2154+
cacheOverride: new CacheOverride('pass'),
2155+
});
2156+
});
2157+
}
2158+
}
2159+
2160+
// setDefaultDynamicBackendConfig
2161+
{
2162+
routes.set('/backend/set-default-backend-configuration', async () => {
2163+
if (isRunningLocally()) {
2164+
return;
2165+
}
2166+
setDefaultDynamicBackendConfig({
2167+
firstByteTimeout: 1_000,
2168+
});
2169+
const backend = new Backend({
2170+
name: 'new-default',
2171+
target: 'http-me.glitch.me',
2172+
});
2173+
console.time(`fetch('https://http-me.glitch.me/test?wait=2000'`);
2174+
await assertRejects(
2175+
() =>
2176+
fetch('https://http-me.glitch.me/test?wait=2000', {
2177+
backend,
2178+
cacheOverride: new CacheOverride('pass'),
2179+
}),
2180+
DOMException,
2181+
'HTTP response timeout',
2182+
);
2183+
console.timeEnd(`fetch('https://http-me.glitch.me/test?wait=2000'`);
2184+
});
20782185
}
20792186

20802187
// exists

integration-tests/js-compute/fixtures/app/src/hono.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ routes.set('/hono', async (evt) => {
1010
allowDynamicBackends(true);
1111
app.get('/hono', async (c) => {
1212
const newRequest = new Request(
13-
'https://compute-sdk-test-backend.edgecompute.app/',
13+
'https://http-me.glitch.me/anything',
1414
c.req.raw,
1515
);
1616
console.log('newRequest: ' + newRequest.url);

0 commit comments

Comments
 (0)