From 75deb7f88250ca01b348960565e00cb5ccd79208 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Thu, 23 Jul 2026 12:37:11 +0000 Subject: [PATCH] docs: redirect bare Learn path --- data/redirects.yml | 2 ++ hack/releaser/cloudfront-lambda-redirects.js | 7 ++++++- hack/releaser/cloudfront-lambda-redirects.test.js | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/data/redirects.yml b/data/redirects.yml index edcc63ca694..6a243e4d8f4 100644 --- a/data/redirects.yml +++ b/data/redirects.yml @@ -8,6 +8,8 @@ # provide a short, permanent link to refer to a topic in the documentation. # For example, the docker CLI can output https://docs.docker.com/go/some-topic # in its help output, which can be redirected to elsewhere in the documentation. +"/learn/": + - /learn "/security/access-tokens/": - /go/access-tokens/ "/reference/api/engine/#deprecated-api-versions": diff --git a/hack/releaser/cloudfront-lambda-redirects.js b/hack/releaser/cloudfront-lambda-redirects.js index 505d73fdab8..7d3d4cfe199 100644 --- a/hack/releaser/cloudfront-lambda-redirects.js +++ b/hack/releaser/cloudfront-lambda-redirects.js @@ -22,7 +22,12 @@ exports.handler = (event, context, callback) => { const redirects = JSON.parse(`{{.RedirectsJSON}}`); for (let key in redirects) { const redirectTarget = key.replace(/\/$/, ""); - if (redirectTarget !== requestUrl) { + const exactMatch = key === request.uri; + // Preserve slash-insensitive matching without redirecting a canonical + // slash-terminated destination back to itself. + const normalizedMatch = + redirectTarget === requestUrl && redirects[key] !== request.uri; + if (!exactMatch && !normalizedMatch) { continue; } //console.log(`redirect: ${requestUrl} to ${redirects[key]}`); diff --git a/hack/releaser/cloudfront-lambda-redirects.test.js b/hack/releaser/cloudfront-lambda-redirects.test.js index f07430fd2cc..915e33b10d6 100644 --- a/hack/releaser/cloudfront-lambda-redirects.test.js +++ b/hack/releaser/cloudfront-lambda-redirects.test.js @@ -17,6 +17,7 @@ const Module = require("node:module"); const SRC = path.join(__dirname, "cloudfront-lambda-redirects.js"); const REDIRECTS = { + "/learn": "/learn/", "/old/page/": "/new/page/", "/target-with-query/": "/dest/?ref=docs", "/target-with-fragment/": "/dest/?ref=docs#install", @@ -85,6 +86,16 @@ test("exact redirect without a query string is unchanged", async () => { assert.equal(locationOf(result), "/new/page/"); }); +test("bare path redirects without redirecting the canonical target to itself", async () => { + const { result: bareResult } = await invoke({ uri: "/learn" }); + assert.equal(bareResult.status, "301"); + assert.equal(locationOf(bareResult), "/learn/"); + + const { result: canonicalResult, request } = await invoke({ uri: "/learn/" }); + assert.equal(canonicalResult, request); + assert.equal(request.uri, "/learn/index.html"); +}); + test("exact redirect appends with & when target already has a query string", async () => { const { result } = await invoke({ uri: "/target-with-query/",