[object Object]

← back to Hollywood Wallcoverings

Route product image_url through vendor-neutral image proxy (no CDN vendor names in customer output)

d63b1c1915ea4b8a5b8c592d5564a88a9f9357d1 · 2026-06-03 14:34:45 -0700 · Steve Abrams

Files touched

Diff

commit d63b1c1915ea4b8a5b8c592d5564a88a9f9357d1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Jun 3 14:34:45 2026 -0700

    Route product image_url through vendor-neutral image proxy (no CDN vendor names in customer output)
---
 server.js | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/server.js b/server.js
index 2aefe74..84a9d61 100644
--- a/server.js
+++ b/server.js
@@ -8,6 +8,8 @@ const express = require('express');
 const helmet = require('helmet');
 const path = require('path');
 const fs = require('fs');
+const { createImgProxy } = require('../_shared/image-proxy');
+const IMGP = createImgProxy();
 
 /* Vendor-name leak scrub (audit 2026-05-29) — strip any hyphen-delimited segment
  * carrying a 3rd-party vendor token from a slug/handle shown in this storefront's
@@ -112,6 +114,10 @@ app.use((req, res, next) => {
   next();
 });
 
+// Vendor-neutral image proxy — streams real CDN bytes via /img/:token so the
+// 3rd-party-vendor-named CDN filenames never reach customer-facing HTML/JSON.
+IMGP.mount(app);
+
 const NORM_TYPE = (t) => {
   if (!t) return 'Other';
   const x = t.replace(/s$/i, '').trim();
@@ -144,7 +150,9 @@ function rebuildCatalog(rawRows) {
   DATA = DATA_RAW.filter(p => !isJunk(p));
   DROPPED = DATA_RAW.length - DATA.length;
   TYPES = [...new Set(DATA.map(p => NORM_TYPE(p.product_type)))].sort();
+  IMGP.registerAll(DATA);
   console.log(`[${__SITE}] catalog: ${DATA_RAW.length} rows, kept ${DATA.length}, dropped ${DROPPED} as junk`);
+  console.log(`[${__SITE}] image-proxy map: ${IMGP.size()} urls`);
 }
 
 const esc = s => String(s||'').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
@@ -709,7 +717,7 @@ function cardHtml(p) {
   const cleanTitle = (p.title || '').replace(/\s*\|\s*Hollywood Wallcoverings\s*$/i,'');
   return `<article class="card">
     <a class="thumb" href="/p/${esc(encodeURIComponent(redactVendorSlug(p.handle||'')))}">
-      ${p.image_url ? `<img loading="lazy" src="${esc(p.image_url)}" alt="${esc(cleanTitle)}">` : ''}
+      ${p.image_url ? `<img loading="lazy" src="${esc(IMGP.proxyImg(p.image_url))}" alt="${esc(cleanTitle)}">` : ''}
     </a>
     <div class="info">
       <a href="/p/${esc(encodeURIComponent(redactVendorSlug(p.handle||'')))}">
@@ -889,7 +897,7 @@ app.get('/p/:handle', (req, res) => {
   const cleanTitle = p.title.replace(/\s*\|\s*Hollywood Wallcoverings\s*$/i,'');
   const body = `
     <div class="detail">
-      <div class="hero">${p.image_url ? `<img src="${esc(p.image_url)}" alt="${esc(cleanTitle)}">` : ''}</div>
+      <div class="hero">${p.image_url ? `<img src="${esc(IMGP.proxyImg(p.image_url))}" alt="${esc(cleanTitle)}">` : ''}</div>
       <div>
         <div class="crumb"><a href="/">Hollywood Wallcoverings</a> / ${esc(NORM_TYPE(p.product_type))}</div>
         <div class="pt">${esc(NORM_TYPE(p.product_type))}</div>

← cc222b0 Add root /favicon.{ico,svg} route (static is mounted under /  ·  back to Hollywood Wallcoverings  ·  Scrub residual vendor names from products.json (title/vendor a3a2311 →