Skip to content

Instantly share code, notes, and snippets.

@jamesflores
Created May 12, 2024 02:07
Show Gist options
  • Save jamesflores/85e9777d5ca076b2d29312a31754003e to your computer and use it in GitHub Desktop.
Save jamesflores/85e9777d5ca076b2d29312a31754003e to your computer and use it in GitHub Desktop.
Cloudflare worker that returns a book cover given a book title and author name using the Open Library API
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
const DEFAULT_IMAGE_URL = ''; // Update to your own default image
async function handleRequest(request) {
const url = new URL(request.url);
const bookTitle = url.searchParams.get('book_title') || '';
const authorName = url.searchParams.get('author_name') || '';
// Attempt to fetch ISBNs from Open Library
const isbns = await fetchISBNs(bookTitle, authorName);
if (isbns.length === 0) {
console.log("No ISBNs found, using default image.");
return fetchAndCacheImage(DEFAULT_IMAGE_URL);
}
// Try fetching cover images for the first ten ISBNs
for (let i = 0; i < Math.min(10, isbns.length); i++) {
const coverUrl = `https://covers.openlibrary.org/b/isbn/${isbns[i]}-L.jpg?default=false`;
const imageResponse = await fetch(coverUrl);
if (imageResponse.ok) {
console.log(`Cover image found for ISBN ${isbns[i]}`);
return new Response(imageResponse.body, {
headers: {
'Content-Type': 'image/jpeg'
}
});
} else {
console.log(`No cover found for ISBN ${isbns[i]}`);
}
}
// If no valid cover images were found, return the default image
console.log("No valid covers found, using default image.");
return fetchAndCacheImage(DEFAULT_IMAGE_URL);
}
async function fetchISBNs(bookTitle, authorName) {
const searchUrl = `https://openlibrary.org/search.json?title=${encodeURIComponent(bookTitle)}&author=${encodeURIComponent(authorName)}&fields=isbn`;
const response = await fetch(searchUrl);
if (!response.ok) {
console.error("Failed to fetch ISBNs:", response.statusText);
return [];
}
const data = await response.json();
if (data.docs.length > 0 && data.docs[0].isbn) {
return data.docs[0].isbn;
}
return [];
}
async function fetchAndCacheImage(imageUrl) {
console.log(`Fetching image from URL: ${imageUrl}`);
const imageResponse = await fetch(imageUrl);
return new Response(imageResponse.body, {
status: imageResponse.status,
statusText: imageResponse.statusText,
headers: {
'Cache-Control': 'public, max-age=31536000, immutable', // Cache for 1 year
'Content-Type': 'image/jpeg'
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment