I am trying to render images in my gallery albums using ImgurAPI. I keep receiving a 429 error, and have researched Imgur's rate limiting. My albums have under 50 images, and I can't seem to debug the issue. For reference here is my api file alongside one of my album files. I have also applied a limiter . When i click on the specific 429 error and open in new tab. The screen displays this error: {"data":{"error":"Authentication required","request":"/3/album/0SW5APn/images}","method":"GET"},"success":false,"status":401}
Here are my ref files:
imgur-api.tsx:
import limiter from "./limiter";
const clientId = process.env.IMGUR_CLIENT_ID || '';
const baseURL = 'https://api.imgur.com/3/';
const cache = new Map();
interface ImgurImage {
link: string;
}
// Function to get images from a public Imgur album
export async function getAlbumImages(albumId: string): Promise<string[]> {
console.log(`Fetching album images for albumId: ${albumId}`); // Log the API call
// Check if data is cached
if (cache.has(albumId)) {
console.log(`Serving from cache for albumId: ${albumId}`);
return cache.get(albumId);
}
try {
const response = await limiter.schedule(() => fetch(`${baseURL}album/${albumId}/images}`, {
method: 'GET',
headers: {
'Authorization': `Client-ID ${clientId}`,
}
}));
// Log rate limit status from the response headers
console.log('Rate Limit Status:', {
clientRemaining: response.headers.get('X-RateLimit-ClientRemaining'),
userRemaining: response.headers.get('X-RateLimit-UserRemaining'),
userReset: response.headers.get('X-RateLimit-UserReset'),
});
// Handle 429 error
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || '60'; // Fallback to 60 seconds
throw new Error(`Rate limit exceeded. Retry after ${retryAfter} seconds.`);
}
if (!response.ok) {
throw new Error(`Error: ${response.statusText}`);
}
// Read rate limit headers and adjust limiter
adjustRateLimiter(response.headers);
const data = await response.json();
const images = data.data.map((image: ImgurImage) => image.link);
// Cache the data
cache.set(albumId, images);
return images;
} catch (error) {
console.error('Error fetching images from Imgur:', error);
throw error;
}
}
function adjustRateLimiter(headers: Headers) {
const clientRemaining = headers.get('X-RateLimit-ClientRemaining');
const userRemaining = headers.get('X-RateLimit-UserRemaining');
const userReset = headers.get('X-RateLimit-UserReset');
if (clientRemaining !== null) {
const remaining = parseInt(clientRemaining, 10);
// Adjust rate limiter based on remaining client credits
return remaining;
}
if (userRemaining !== null) {
const remaining = parseInt(userRemaining, 10);
// Adjust rate limiter based on remaining user credits
return remaining;
}
if (userReset !== null) {
const resetTime = parseInt(userReset, 10) * 1000; // Convert to milliseconds
// Handle the reset time logic
return resetTime; // Return the reset time in milliseconds
}
}
NYC gallery page.tsx file:
'use client';
import { useEffect, useState } from 'react';
import Image from 'next/image';
import { getAlbumImages } from '@/services/Imgur-api';
import Loading from '../loading';
const NYCpage = () => {
const [data, setData] = useState<string[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
setLoading(true);
getAlbumImages('0SW5APn')
.then((images) => {
setData(images);
setLoading(false);
})
.catch((error: Error) => {
console.error("Error fetching data:", error);
setError(error);
setLoading(false);
});
}, []);
if (loading) {
return <Loading />;
}
if (error) {
return <div className="flex justify-center">Error loading images...</div>;
}
return (
<div className="grid grid-cols-4 gap-4 gap-y-3 w-full text-center">
{data.map((imageUrl, index) => (
<Image
key={index}
src={imageUrl}
loading="lazy"
width={200}
height={200}
alt={`NYC Image ${index + 1}`}
/>
))}
</div>
);
};
export default NYCpage;
I tried to put a limiter on and incorporate error handling too pinpoint the issue, but I am at a standstill at this point :/