Skip to content

Commit d409943

Browse files
kennethkalmerclaude
andcommitted
feat: add endpoint and controlAPIHost to signed config
Add support for endpoint and controlAPIHost parameters in the signed config system to restore custom endpoint configuration that was lost in PR #129. Changes: - Update SignRequest interface to accept optional endpoint and controlAPIHost - Modify signCredentials() to include endpoint fields in config when provided - Update /api/sign endpoint and vite middleware to accept and pass through endpoint params - Maintain backward compatibility - endpoints are optional This allows implementations to specify custom Ably endpoints (e.g., staging) which will be signed and validated via HMAC. Related to: PR #129 (d454d36) Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
1 parent 1a35aa0 commit d409943

3 files changed

Lines changed: 11 additions & 5 deletions

File tree

examples/web-cli/api/sign.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { signCredentials, getSigningSecret } from "../server/sign-handler.js";
1313
* Request Body:
1414
* - apiKey: string (required) - Ably API key in format "appId.keyId:secret"
1515
* - bypassRateLimit: boolean (optional) - Set to true for CI/testing
16+
* - endpoint: string (optional) - Custom Ably endpoint URL
17+
* - controlAPIHost: string (optional) - Custom control API host URL
1618
*
1719
* Response:
1820
* - signedConfig: string - JSON-encoded config that was signed
@@ -35,14 +37,14 @@ export default async function handler(
3537
return res.status(500).json({ error: "Signing secret not configured" });
3638
}
3739

38-
const { apiKey, bypassRateLimit } = req.body;
40+
const { apiKey, bypassRateLimit, endpoint, controlAPIHost } = req.body;
3941

4042
if (!apiKey) {
4143
return res.status(400).json({ error: "apiKey is required" });
4244
}
4345

4446
// Use shared signing logic
45-
const result = signCredentials({ apiKey, bypassRateLimit }, secret);
47+
const result = signCredentials({ apiKey, bypassRateLimit, endpoint, controlAPIHost }, secret);
4648

4749
res.status(200).json(result);
4850
}

examples/web-cli/server/sign-handler.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import crypto from "crypto";
88
export interface SignRequest {
99
apiKey: string;
1010
bypassRateLimit?: boolean;
11+
endpoint?: string;
12+
controlAPIHost?: string;
1113
}
1214

1315
export interface SignResponse {
@@ -25,13 +27,15 @@ export function signCredentials(
2527
request: SignRequest,
2628
secret: string,
2729
): SignResponse {
28-
const { apiKey, bypassRateLimit } = request;
30+
const { apiKey, bypassRateLimit, endpoint, controlAPIHost } = request;
2931

3032
// Build config object (matches terminal server expectations)
3133
const config = {
3234
apiKey,
3335
timestamp: Date.now(),
3436
bypassRateLimit: bypassRateLimit || false,
37+
...(endpoint && { endpoint }),
38+
...(controlAPIHost && { controlAPIHost }),
3539
};
3640

3741
// Serialize to JSON - this exact string is what gets signed

examples/web-cli/vite.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function apiSignPlugin(): Plugin {
3636

3737
req.on("end", () => {
3838
try {
39-
const { apiKey, bypassRateLimit } = JSON.parse(body);
39+
const { apiKey, bypassRateLimit, endpoint, controlAPIHost } = JSON.parse(body);
4040

4141
if (!apiKey) {
4242
res.statusCode = 400;
@@ -46,7 +46,7 @@ function apiSignPlugin(): Plugin {
4646
}
4747

4848
// Use shared signing logic
49-
const result = signCredentials({ apiKey, bypassRateLimit }, secret);
49+
const result = signCredentials({ apiKey, bypassRateLimit, endpoint, controlAPIHost }, secret);
5050

5151
res.statusCode = 200;
5252
res.setHeader("Content-Type", "application/json");

0 commit comments

Comments
 (0)