From c10182cbb99d5a793418adb224ab3e1a8b3b28b0 Mon Sep 17 00:00:00 2001 From: Stefan Guggisberg Date: Fri, 24 Jan 2025 11:32:48 +0100 Subject: [PATCH] fix: surrogate key for non-existing .html in code-bus --- src/json-pipe.js | 11 ++++++----- src/robots-pipe.js | 4 ++-- src/steps/fetch-404.js | 22 +++++++++++++--------- src/steps/fetch-content.js | 6 +++--- src/steps/set-x-surrogate-key-header.js | 24 +++++++++++++++++++----- test/rendering.test.js | 2 +- 6 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/json-pipe.js b/src/json-pipe.js index 0e9d735e..f6faef5e 100644 --- a/src/json-pipe.js +++ b/src/json-pipe.js @@ -12,6 +12,7 @@ import { cleanupHeaderValue, computeSurrogateKey } from '@adobe/helix-shared-utils'; import initConfig from './steps/init-config.js'; import setCustomResponseHeaders from './steps/set-custom-response-headers.js'; +import { computeContentPathKey, computeCodePathKey } from './steps/set-x-surrogate-key-header.js'; import { PipelineResponse } from './PipelineResponse.js'; import jsonFilter from './utils/json-filter.js'; import { extractLastModified, updateLastModified } from './utils/last-modified.js'; @@ -42,7 +43,7 @@ export default function folderMapping(state) { async function fetchJsonContent(state, req, res) { const { - owner, repo, ref, contentBusId, partition, s3Loader, log, info, + owner, repo, ref, contentBusId, partition, s3Loader, log, } = state; const { path } = state.info; state.content.sourceBus = 'content'; @@ -65,11 +66,11 @@ async function fetchJsonContent(state, req, res) { if (state.content.sourceBus === 'content') { // provide either (prefixed) preview or (unprefixed) live content keys const contentKeyPrefix = partition === 'preview' ? 'p_' : ''; - keys.push(`${contentKeyPrefix}${await computeSurrogateKey(`${contentBusId}${info.path}`)}`); + keys.push(`${contentKeyPrefix}${await computeContentPathKey(state)}`); keys.push(`${contentKeyPrefix}${contentBusId}`); } else { keys.push(`${ref}--${repo}--${owner}_code`); - keys.push(await computeSurrogateKey(`${ref}--${repo}--${owner}${info.path}`)); + keys.push(await computeCodePathKey(state)); } res.headers.set('x-surrogate-key', keys.join(' ')); res.error = 'moved'; @@ -100,13 +101,13 @@ async function computeSurrogateKeys(state) { keys.push(await computeSurrogateKey(`${state.site}--${state.org}_config.json`)); } if (state.content.sourceBus.includes('code')) { - keys.push(await computeSurrogateKey(`${state.ref}--${state.repo}--${state.owner}${state.info.path}`)); + keys.push(await computeCodePathKey(state)); keys.push(`${state.ref}--${state.repo}--${state.owner}_code`); } if (state.content.sourceBus.includes('content')) { // provide either (prefixed) preview or (unprefixed) live content keys const contentKeyPrefix = state.partition === 'preview' ? 'p_' : ''; - keys.push(`${contentKeyPrefix}${await computeSurrogateKey(`${state.contentBusId}${state.info.path}`)}`); + keys.push(`${contentKeyPrefix}${await await computeContentPathKey(state)}`); keys.push(`${contentKeyPrefix}${state.contentBusId}`); } diff --git a/src/robots-pipe.js b/src/robots-pipe.js index 1fc1bbbc..0560ada1 100644 --- a/src/robots-pipe.js +++ b/src/robots-pipe.js @@ -11,6 +11,7 @@ */ import { cleanupHeaderValue, computeSurrogateKey } from '@adobe/helix-shared-utils'; import renderCode from './steps/render-code.js'; +import { computeCodePathKey } from './steps/set-x-surrogate-key-header.js'; import setCustomResponseHeaders from './steps/set-custom-response-headers.js'; import { PipelineResponse } from './PipelineResponse.js'; import initConfig from './steps/init-config.js'; @@ -119,9 +120,8 @@ function getForwardedHosts(req) { async function computeSurrogateKeys(state) { const keys = []; - const pathKey = `${state.ref}--${state.repo}--${state.owner}${state.info.path}`; keys.push(await computeSurrogateKey(`${state.site}--${state.org}_config.json`)); - keys.push(await computeSurrogateKey(pathKey)); + keys.push(await computeCodePathKey(state)); return keys; } diff --git a/src/steps/fetch-404.js b/src/steps/fetch-404.js index 8ec94401..7d516aa3 100644 --- a/src/steps/fetch-404.js +++ b/src/steps/fetch-404.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ import { extractLastModified } from '../utils/last-modified.js'; -import { getPathKey } from './set-x-surrogate-key-header.js'; +import { computeContentPathKey, computeCodePathKey } from './set-x-surrogate-key-header.js'; /** * Loads the 404.html from code-bus and stores it in `res.body` @@ -39,18 +39,22 @@ export default async function fetch404(state, req, res) { } // set 404 keys in any case - const pathKey = await getPathKey(state); // provide either (prefixed) preview or (unprefixed) live content keys const contentKeyPrefix = partition === 'preview' ? 'p_' : ''; - const keys = [ - `${contentKeyPrefix}${pathKey}`, - `${contentKeyPrefix}${contentBusId}`, - `${ref}--${repo}--${owner}_404`, - `${ref}--${repo}--${owner}_code`, - ]; + const keys = []; + if (state.content.sourceBus === 'code') { + keys.push(await computeCodePathKey(state)); + } else { + const contentPathKey = await computeContentPathKey(state); + // provide either (prefixed) preview or (unprefixed) live content keys + keys.push(`${contentKeyPrefix}${contentPathKey}`); + keys.push(`${contentKeyPrefix}${contentBusId}`); + } + keys.push(`${ref}--${repo}--${owner}_404`); + keys.push(`${ref}--${repo}--${owner}_code`); if (state.info.unmappedPath) { - const unmappedPathKey = await getPathKey({ + const unmappedPathKey = await computeContentPathKey({ contentBusId, info: { path: state.info.unmappedPath }, }); diff --git a/src/steps/fetch-content.js b/src/steps/fetch-content.js index 5efd1b36..e5de6151 100644 --- a/src/steps/fetch-content.js +++ b/src/steps/fetch-content.js @@ -9,8 +9,8 @@ * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -import { computeSurrogateKey } from '@adobe/helix-shared-utils'; import { extractLastModified, updateLastModified } from '../utils/last-modified.js'; +import { computeContentPathKey, computeCodePathKey } from './set-x-surrogate-key-header.js'; /** * Loads the content from either the content-bus or code-bus and stores it in `state.content` @@ -43,12 +43,12 @@ export default async function fetchContent(state, req, res) { res.headers.set('location', redirectLocation); const keys = []; if (isCode) { - keys.push(await computeSurrogateKey(`${ref}--${repo}--${owner}${info.path}`)); + keys.push(await computeCodePathKey(state)); keys.push(`${ref}--${repo}--${owner}_code`); } else { // provide either (prefixed) preview or (unprefixed) live content keys const contentKeyPrefix = partition === 'preview' ? 'p_' : ''; - keys.push(`${contentKeyPrefix}${await computeSurrogateKey(`${contentBusId}${info.path}`)}`); + keys.push(`${contentKeyPrefix}${await computeContentPathKey(state)}`); keys.push(`${contentKeyPrefix}${contentBusId}`); } res.headers.set('x-surrogate-key', keys.join(' ')); diff --git a/src/steps/set-x-surrogate-key-header.js b/src/steps/set-x-surrogate-key-header.js index de2966a5..77494b18 100644 --- a/src/steps/set-x-surrogate-key-header.js +++ b/src/steps/set-x-surrogate-key-header.js @@ -12,11 +12,12 @@ import { computeSurrogateKey } from '@adobe/helix-shared-utils'; /** - * Returns the surrogate key based on the contentBusId and the resource path + * Returns the surrogate key for a content-bus resource + * based on the contentBusId and the resource path * @param state * @returns {Promise} */ -export async function getPathKey(state) { +export async function computeContentPathKey(state) { const { contentBusId, info } = state; let { path } = info; // surrogate key for path @@ -33,6 +34,19 @@ export async function getPathKey(state) { return computeSurrogateKey(`${contentBusId}${path}`); } +/** + * Returns the surrogate key for a code-bus resource + * based on the repositry and the resource path + * @param state + * @returns {Promise} + */ +export async function computeCodePathKey(state) { + const { + owner, repo, ref, info: { path }, + } = state; + return computeSurrogateKey(`${ref}--${repo}--${owner}${path}`); +} + /** * @type PipelineStep * @param {PipelineState} state @@ -50,9 +64,9 @@ export default async function setXSurrogateKeyHeader(state, req, res) { // provide either (prefixed) preview or (unprefixed) live content keys const contentKeyPrefix = partition === 'preview' ? 'p_' : ''; const keys = []; - const hash = await getPathKey(state); + const hash = await computeContentPathKey(state); if (isCode) { - keys.push(await computeSurrogateKey(`${ref}--${repo}--${owner}${state.info.path}`)); + keys.push(await computeCodePathKey(state)); keys.push(`${ref}--${repo}--${owner}_code`); } else { keys.push(`${contentKeyPrefix}${hash}`); @@ -64,7 +78,7 @@ export default async function setXSurrogateKeyHeader(state, req, res) { if (state.mapped) { keys.push(`${contentKeyPrefix}${hash}_metadata`); if (state.info.unmappedPath) { - keys.push(`${contentKeyPrefix}${await getPathKey({ + keys.push(`${contentKeyPrefix}${await computeContentPathKey({ contentBusId, info: { path: state.info.unmappedPath }, })}`); diff --git a/test/rendering.test.js b/test/rendering.test.js index 341ebc00..3cb73d40 100644 --- a/test/rendering.test.js +++ b/test/rendering.test.js @@ -564,7 +564,7 @@ describe('Rendering', () => { 'content-type': 'text/html; charset=utf-8', 'last-modified': 'Wed, 12 Oct 2009 17:50:00 GMT', 'x-error': 'failed to load /not-found-with-handler.html from code-bus: 404', - 'x-surrogate-key': 'ta3V7wR3zlRh1b0E foo-id super-test--helix-pages--adobe_404 super-test--helix-pages--adobe_code', + 'x-surrogate-key': '9q9qs7DEYGc4lYTJ super-test--helix-pages--adobe_404 super-test--helix-pages--adobe_code', link: '; rel=modulepreload; as=script; crossorigin=use-credentials', 'access-control-allow-origin': '*', });