fix: ensures req.origin includes port on localhost (#11454)

The `req.origin` property on the `PayloadRequest` object does not
include the port when running on localhost, a requirement of the [HTML
Living Standard](https://html.spec.whatwg.org/#origin). This was because
we were initializing the url with a fallback of `http://localhost` (no
port). When constructed via `new URL()`, the port is unable to be
extracted. This is fixed by using the `host` property off the headers
object, if it exists, which includes the port.

Partial fix for #11448.
This commit is contained in:
Jacob Fletcher
2025-02-28 12:26:38 -05:00
committed by GitHub
parent 4a1b74952f
commit a65289c211
2 changed files with 17 additions and 8 deletions

View File

@@ -26,22 +26,26 @@ function getRequestContext(
const attachFakeURLProperties = (req: Partial<PayloadRequest>) => {
/**
* *NOTE*
* If no URL is provided, the local API was called directly outside
* If no URL is provided, the local API was called outside
* the context of a request. Therefore we create a fake URL object.
* `ts-expect-error` is used below for properties that are 'read-only'
* since they do not exist yet we can safely ignore the error.
* `ts-expect-error` is used below for properties that are 'read-only'.
* Since they do not exist yet we can safely ignore the error.
*/
let urlObject
let urlObject: undefined | URL
function getURLObject() {
if (urlObject) {
return urlObject
}
const urlToUse = req?.url || req.payload.config?.serverURL || 'http://localhost'
const fallbackURL = `http://${req.host || 'localhost'}`
const urlToUse = req?.url || req.payload.config?.serverURL || fallbackURL
try {
urlObject = new URL(urlToUse)
} catch (error) {
urlObject = new URL('http://localhost')
} catch (_err) {
urlObject = new URL(fallbackURL)
}
return urlObject
@@ -50,20 +54,25 @@ const attachFakeURLProperties = (req: Partial<PayloadRequest>) => {
if (!req.host) {
req.host = getURLObject().host
}
if (!req.protocol) {
req.protocol = getURLObject().protocol
}
if (!req.pathname) {
req.pathname = getURLObject().pathname
}
if (!req.searchParams) {
// @ts-expect-error eslint-disable-next-line no-param-reassign
req.searchParams = getURLObject().searchParams
}
if (!req.origin) {
// @ts-expect-error eslint-disable-next-line no-param-reassign
req.origin = getURLObject().origin
}
if (!req?.url) {
// @ts-expect-error eslint-disable-next-line no-param-reassign
req.url = getURLObject().href

View File

@@ -31,7 +31,7 @@
}
],
"paths": {
"@payload-config": ["./test/admin/config.ts"],
"@payload-config": ["./test/_community/config.ts"],
"@payloadcms/live-preview": ["./packages/live-preview/src"],
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],