feat(storage-*): include modified headers into the response headers of files when using adapters (#12096)

This PR makes it so that `modifyResponseHeaders` is supported in our
adapters when set on the collection config. Previously it would be
ignored.

This means that users can now modify or append new headers to what's
returned by each service.

```ts
import type { CollectionConfig } from 'payload'

export const Media: CollectionConfig = {
  slug: 'media',
  upload: {
    modifyResponseHeaders: ({ headers }) => {
      const newHeaders = new Headers(headers) // Copy existing headers
      newHeaders.set('X-Frame-Options', 'DENY') // Set new header

      return newHeaders
    },
  },
}
```

Also adds support for `void` return on the `modifyResponseHeaders`
function in the case where the user just wants to use existing headers
and doesn't need more control.

eg:

```ts
import type { CollectionConfig } from 'payload'

export const Media: CollectionConfig = {
  slug: 'media',
  upload: {
    modifyResponseHeaders: ({ headers }) => {
      headers.set('X-Frame-Options', 'DENY') // You can directly set headers without returning
    },
  },
}
```

Manual testing checklist (no CI e2es setup for these envs yet):
- [x] GCS
- [x] S3
- [x] Azure
- [x] UploadThing
- [x] Vercel Blob

---------

Co-authored-by: James <james@trbl.design>
This commit is contained in:
Paul
2025-07-10 16:00:26 +01:00
committed by GitHub
parent 055cc4ef12
commit cb6a73e1b4
17 changed files with 256 additions and 99 deletions

View File

@@ -3,6 +3,9 @@ import type { CollectionConfig } from 'payload'
export const Media: CollectionConfig = {
slug: 'media',
upload: {
modifyResponseHeaders({ headers }) {
headers.set('X-Universal-Truth', 'Set')
},
disableLocalStorage: true,
resizeOptions: {
position: 'center',

View File

@@ -84,7 +84,7 @@ export interface Config {
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
db: {
defaultIDType: string;
defaultIDType: number;
};
globals: {};
globalsSelect: {};
@@ -120,7 +120,7 @@ export interface UserAuthOperations {
* via the `definition` "media".
*/
export interface Media {
id: string;
id: number;
alt?: string | null;
updatedAt: string;
createdAt: string;
@@ -157,7 +157,7 @@ export interface Media {
* via the `definition` "media-with-prefix".
*/
export interface MediaWithPrefix {
id: string;
id: number;
prefix?: string | null;
updatedAt: string;
createdAt: string;
@@ -176,7 +176,7 @@ export interface MediaWithPrefix {
* via the `definition` "users".
*/
export interface User {
id: string;
id: number;
updatedAt: string;
createdAt: string;
email: string;
@@ -186,6 +186,13 @@ export interface User {
hash?: string | null;
loginAttempts?: number | null;
lockUntil?: string | null;
sessions?:
| {
id: string;
createdAt?: string | null;
expiresAt: string;
}[]
| null;
password?: string | null;
}
/**
@@ -193,24 +200,24 @@ export interface User {
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: string;
id: number;
document?:
| ({
relationTo: 'media';
value: string | Media;
value: number | Media;
} | null)
| ({
relationTo: 'media-with-prefix';
value: string | MediaWithPrefix;
value: number | MediaWithPrefix;
} | null)
| ({
relationTo: 'users';
value: string | User;
value: number | User;
} | null);
globalSlug?: string | null;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
updatedAt: string;
createdAt: string;
@@ -220,10 +227,10 @@ export interface PayloadLockedDocument {
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: string;
id: number;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
key?: string | null;
value?:
@@ -243,7 +250,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: string;
id: number;
name?: string | null;
batch?: number | null;
updatedAt: string;
@@ -323,6 +330,13 @@ export interface UsersSelect<T extends boolean = true> {
hash?: T;
loginAttempts?: T;
lockUntil?: T;
sessions?:
| T
| {
id?: T;
createdAt?: T;
expiresAt?: T;
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema

View File

@@ -3,6 +3,9 @@ import type { CollectionConfig } from 'payload'
export const Media: CollectionConfig = {
slug: 'media',
upload: {
modifyResponseHeaders({ headers }) {
headers.set('X-Universal-Truth', 'Set')
},
disableLocalStorage: true,
resizeOptions: {
position: 'center',

View File

@@ -3,6 +3,9 @@ import type { CollectionConfig } from 'payload'
export const Media: CollectionConfig = {
slug: 'media',
upload: {
modifyResponseHeaders({ headers }) {
headers.set('X-Universal-Truth', 'Set')
},
disableLocalStorage: true,
resizeOptions: {
position: 'center',

View File

@@ -3,6 +3,9 @@ import type { CollectionConfig } from 'payload'
export const Media: CollectionConfig = {
slug: 'media',
upload: {
modifyResponseHeaders({ headers }) {
headers.set('X-Universal-Truth', 'Set')
},
disableLocalStorage: true,
resizeOptions: {
position: 'center',

View File

@@ -84,7 +84,7 @@ export interface Config {
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
db: {
defaultIDType: string;
defaultIDType: number;
};
globals: {};
globalsSelect: {};
@@ -120,7 +120,7 @@ export interface UserAuthOperations {
* via the `definition` "media".
*/
export interface Media {
id: string;
id: number;
alt?: string | null;
_key?: string | null;
updatedAt: string;
@@ -160,7 +160,7 @@ export interface Media {
* via the `definition` "media-with-prefix".
*/
export interface MediaWithPrefix {
id: string;
id: number;
updatedAt: string;
createdAt: string;
url?: string | null;
@@ -178,7 +178,7 @@ export interface MediaWithPrefix {
* via the `definition` "users".
*/
export interface User {
id: string;
id: number;
updatedAt: string;
createdAt: string;
email: string;
@@ -188,6 +188,13 @@ export interface User {
hash?: string | null;
loginAttempts?: number | null;
lockUntil?: string | null;
sessions?:
| {
id: string;
createdAt?: string | null;
expiresAt: string;
}[]
| null;
password?: string | null;
}
/**
@@ -195,24 +202,24 @@ export interface User {
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: string;
id: number;
document?:
| ({
relationTo: 'media';
value: string | Media;
value: number | Media;
} | null)
| ({
relationTo: 'media-with-prefix';
value: string | MediaWithPrefix;
value: number | MediaWithPrefix;
} | null)
| ({
relationTo: 'users';
value: string | User;
value: number | User;
} | null);
globalSlug?: string | null;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
updatedAt: string;
createdAt: string;
@@ -222,10 +229,10 @@ export interface PayloadLockedDocument {
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: string;
id: number;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
key?: string | null;
value?:
@@ -245,7 +252,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: string;
id: number;
name?: string | null;
batch?: number | null;
updatedAt: string;
@@ -327,6 +334,13 @@ export interface UsersSelect<T extends boolean = true> {
hash?: T;
loginAttempts?: T;
lockUntil?: T;
sessions?:
| T
| {
id?: T;
createdAt?: T;
expiresAt?: T;
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema

View File

@@ -3,6 +3,9 @@ import type { CollectionConfig } from 'payload'
export const Media: CollectionConfig = {
slug: 'media',
upload: {
modifyResponseHeaders({ headers }) {
headers.set('X-Universal-Truth', 'Set')
},
resizeOptions: {
position: 'center',
width: 200,

View File

@@ -84,7 +84,7 @@ export interface Config {
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
db: {
defaultIDType: string;
defaultIDType: number;
};
globals: {};
globalsSelect: {};
@@ -120,7 +120,7 @@ export interface UserAuthOperations {
* via the `definition` "media".
*/
export interface Media {
id: string;
id: number;
alt?: string | null;
updatedAt: string;
createdAt: string;
@@ -157,7 +157,8 @@ export interface Media {
* via the `definition` "media-with-prefix".
*/
export interface MediaWithPrefix {
id: string;
id: number;
prefix?: string | null;
updatedAt: string;
createdAt: string;
url?: string | null;
@@ -175,7 +176,7 @@ export interface MediaWithPrefix {
* via the `definition` "users".
*/
export interface User {
id: string;
id: number;
updatedAt: string;
createdAt: string;
email: string;
@@ -185,6 +186,13 @@ export interface User {
hash?: string | null;
loginAttempts?: number | null;
lockUntil?: string | null;
sessions?:
| {
id: string;
createdAt?: string | null;
expiresAt: string;
}[]
| null;
password?: string | null;
}
/**
@@ -192,24 +200,24 @@ export interface User {
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: string;
id: number;
document?:
| ({
relationTo: 'media';
value: string | Media;
value: number | Media;
} | null)
| ({
relationTo: 'media-with-prefix';
value: string | MediaWithPrefix;
value: number | MediaWithPrefix;
} | null)
| ({
relationTo: 'users';
value: string | User;
value: number | User;
} | null);
globalSlug?: string | null;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
updatedAt: string;
createdAt: string;
@@ -219,10 +227,10 @@ export interface PayloadLockedDocument {
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: string;
id: number;
user: {
relationTo: 'users';
value: string | User;
value: number | User;
};
key?: string | null;
value?:
@@ -242,7 +250,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: string;
id: number;
name?: string | null;
batch?: number | null;
updatedAt: string;
@@ -295,6 +303,7 @@ export interface MediaSelect<T extends boolean = true> {
* via the `definition` "media-with-prefix_select".
*/
export interface MediaWithPrefixSelect<T extends boolean = true> {
prefix?: T;
updatedAt?: T;
createdAt?: T;
url?: T;
@@ -321,6 +330,13 @@ export interface UsersSelect<T extends boolean = true> {
hash?: T;
loginAttempts?: T;
lockUntil?: T;
sessions?:
| T
| {
id?: T;
createdAt?: T;
expiresAt?: T;
};
}
/**
* This interface was referenced by `Config`'s JSON-Schema