openvibers/openvibe.media Commits
Thumbnails are open to every origin (Live's player reads a thumbnail's colours; every offline channel page logged a CORS error) (#161)
Changes
@@@ -272,6 +272,11 @@ router.get('/og-image.png', (req, res) => {// ── Thumbnails ───────────────────────────────────────────────router.get('/t/:id', (req, res) => {if (drill.refuseBytes(res)) return;++ // Open to every origin like the other public images: Live's player samples a stream thumbnail's colours on a++ // canvas (an anonymous CORS load), which failed with a console error on every offline channel page (2026-10-23).++ // Whoever has the URL can already load the image; this lets a page read its pixels.++ res.set('Access-Control-Allow-Origin', '*');++ res.set('Cross-Origin-Resource-Policy', 'cross-origin');require('../thumbnails/thumbnail-service').serveThumbnail(req, res);});@@@ -73,6 +73,11 @@ const express = require('express');(async () => {await new Promise((res) => (server.listening ? res() : server.once('listening', res)));++ // ── thumbnails: open to every origin (Live samples a stream thumbnail's colours on a canvas) ──++ let t = await get('/t/g1.jpg', { origin: 'https://openvibe.live' });++ assert.strictEqual(t.status, 200);++ assert.strictEqual(t.headers['access-control-allow-origin'], '*', 'a thumbnail may be read cross-origin');++ assert.strictEqual(t.headers['cross-origin-resource-policy'], 'cross-origin');// ── robots.txt ──let r = await get('/robots.txt');assert.strictEqual(r.status, 200);
@@ -272,6 +272,11 @@ router.get('/og-image.png', (req, res) => {
@@ -272,6 +272,11 @@ router.get('/og-image.png', (req, res) => {
// ── Thumbnails ───────────────────────────────────────────────
// ── Thumbnails ───────────────────────────────────────────────
router.get('/t/:id', (req, res) => {
router.get('/t/:id', (req, res) => {
if (drill.refuseBytes(res)) return;
if (drill.refuseBytes(res)) return;
+ // Open to every origin like the other public images: Live's player samples a stream thumbnail's colours on a
+ // canvas (an anonymous CORS load), which failed with a console error on every offline channel page (2026-10-23).
+ // Whoever has the URL can already load the image; this lets a page read its pixels.
+ res.set('Access-Control-Allow-Origin', '*');
+ res.set('Cross-Origin-Resource-Policy', 'cross-origin');
require('../thumbnails/thumbnail-service').serveThumbnail(req, res);
require('../thumbnails/thumbnail-service').serveThumbnail(req, res);
});
});
@@ -73,6 +73,11 @@ const express = require('express');
@@ -73,6 +73,11 @@ const express = require('express');
(async () => {
(async () => {
await new Promise((res) => (server.listening ? res() : server.once('listening', res)));
await new Promise((res) => (server.listening ? res() : server.once('listening', res)));
+ // ── thumbnails: open to every origin (Live samples a stream thumbnail's colours on a canvas) ──
+ let t = await get('/t/g1.jpg', { origin: 'https://openvibe.live' });
+ assert.strictEqual(t.status, 200);
+ assert.strictEqual(t.headers['access-control-allow-origin'], '*', 'a thumbnail may be read cross-origin');
+ assert.strictEqual(t.headers['cross-origin-resource-policy'], 'cross-origin');
// ── robots.txt ──
// ── robots.txt ──
let r = await get('/robots.txt');
let r = await get('/robots.txt');
assert.strictEqual(r.status, 200);
assert.strictEqual(r.status, 200);