Skip to content

Commit 17988a0

Browse files
authored
Ensure fetch errors are caught properly, simplify handling of Headers to fix bug (#179)
* Update curl command in fetchWithRetry to include error handling options, ensure errors are actually caught properly and returned to users. * Force format of headers passed into fetchWithRetry to be more predictable, no more reliance on `instanceof Headers` check. Fixes #177
1 parent 8c81927 commit 17988a0

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

.changeset/large-years-obey.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"figma-developer-mcp": patch
3+
---
4+
5+
Update curl command in fetchWithRetry to include error handling options, ensure errors are actually caught properly and returned to users.

src/utils/fetch-with-retry.ts

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ import { Logger } from "./logger.js";
44

55
const execAsync = promisify(exec);
66

7-
export async function fetchWithRetry<T>(url: string, options: RequestInit = {}): Promise<T> {
7+
type RequestOptions = RequestInit & {
8+
/**
9+
* Force format of headers to be a record of strings, e.g. { "Authorization": "Bearer 123" }
10+
*
11+
* Avoids complexity of needing to deal with `instanceof Headers`, which is not supported in some environments.
12+
*/
13+
headers?: Record<string, string>;
14+
};
15+
16+
export async function fetchWithRetry<T>(url: string, options: RequestOptions = {}): Promise<T> {
817
try {
918
const response = await fetch(url, options);
1019

@@ -18,7 +27,11 @@ export async function fetchWithRetry<T>(url: string, options: RequestInit = {}):
1827
);
1928

2029
const curlHeaders = formatHeadersForCurl(options.headers);
21-
const curlCommand = `curl -s -L ${curlHeaders.join(" ")} "${url}"`;
30+
// -s: Silent mode—no progress bar in stderr
31+
// -S: Show errors in stderr
32+
// --fail-with-body: curl errors with code 22, and outputs body of failed request, e.g. "Fetch failed with status 404"
33+
// -L: Follow redirects
34+
const curlCommand = `curl -s -S --fail-with-body -L ${curlHeaders.join(" ")} "${url}"`;
2235

2336
try {
2437
// Fallback to curl for corporate networks that have proxies that sometimes block fetch
@@ -60,25 +73,10 @@ export async function fetchWithRetry<T>(url: string, options: RequestInit = {}):
6073
* @param headers Headers to convert.
6174
* @returns Array of strings, each a curl -H argument.
6275
*/
63-
function formatHeadersForCurl(headers: HeadersInit | undefined): string[] {
76+
function formatHeadersForCurl(headers: Record<string, string> | undefined): string[] {
6477
if (!headers) {
6578
return [];
6679
}
6780

68-
const curlHeaders: string[] = [];
69-
70-
if (headers instanceof Headers) {
71-
headers.forEach((value, key) => {
72-
curlHeaders.push(`-H "${key}: ${value}"`);
73-
});
74-
} else if (Array.isArray(headers)) {
75-
headers.forEach(([key, value]) => {
76-
curlHeaders.push(`-H "${key}: ${value}"`);
77-
});
78-
} else {
79-
Object.entries(headers).forEach(([key, value]) => {
80-
curlHeaders.push(`-H "${key}: ${value}"`);
81-
});
82-
}
83-
return curlHeaders;
81+
return Object.entries(headers).map(([key, value]) => `-H "${key}: ${value}"`);
8482
}

0 commit comments

Comments
 (0)