Skip to content

Commit 760212b

Browse files
Update preview URL token format for DNS compliance
Updated Sandbox SDK documentation to reflect the DNS-compliant token format change from PR #247. Preview URL tokens now use only lowercase alphanumeric characters and hyphens (RFC 952/1123 compliant) instead of including underscores. Changes: - Updated URL format examples to include 16-character tokens - Added migration note about breaking change in SDK v0.5.4+ - Clarified token security characteristics - Updated all code examples with correct URL format This is a breaking change - existing preview URLs with underscores will stop working after SDK upgrade. Users must call exposePort() again to get new DNS-compliant URLs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent ad91c85 commit 760212b

File tree

4 files changed

+24
-16
lines changed

4 files changed

+24
-16
lines changed

src/content/docs/sandbox/api/ports.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ await sandbox.startProcess('python -m http.server 8000');
4141
const exposed = await sandbox.exposePort(8000, { hostname });
4242
4343
console.log('Available at:', exposed.exposedAt);
44-
// https://8000-abc123.yourdomain.com
44+
// https://8000-abc123-a1b2c3d4e5f6g7h8.yourdomain.com
4545
4646
// Multiple services with names
4747
await sandbox.startProcess('node api.js');

src/content/docs/sandbox/concepts/preview-urls.mdx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,27 @@ await sandbox.startProcess("python -m http.server 8000");
1919
const exposed = await sandbox.exposePort(8000, { hostname });
2020

2121
console.log(exposed.exposedAt);
22-
// Production: https://8000-abc123.yourdomain.com
22+
// Production: https://8000-abc123-a1b2c3d4e5f6g7h8.yourdomain.com
2323
// Local dev: http://localhost:8787/...
2424
```
2525

2626
## URL Format
2727

28-
**Production**: `https://{port}-{sandbox-id}.yourdomain.com`
28+
**Production**: `https://{port}-{sandbox-id}-{token}.yourdomain.com`
2929

30-
- Port 8080: `https://8080-abc123.yourdomain.com`
31-
- Port 3000: `https://3000-abc123.yourdomain.com`
30+
- Port 8080: `https://8080-abc123-a1b2c3d4e5f6g7h8.yourdomain.com`
31+
- Port 3000: `https://3000-abc123-x9y8z7w6v5u4t3s2.yourdomain.com`
3232

3333
**Local development**: `http://localhost:8787/...`
3434

35+
The token is a 16-character random string containing only lowercase alphanumeric characters and hyphens, ensuring DNS compliance with RFC 952/1123 hostname requirements.
36+
3537
Preview URLs remain stable while a port is exposed and can be shared during that time. However, if you unexpose and re-expose a port, a new random token is generated and the URL changes. For persistent URLs, keep ports exposed for the duration you need them accessible.
3638

39+
:::note[Token format change - SDK v0.5.4+]
40+
Starting in SDK version 0.5.4, preview URL tokens use only DNS-valid characters (RFC 952/1123 compliant). Tokens generated by earlier versions containing underscores are automatically migrated when you access the sandbox. This is a breaking change - old preview URLs with underscores will stop working after upgrade. Call `exposePort()` again to get new DNS-compliant URLs.
41+
:::
42+
3743
## ID Case Sensitivity
3844

3945
Preview URLs extract the sandbox ID from the hostname to route requests. Since hostnames are case-insensitive (per RFC 3986), they're always lowercased: `8080-MyProject-123.yourdomain.com` becomes `8080-myproject-123.yourdomain.com`.
@@ -101,9 +107,9 @@ await sandbox.startProcess("node admin.js"); // Port 3001
101107
const api = await sandbox.exposePort(3000, { hostname, name: "api" });
102108
const admin = await sandbox.exposePort(3001, { hostname, name: "admin" });
103109

104-
// Each gets its own URL:
105-
// https://3000-abc123.yourdomain.com
106-
// https://3001-abc123.yourdomain.com
110+
// Each gets its own URL with unique tokens:
111+
// https://3000-abc123-x1y2z3w4v5u6t7s8.yourdomain.com
112+
// https://3001-abc123-p9q8r7s6t5u4v3w2.yourdomain.com
107113
```
108114

109115
## What Works
@@ -155,9 +161,9 @@ Preview URLs are publicly accessible by default, but require a valid access toke
155161

156162
**Built-in security**:
157163

158-
- **Token-based access** - Each exposed port gets a unique token in the URL (for example, `https://8080-sandbox-abc123token.yourdomain.com`)
164+
- **Token-based access** - Each exposed port gets a unique 16-character token in the URL (for example, `https://8080-sandbox-a1b2c3d4e5f6g7h8.yourdomain.com`)
159165
- **HTTPS in production** - All traffic is encrypted with automatic TLS
160-
- **Unpredictable URLs** - Tokens are randomly generated and difficult to guess
166+
- **Unpredictable URLs** - Tokens are cryptographically random and use only DNS-valid characters (lowercase alphanumeric and hyphens per RFC 952/1123)
161167

162168
**Add application-level authentication**:
163169

src/content/docs/sandbox/guides/expose-services.mdx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export default {
5555
5656
// 4. Preview URL is now available (public by default)
5757
console.log('Server accessible at:', exposed.exposedAt);
58-
// Production: https://8000-abc123.yourdomain.com
58+
// Production: https://8000-abc123-a1b2c3d4e5f6g7h8.yourdomain.com
5959
// Local dev: http://localhost:8787/...
6060
6161
return Response.json({ url: exposed.exposedAt });
@@ -330,10 +330,12 @@ See [Sandbox options - normalizeId](/sandbox/configuration/sandbox-options/#norm
330330

331331
## Preview URL Format
332332

333-
**Production**: `https://{port}-{sandbox-id}.yourdomain.com`
333+
**Production**: `https://{port}-{sandbox-id}-{token}.yourdomain.com`
334334

335-
- Port 8080: `https://8080-abc123.yourdomain.com`
336-
- Port 5173: `https://5173-abc123.yourdomain.com`
335+
- Port 8080: `https://8080-abc123-a1b2c3d4e5f6g7h8.yourdomain.com`
336+
- Port 5173: `https://5173-abc123-x9y8z7w6v5u4t3s2.yourdomain.com`
337+
338+
The token is a 16-character random string using only DNS-valid characters (lowercase alphanumeric and hyphens per RFC 952/1123).
337339

338340
**Local development**: `http://localhost:8787/...`
339341

src/content/docs/sandbox/guides/production-deployment.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { WranglerConfig } from "~/components";
1212
Custom domain setup is ONLY needed if you use `exposePort()` to expose services from sandboxes. If your application does not expose ports, you can deploy to `.workers.dev` without this configuration.
1313
:::
1414

15-
Deploy your Sandbox SDK application to production with preview URL support. Preview URLs require wildcard DNS routing because they generate unique subdomains for each exposed port: `https://8080-abc123.yourdomain.com`.
15+
Deploy your Sandbox SDK application to production with preview URL support. Preview URLs require wildcard DNS routing because they generate unique subdomains for each exposed port: `https://8080-abc123-a1b2c3d4e5f6g7h8.yourdomain.com`.
1616

1717
The `.workers.dev` domain does not support wildcard subdomains, so production deployments that use preview URLs need a custom domain.
1818

@@ -74,7 +74,7 @@ await sandbox.startProcess('python -m http.server 8080');
7474
const exposed = await sandbox.exposePort(8080, { hostname });
7575

7676
console.log(exposed.exposedAt);
77-
// https://8080-test-sandbox.yourdomain.com
77+
// https://8080-test-sandbox-a1b2c3d4e5f6g7h8.yourdomain.com
7878
```
7979

8080
Visit the URL in your browser to confirm your service is accessible.

0 commit comments

Comments
 (0)