Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 68 additions & 38 deletions src/core/functions/uploads/createSignedUploadURL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,49 +84,79 @@ export const createSignedUploadURL = async (
};
}

try {
const request = await fetch(`${endpoint}/files/sign`, {
method: "POST",
headers: headers,
cache: "no-store",
body: JSON.stringify(payload),
});

if (!request.ok) {
const errorData = await request.text();
if (request.status === 401 || request.status === 403) {
throw new AuthenticationError(
`Authentication Failed: ${errorData}`,
request.status,
{
error: errorData,
code: "AUTH_ERROR",
metadata: {
requestUrl: request.url,
const maxRetries = 3;

for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const request = await fetch(`${endpoint}/files/sign`, {
method: "POST",
headers: headers,
cache: "no-store",
body: JSON.stringify(payload),
});

if (!request.ok) {
const errorData = await request.text();
if (request.status === 401 || request.status === 403) {
throw new AuthenticationError(
`Authentication Failed: ${errorData}`,
request.status,
{
error: errorData,
code: "AUTH_ERROR",
metadata: {
requestUrl: request.url,
},
},
);
}
throw new NetworkError(`HTTP error: ${errorData}`, request.status, {
error: errorData,
code: "HTTP_ERROR",
metadata: {
requestUrl: request.url,
},
});
}

const res = await request.json();
return res.data;
} catch (error) {
// Don't retry auth errors or client errors (except 429)
if (error instanceof AuthenticationError) {
throw error;
}
if (
error instanceof NetworkError &&
error.statusCode &&
error.statusCode >= 400 &&
error.statusCode < 500 &&
error.statusCode !== 429
) {
throw error;
}

// If we've exhausted retries, throw the error
if (attempt === maxRetries) {
if (error instanceof PinataError) {
throw error;
}
if (error instanceof Error) {
throw new PinataError(
`Error processing createSignedURL: ${error.message}`,
);
}
throw new PinataError(
"An unknown error occurred while getting signed url",
);
}
throw new NetworkError(`HTTP error: ${errorData}`, request.status, {
error: errorData,
code: "HTTP_ERROR",
metadata: {
requestUrl: request.url,
},
});
}

const res = await request.json();
return res.data;
} catch (error) {
if (error instanceof PinataError) {
throw error;
// Wait before retrying (exponential backoff: 1s, 2s, 4s)
const delay = Math.min(1000 * Math.pow(2, attempt), 4000);
await new Promise((resolve) => setTimeout(resolve, delay));
}
if (error instanceof Error) {
throw new PinataError(
`Error processing createSignedURL: ${error.message}`,
);
}
throw new PinataError("An unknown error occurred while getting signed url");
}

// This should never be reached, but TypeScript requires it
throw new PinataError("An unknown error occurred while getting signed url");
};