Skip to content

Commit

Permalink
chore: forward origin header to usage tracker (#6384)
Browse files Browse the repository at this point in the history
  • Loading branch information
arcoraven authored Mar 1, 2025
1 parent 47c9c43 commit 25b149d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-planes-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@thirdweb-dev/service-utils": patch
---

[service-utils] Provide CF req to forward origin header
45 changes: 21 additions & 24 deletions packages/service-utils/src/cf-worker/usageV2.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
import { Headers, type Request, fetch } from "@cloudflare/workers-types";
import type { CoreAuthInput } from "src/core/types.js";
import type {
ClientUsageV2Event,
UsageV2Event,
UsageV2Source,
} from "../core/usageV2.js";
import { extractAuthorizationData } from "./index.js";

type UsageV2Options = {
usageBaseUrl: string;
source: UsageV2Source;
} & (
| { serviceKey: string; thirdwebClientId?: never; thirdwebSecretKey?: never }
| { serviceKey?: never; thirdwebClientId: string; thirdwebSecretKey?: never }
| { serviceKey?: never; thirdwebClientId?: never; thirdwebSecretKey: string }
);
authInput: CoreAuthInput & { req: Request };
serviceKey?: string;
};

/**
* Send usageV2 events from either internal services or public clients.
*
* Exactly one authentication method must be provided:
* - serviceKey: for internal services
* - thirdwebClientId: for public clients (MUST be the user's project)
* - thirdwebSecretKey: for public clients (MUST be the user's project)
*
* NOTE: `team_id` is required if `serviceKey` is provided.
*
* This method may throw. To call this non-blocking:
* ```ts
* void sendUsageV2Events(...).catch((e) => console.error(e))
Expand All @@ -34,19 +28,23 @@ export async function sendUsageV2Events<T extends UsageV2Options>(
: ClientUsageV2Event[],
options: T,
): Promise<void> {
const { usageBaseUrl, source, authInput, serviceKey } = options;
const { clientId, secretKey } = await extractAuthorizationData(authInput);

// Forward headers from the origin request.
// Determine endpoint and auth header based on provided credentials.
let url: string;
const headers: HeadersInit = { "Content-Type": "application/json" };

if (options.serviceKey) {
url = `${options.usageBaseUrl}/usage-v2/${options.source}`;
headers["x-service-api-key"] = options.serviceKey;
} else if (options.thirdwebSecretKey) {
url = `${options.usageBaseUrl}/usage-v2/${options.source}/client`;
headers["x-secret-key"] = options.thirdwebSecretKey;
} else if (options.thirdwebClientId) {
url = `${options.usageBaseUrl}/usage-v2/${options.source}/client`;
headers["x-client-id"] = options.thirdwebClientId;
const headers = new Headers(authInput.req.headers);
headers.set("Content-Type", "application/json");
if (serviceKey) {
// If a service key is provided, call the non-public usage endpoint.
url = `${usageBaseUrl}/usage-v2/${source}`;
headers.set("x-service-api-key", serviceKey);
} else if (clientId) {
url = `${usageBaseUrl}/usage-v2/${source}/client`;
headers.set("x-client-id", clientId);
} else if (secretKey) {
url = `${usageBaseUrl}/usage-v2/${source}/client`;
} else {
throw new Error("[UsageV2] No authentication method provided.");
}
Expand All @@ -56,7 +54,6 @@ export async function sendUsageV2Events<T extends UsageV2Options>(
headers,
body: JSON.stringify({ events }),
});

if (!resp.ok) {
throw new Error(
`[UsageV2] Unexpected response ${resp.status}: ${await resp.text()}`,
Expand Down

0 comments on commit 25b149d

Please sign in to comment.