in src/core.ts [472:531]
private async makeRequest<Req>(
optionsInput: PromiseOrValue<FinalRequestOptions<Req>>,
retriesRemaining: number | null,
): Promise<APIResponseProps> {
const options = await optionsInput;
const maxRetries = options.maxRetries ?? this.maxRetries;
if (retriesRemaining == null) {
retriesRemaining = maxRetries;
}
await this.prepareOptions(options);
const { req, url, timeout } = this.buildRequest(options, { retryCount: maxRetries - retriesRemaining });
await this.prepareRequest(req, { url, options });
debug('request', url, options, req.headers);
if (options.signal?.aborted) {
throw new APIUserAbortError();
}
const controller = new AbortController();
const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
if (response instanceof Error) {
if (options.signal?.aborted) {
throw new APIUserAbortError();
}
if (retriesRemaining) {
return this.retryRequest(options, retriesRemaining);
}
if (response.name === 'AbortError') {
throw new APIConnectionTimeoutError();
}
throw new APIConnectionError({ cause: response });
}
const responseHeaders = createResponseHeaders(response.headers);
if (!response.ok) {
if (retriesRemaining && this.shouldRetry(response)) {
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
debug(`response (error; ${retryMessage})`, response.status, url, responseHeaders);
return this.retryRequest(options, retriesRemaining, responseHeaders);
}
const errText = await response.text().catch((e) => castToError(e).message);
const errJSON = safeJSON(errText);
const errMessage = errJSON ? undefined : errText;
const retryMessage = retriesRemaining ? `(error; no more retries left)` : `(error; not retryable)`;
debug(`response (error; ${retryMessage})`, response.status, url, responseHeaders, errMessage);
const err = this.makeStatusError(response.status, errJSON, errMessage, responseHeaders);
throw err;
}
return { response, options, controller };
}