From 2dca2a899748c5fcd9a4c3bcf2f04bb6c81bcb7c Mon Sep 17 00:00:00 2001 From: David Murdoch Date: Thu, 15 May 2025 01:35:23 +0100 Subject: [PATCH] fix(media): component failing when setting a custom serverURL * https://github.com/payloadcms/payload/pull/12214 --- src/components/Media/ImageMedia/index.tsx | 4 +-- src/components/Media/VideoMedia/index.tsx | 4 +-- src/utilities/get-media-url/index.ts | 23 +++++++++++++ src/utilities/get-media-url/test.ts | 41 +++++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/utilities/get-media-url/index.ts create mode 100644 src/utilities/get-media-url/test.ts diff --git a/src/components/Media/ImageMedia/index.tsx b/src/components/Media/ImageMedia/index.tsx index d8222d2..94edf15 100644 --- a/src/components/Media/ImageMedia/index.tsx +++ b/src/components/Media/ImageMedia/index.tsx @@ -4,7 +4,7 @@ import type { FunctionComponent } from "react"; import NextImage from "next/image"; import type { StaticImageData } from "next/image"; import { cssVariables } from "~/cssVariables"; -import { getClientSideURL } from "~/utilities/get-url"; +import { getMediaUrl } from "~/utilities/get-media-url"; import { cn } from "~/utilities/ui"; import type { Props as MediaProps } from "../types"; @@ -46,7 +46,7 @@ export const ImageMedia: FunctionComponent = (props) => { const cacheTag = resource.updatedAt; - src = `${getClientSideURL()}${url}?${cacheTag}`; + src = getMediaUrl(url, cacheTag); } const loading = loadingFromProps || (!priority ? "lazy" : undefined); diff --git a/src/components/Media/VideoMedia/index.tsx b/src/components/Media/VideoMedia/index.tsx index 32ed28d..325399d 100644 --- a/src/components/Media/VideoMedia/index.tsx +++ b/src/components/Media/VideoMedia/index.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef } from "react"; import type { FunctionComponent } from "react"; -import { getClientSideURL } from "~/utilities/get-url"; +import { getMediaUrl } from "~/utilities/get-media-url"; import { cn } from "~/utilities/ui"; import type { Props as MediaProps } from "../types"; @@ -36,7 +36,7 @@ export const VideoMedia: FunctionComponent = (props) => { playsInline ref={videoRef} > - + ); } diff --git a/src/utilities/get-media-url/index.ts b/src/utilities/get-media-url/index.ts new file mode 100644 index 0000000..dfdbfda --- /dev/null +++ b/src/utilities/get-media-url/index.ts @@ -0,0 +1,23 @@ +import { getClientSideURL } from "~/utilities/get-url/"; + +/** + * Processes media resource URL to ensure proper formatting + * @param url The original URL from the resource + * @param cacheTag Optional cache tag to append to the URL + * @returns Properly formatted URL with cache tag if provided + */ +export const getMediaUrl = ( + url: string | null | undefined, + cacheTag?: string | null, +): string => { + if (!url) return ""; + + // Check if URL already has http/https protocol + if (url.startsWith("http://") || url.startsWith("https://")) { + return cacheTag ? `${url}?${cacheTag}` : url; + } + + // Otherwise prepend client-side URL + const baseUrl = getClientSideURL(); + return cacheTag ? `${baseUrl}${url}?${cacheTag}` : `${baseUrl}${url}`; +}; diff --git a/src/utilities/get-media-url/test.ts b/src/utilities/get-media-url/test.ts new file mode 100644 index 0000000..3dfb7d1 --- /dev/null +++ b/src/utilities/get-media-url/test.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from "@jest/globals"; +import { getMediaUrl } from "."; + +describe("utilities", () => { + describe("getMediaUrl", () => { + it("use no url", () => { + // @ts-expect-error cope with no arguments + expect(getMediaUrl()).toBe(""); + }); + + it("use full url", () => { + expect(getMediaUrl("http://localhost:3000")).toBe( + "http://localhost:3000", + ); + }); + + it("use full url with cacheTag", () => { + expect(getMediaUrl("http://localhost:3000", "tag=tag")).toBe( + "http://localhost:3000?tag=tag", + ); + }); + + it("use client browser plus endpoint", () => { + Object.defineProperty(window, "location", { + value: new URL("http://localhost:3000"), + }); + + expect(getMediaUrl("/foo")).toBe("http://localhost:3000/foo"); + }); + + it("use client browser plus endpoint with cacheTage", () => { + Object.defineProperty(window, "location", { + value: new URL("http://localhost:3000"), + }); + + expect(getMediaUrl("/foo", "tag=tag")).toBe( + "http://localhost:3000/foo?tag=tag", + ); + }); + }); +});