429 error response on my photography portfolio using Imgur API

68 views Asked by At

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 :/

0

There are 0 answers