Skip to content

Commit

Permalink
feat(apps/hermes/client): allow authorization headers (#1738)
Browse files Browse the repository at this point in the history
* feat(apps/hermes/client): allow authorization headers

* bump version

* pass in headers to constructor instead

* address comments
  • Loading branch information
cctdaniel authored Jul 4, 2024
1 parent 3762116 commit 07a7767
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
2 changes: 1 addition & 1 deletion apps/hermes/client/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pythnetwork/hermes-client",
"version": "1.0.3",
"version": "1.0.4",
"description": "Pyth Hermes Client",
"author": {
"name": "Pyth Data Association"
Expand Down
16 changes: 13 additions & 3 deletions apps/hermes/client/js/src/HermesClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@ export type HermesClientConfig = {
* it will timeout regardless of the retries at the configured `timeout` time.
*/
httpRetries?: number;
/**
* Optional headers to be included in every request.
*/
headers?: HeadersInit;
};

export class HermesClient {
private baseURL: string;
private timeout: DurationInMs;
private httpRetries: number;
private headers: HeadersInit;

/**
* Constructs a new Connection.
Expand All @@ -46,6 +51,7 @@ export class HermesClient {
this.baseURL = endpoint;
this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;
this.httpRetries = config?.httpRetries ?? DEFAULT_HTTP_RETRIES;
this.headers = config?.headers ?? {};
}

private async httpRequest<ResponseData>(
Expand All @@ -58,7 +64,11 @@ export class HermesClient {
): Promise<ResponseData> {
const controller = externalAbortController ?? new AbortController();
const { signal } = controller;
options = { ...options, signal }; // Merge any existing options with the signal
options = {
...options,
signal,
headers: { ...this.headers, ...options?.headers },
}; // Merge any existing options with the signal and headers

// Set a timeout to abort the request if it takes too long
const timeout = setTimeout(() => controller.abort(), this.timeout);
Expand Down Expand Up @@ -129,7 +139,7 @@ export class HermesClient {
parsed?: boolean;
}
): Promise<PriceUpdate> {
const url = new URL(`v2/updates/price/latest`, this.baseURL);
const url = new URL("v2/updates/price/latest", this.baseURL);
for (const id of ids) {
url.searchParams.append("ids[]", id);
}
Expand Down Expand Up @@ -208,7 +218,7 @@ export class HermesClient {
this.appendUrlSearchParams(url, transformedOptions);
}

return new EventSource(url.toString());
return new EventSource(url.toString(), { headers: this.headers });
}

private appendUrlSearchParams(
Expand Down
29 changes: 28 additions & 1 deletion apps/hermes/client/js/src/examples/HermesClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,35 @@ const argv = yargs(hideBin(process.argv))
})
.parseSync();

/**
* Extracts the endpoint and basic authorization headers from a given URL string.
*
* @param {string} urlString - The URL string containing the endpoint and optional basic auth credentials.
* @returns {{ endpoint: string; headers: HeadersInit }} An object containing the endpoint URL and headers.
*/
function extractBasicAuthorizationHeadersFromUrl(urlString: string): {
endpoint: string;
headers: HeadersInit;
} {
const url = new URL(urlString);
const headers: HeadersInit = {};

if (url.username && url.password) {
headers["Authorization"] = `Basic ${btoa(
`${url.username}:${url.password}`
)}`;
url.username = "";
url.password = "";
}

return { endpoint: url.toString(), headers };
}

async function run() {
const connection = new HermesClient(argv.endpoint);
const { endpoint, headers } = extractBasicAuthorizationHeadersFromUrl(
argv.endpoint
);
const connection = new HermesClient(endpoint, { headers });

const priceIds = argv.priceIds as string[];

Expand Down

0 comments on commit 07a7767

Please sign in to comment.