@coinbase/cdp-sdk
Version:
SDK for interacting with the Coinbase Developer Platform Wallet API
120 lines • 5.23 kB
JavaScript
import { createLogger } from "../logging/logger.js";
import { join } from "../url/join.js";
import { EndpointSupplier } from "./EndpointSupplier.js";
import { getFetchFn } from "./getFetchFn.js";
import { makeRequest } from "./makeRequest.js";
import { requestWithRetries } from "./requestWithRetries.js";
import { Supplier } from "./Supplier.js";
/**
* Makes a passthrough HTTP request using the SDK's configuration (auth, retry, logging, etc.)
* while mimicking the standard `fetch` API.
*
* @param input - The URL, path, or Request object. If a relative path, it will be resolved against the configured base URL.
* @param init - Standard RequestInit options (method, headers, body, signal, etc.)
* @param clientOptions - SDK client options (auth, default headers, logging, etc.)
* @param requestOptions - Per-request overrides (timeout, retries, extra headers, abort signal).
* @returns A standard Response object.
*/
export async function makePassthroughRequest(input, init, clientOptions, requestOptions) {
const logger = createLogger(clientOptions.logging);
// Extract URL and default init properties from Request object if provided
let url;
let effectiveInit = init;
if (input instanceof Request) {
url = input.url;
// If no explicit init provided, extract properties from the Request object
if (init == null) {
effectiveInit = {
method: input.method,
headers: Object.fromEntries(input.headers.entries()),
body: input.body,
signal: input.signal,
credentials: input.credentials,
cache: input.cache,
redirect: input.redirect,
referrer: input.referrer,
integrity: input.integrity,
mode: input.mode,
};
}
}
else {
url = input instanceof URL ? input.toString() : input;
}
// Resolve the base URL
const baseUrl = (clientOptions.baseUrl != null ? await Supplier.get(clientOptions.baseUrl) : undefined) ??
(clientOptions.environment != null ? await Supplier.get(clientOptions.environment) : undefined);
// Determine the full URL
let fullUrl;
if (url.startsWith("http://") || url.startsWith("https://")) {
fullUrl = url;
}
else if (baseUrl != null) {
fullUrl = join(baseUrl, url);
}
else {
fullUrl = url;
}
// Merge headers: SDK default headers -> auth headers -> user-provided headers
const mergedHeaders = {};
// Apply SDK default headers (resolve suppliers)
if (clientOptions.headers != null) {
for (const [key, value] of Object.entries(clientOptions.headers)) {
const resolved = await EndpointSupplier.get(value, { endpointMetadata: {} });
if (resolved != null) {
mergedHeaders[key.toLowerCase()] = `${resolved}`;
}
}
}
// Apply auth headers
if (clientOptions.getAuthHeaders != null) {
const authHeaders = await clientOptions.getAuthHeaders();
for (const [key, value] of Object.entries(authHeaders)) {
mergedHeaders[key.toLowerCase()] = value;
}
}
// Apply user-provided headers from init
if (effectiveInit?.headers != null) {
const initHeaders = effectiveInit.headers instanceof Headers
? Object.fromEntries(effectiveInit.headers.entries())
: Array.isArray(effectiveInit.headers)
? Object.fromEntries(effectiveInit.headers)
: effectiveInit.headers;
for (const [key, value] of Object.entries(initHeaders)) {
if (value != null) {
mergedHeaders[key.toLowerCase()] = value;
}
}
}
// Apply per-request option headers (highest priority)
if (requestOptions?.headers != null) {
for (const [key, value] of Object.entries(requestOptions.headers)) {
mergedHeaders[key.toLowerCase()] = value;
}
}
const method = effectiveInit?.method ?? "GET";
const body = effectiveInit?.body;
const timeoutInSeconds = requestOptions?.timeoutInSeconds ?? clientOptions.timeoutInSeconds;
const timeoutMs = timeoutInSeconds != null ? timeoutInSeconds * 1000 : undefined;
const maxRetries = requestOptions?.maxRetries ?? clientOptions.maxRetries;
const abortSignal = requestOptions?.abortSignal ?? effectiveInit?.signal ?? undefined;
const fetchFn = clientOptions.fetch ?? (await getFetchFn());
if (logger.isDebug()) {
logger.debug("Making passthrough HTTP request", {
method,
url: fullUrl,
hasBody: body != null,
});
}
const response = await requestWithRetries(async () => makeRequest(fetchFn, fullUrl, method, mergedHeaders, body ?? undefined, timeoutMs, abortSignal, effectiveInit?.credentials === "include", undefined, // duplex
false), maxRetries);
if (logger.isDebug()) {
logger.debug("Passthrough HTTP request completed", {
method,
url: fullUrl,
statusCode: response.status,
});
}
return response;
}
//# sourceMappingURL=makePassthroughRequest.js.map