From db12dd6074e11f239287fdf56c63b373cea3c9b4 Mon Sep 17 00:00:00 2001 From: kptdobe Date: Tue, 30 Jun 2026 12:09:36 +0200 Subject: [PATCH] fix: load hlx6 media via preview.da.live proxy For hlx6 repos, images/videos are served through api.aem.live with Bearer auth. The previous code used content.da.live which does not serve hlx6 content. Now mirrors the approach from PR #930: detects hlx6 via isHlx6, rewrites contentUrl to the preview.da.live equivalent (same host pattern used for AEM images in the editor), and authenticates with livePreviewLogin instead of contentLogin. No binary fetch or blob URL needed. Co-Authored-By: Claude Sonnet 4.6 --- blocks/media/media.js | 19 +++++-- test/unit/blocks/media/media.test.js | 79 ++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 test/unit/blocks/media/media.test.js diff --git a/blocks/media/media.js b/blocks/media/media.js index def39a141..d888208d2 100644 --- a/blocks/media/media.js +++ b/blocks/media/media.js @@ -2,7 +2,8 @@ import getPathDetails from '../shared/pathDetails.js'; import { getNx, getNx2Api } from '../../scripts/utils.js'; import '../edit/da-title/da-title.js'; -import { contentLogin } from '../shared/utils.js'; +import { contentLogin, livePreviewLogin } from '../shared/utils.js'; +import { getLivePreviewUrl } from '../shared/constants.js'; const PDF_VIEWER_SRC = 'https://acrobatservices.adobe.com/view-sdk/viewer.js'; const PDF_CLIENT_ID = 'cd73455ea6c04d0aac86270f9f5f830c'; @@ -65,17 +66,27 @@ async function loadPdfMedia(path, fileName) { export default async function init(el) { const details = getPathDetails(); - const { name, fullpath, owner, repo } = details; + const { name, fullpath, owner, repo, path } = details; const ext = name.split('.').pop(); - await contentLogin(owner, repo); + const { isHlx6 } = await getNx2Api(); + const hlx6 = await isHlx6(owner, repo); + + let mediaDetails = details; + if (hlx6 && ext !== 'pdf') { + const contentUrl = `${getLivePreviewUrl(owner, repo)}${path}`; + mediaDetails = { ...details, contentUrl }; + await livePreviewLogin(owner, repo); + } else { + await contentLogin(owner, repo); + } const daTitle = document.createElement('da-title'); const daMedia = ext === 'pdf' ? await getPdfMedia() : await getDefaultMedia(); daTitle.details = details; - daMedia.details = details; + daMedia.details = mediaDetails; el.append(daTitle, daMedia); if (ext === 'pdf') loadPdfMedia(fullpath, name); diff --git a/test/unit/blocks/media/media.test.js b/test/unit/blocks/media/media.test.js new file mode 100644 index 000000000..410589de2 --- /dev/null +++ b/test/unit/blocks/media/media.test.js @@ -0,0 +1,79 @@ +import { expect } from '@esm-bundle/chai'; + +const { setNx } = await import('../../../../scripts/utils.js'); +setNx('/test/fixtures/nx', { hostname: 'example.com' }); + +const { default: init } = await import('../../../../blocks/media/media.js'); + +const HLX_ADMIN = 'https://admin.hlx.page'; +const CON_ORIGIN = 'https://content.da.live'; +const PREVIEW_DOMAIN = 'preview.da.live'; + +function makeFetchMock({ hlx6Paths = [] } = {}) { + return (url) => { + if (url.startsWith(`${HLX_ADMIN}/ping/`)) { + const path = url.slice(`${HLX_ADMIN}/ping`.length); + const headers = new Headers(); + if (hlx6Paths.some((p) => path.startsWith(p))) { + headers.set('x-api-upgrade-available', 'true'); + } + return Promise.resolve(new Response('', { status: 200, headers })); + } + if (url.includes('.gimme_cookie')) { + return Promise.resolve(new Response('', { status: 200 })); + } + return Promise.resolve(new Response('', { status: 404 })); + }; +} + +describe('media init', () => { + let el; + let savedFetch; + + beforeEach(() => { + savedFetch = window.fetch; + el = document.createElement('div'); + document.body.appendChild(el); + }); + + afterEach(() => { + window.fetch = savedFetch; + el.remove(); + }); + + it('rewrites contentUrl to preview.da.live for hlx6 image repos', async () => { + window.fetch = makeFetchMock({ hlx6Paths: ['/rofe/media-hlx6a'] }); + history.pushState(null, '', '/media#/rofe/media-hlx6a/photo.png'); + + await init(el); + + const daMedia = el.querySelector('da-media'); + expect(daMedia).to.exist; + expect(daMedia.details.contentUrl).to.equal(`https://main--media-hlx6a--rofe.${PREVIEW_DOMAIN}/photo.png`); + }); + + it('keeps content.da.live contentUrl for non-hlx6 repos', async () => { + window.fetch = makeFetchMock({ hlx6Paths: [] }); + history.pushState(null, '', '/media#/rofe/media-legacy1/photo.png'); + + await init(el); + + const daMedia = el.querySelector('da-media'); + expect(daMedia).to.exist; + expect(daMedia.details.contentUrl).to.include(CON_ORIGIN); + expect(daMedia.details.contentUrl).to.not.include(PREVIEW_DOMAIN); + }); + + it('uses different contentUrl object for hlx6 to avoid mutating pathDetails cache', async () => { + window.fetch = makeFetchMock({ hlx6Paths: ['/rofe/media-hlx6b'] }); + history.pushState(null, '', '/media#/rofe/media-hlx6b/img.jpg'); + + await init(el); + + const daMedia = el.querySelector('da-media'); + const daTitle = el.querySelector('da-title'); + expect(daMedia.details).to.not.equal(daTitle.details); + expect(daMedia.details.contentUrl).to.include(PREVIEW_DOMAIN); + expect(daTitle.details.contentUrl).to.include(CON_ORIGIN); + }); +});