From ae6b012f8866c3a1a973687d3a24f683880b913d Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 3 Sep 2021 14:55:50 -0700 Subject: [PATCH] Fail harder when *all* layers fail to load This was actually being _triggered_ by the fact that the user outfits page doesn't generate great outfit image URLs! It doesn't encode the layerUrls parameter, so now that image URLs sometimes contain `&`, the parameter was being misparsed. Example: ``` http://localhost:3000/api/outfitImage?size=300&layerUrls=https://impress-2020.openneo.net/api/assetImage?libraryUrl=https%3A%2F%2Fimages.neopets.com%2Fcp%2Fitems%2Fdata%2F000%2F000%2F054%2F54348_cf1cfe10c7%2Fall-background.js&size=300,http://images.neopets.com/cp/bio/data/000/000/041/41572_0450defb29/41572.svg,http://images.neopets.com/cp/bio/data/000/000/041/41570_83582a4a83/41570.svg,http://images.neopets.com/cp/bio/data/000/000/041/41571_7e6c072e12/41571.svg,http://images.neopets.com/cp/bio/data/000/000/041/41582_06159c1e4d/41582.svg,http://images.neopets.com/cp/bio/data/000/000/041/41574_520e661a8a/41574.svg,http://images.neopets.com/cp/bio/data/000/000/041/41573_f4f480ba37/41573.svg,https://impress-asset-images.openneo.net/object/000/000/480/480378/300x300.png?v2-1597211608000 ``` would get the following list of layer URLs: ``` ["https://impress-2020.openneo.net/api/assetImage?libraryUrl=https://images.neopets.com/cp/items/data/000/000/054/54348_cf1cfe10c7/all-background.js"] ``` Anyway, I'm gonna fix that (probably by just not using this layerUrls param anymore and moving to the new outfit ID + timestamp URLs), but let's also just have clearer error messages instead of just a blank image! That way, if something similar happens again, the client will fall back to alt text, instead of showing a blank image. --- src/server/outfit-images.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/server/outfit-images.js b/src/server/outfit-images.js index d5efdad..68256d3 100644 --- a/src/server/outfit-images.js +++ b/src/server/outfit-images.js @@ -1,11 +1,18 @@ import { createCanvas, loadImage } from "canvas"; -async function renderOutfitImage(layerRefs, size) { +async function renderOutfitImage(layerUrls, size) { const canvas = createCanvas(size, size); const ctx = canvas.getContext("2d"); - const images = await Promise.all(layerRefs.map(loadImageAndSkipOnFailure)); + const images = await Promise.all(layerUrls.map(loadImageAndSkipOnFailure)); + const loadedImages = images.filter((image) => image); + if (loadedImages.length === 0) { + throw new Error( + `Could not load any of the layer images: ${layerUrls.join(", ")}` + ); + } + for (const image of loadedImages) { ctx.drawImage(image, 0, 0, size, size); } @@ -13,7 +20,7 @@ async function renderOutfitImage(layerRefs, size) { return { image: canvas.toBuffer(), status: - loadedImages.length === layerRefs.length ? "success" : "partial-failure", + loadedImages.length === layerUrls.length ? "success" : "partial-failure", }; }