payloadcms/payload

collection.upload handlers - mismatch between docs and implementation

Closed this issue · 2 comments

Link to reproduction

No response

Describe the Bug

When setting an upload collection handlers array, all handlers are run and the last result is effective. This contradicts docs and results in redundant handler runs.

Docs:

"If a handler returns a Response, the response will be sent to the client and no further handlers will be run. "

/**
* Custom handlers to run when a file is fetched.
*
* - If a handler returns a Response, the response will be sent to the client and no further handlers will be run.
* - If a handler returns null, the next handler will be run.
* - If no handlers return a response the file will be returned by default.
*
* @default undefined
*/
handlers?: ((
req: PayloadRequest,
args: {
doc: TypeWithID
params: { clientUploadContext?: unknown; collection: string; filename: string }
},
) => Promise<Response> | Promise<void> | Response | void)[]

Implementation:

if (collection.config.upload.handlers?.length) {
let customResponse = null
for (const handler of collection.config.upload.handlers) {
customResponse = await handler(req, {
doc: accessResult,
params: {
collection: collection.config.slug,
filename,
},
})
}
if (customResponse instanceof Response) {
return customResponse
}
}

To Reproduce

  1. You can clone this repo and skip steps 1+2: https://github.com/OrenSayag/poc-payload-upload-handlers

  2. pnpm dlx create-payload-app poc-upload-handlers-bug

  3. Edit Media collection:

import type { CollectionConfig } from 'payload'

export const Media: CollectionConfig = {
    slug: 'media',
    access: {
        read: () => true,
    },
    fields: [
        {
            name: 'alt',
            type: 'text',
            required: true,
        },
    ],
    upload: {
        handlers: [
            async () => {
                await new Promise((resolve) => setTimeout(resolve, 3_000))
                console.log(`File processed after 3 seconds`)
                return Response.json({ message: 'File processed after 3 seconds' })
            },

            async () => {
                await new Promise((resolve) => setTimeout(resolve, 5_000))
                console.log(`File processed after 5 seconds`)
                return Response.json({ message: 'File processed after 8 seconds' })
            },
        ],
    },
}
  1. Upload a file using UI
  2. Click on its name to open in a new tab, the static route
Image
  1. Notice the response is served after 8 seconds,
    and in console logs:

File processed after 3 seconds
File processed after 5 seconds
GET /api/media/file/android-chrome-192x192.png 200 in 8037ms

Payload Version

3.55.0

Adapters and Plugins

No response

🚀 This is included in version v3.57.0

This issue has been automatically locked.
Please open a new issue if this issue persists with any additional detail.