[wp-trac] [WordPress Trac] #64804: REST API: Add finalize endpoint to `WP_REST_Attachments_Controller` for client-side media processing

WordPress Trac noreply at wordpress.org
Thu Mar 5 17:50:16 UTC 2026


#64804: REST API: Add finalize endpoint to `WP_REST_Attachments_Controller` for
client-side media processing
--------------------------------------+---------------------
 Reporter:  adamsilverstein           |       Owner:  (none)
     Type:  defect (bug)              |      Status:  new
 Priority:  normal                    |   Milestone:  7.0
Component:  REST API                  |     Version:  trunk
 Severity:  normal                    |  Resolution:
 Keywords:  has-patch has-unit-tests  |     Focuses:
--------------------------------------+---------------------
Description changed by westonruter:

Old description:

> When client-side media processing is active, the editor handles image
> resizing, thumbnail generation, and format conversion in the browser
> using WebAssembly. This bypasses the `wp_generate_attachment_metadata`
> filter that normally fires during `wp_generate_attachment_metadata()` in
> `wp-admin/includes/image.php`.
>
> Many plugins rely on this filter to post-process uploads — for example,
> adding watermarks, syncing to a CDN, generating custom image sizes, or
> updating external indexes. When client-side processing is active, these
> plugins silently stop working because the filter never fires.
>
> ### Proposed solution
>
> Add a `POST /wp/v2/media/{id}/finalize` REST API endpoint to
> `WP_REST_Attachments_Controller`. This endpoint:
>
> 1. Retrieves the current attachment metadata
> 2. Re-applies the `wp_generate_attachment_metadata` filter with context
> `'update'`
> 3. Saves the (potentially modified) metadata back
> 4. Returns the updated attachment object
>
> The endpoint is only registered when
> `wp_is_client_side_media_processing_enabled()` returns `true`, so it has
> zero impact on sites not using client-side processing.
>
> ### How it works
>
> The client-side media pipeline calls this endpoint after all operations
> (upload, thumbnail sideloads, scaled image sideload) are complete. No new
> hooks are needed — the existing `wp_generate_attachment_metadata` filter
> is reused. Plugins that already hook into this filter will work without
> modification; they can distinguish client-side finalization by checking
> the `$context` parameter:
>
> ```php
> add_filter( 'wp_generate_attachment_metadata', function( $metadata,
> $attachment_id, $context ) {
>     if ( 'update' === $context ) {
>         // Called from finalize endpoint after client-side processing.
>         my_plugin_process_attachment( $attachment_id, $metadata );
>     }
>     return $metadata;
> }, 10, 3 );
> ```
>
> ### Permissions
>
> The endpoint reuses `edit_media_item_permissions_check()`, consistent
> with the existing `sideload` and `edit` endpoints. A user must have
> permission to edit the attachment.
>
> ### Related
>
> - Gutenberg PR (hooks + JS pipeline):
> https://github.com/WordPress/gutenberg/pull/74913
> - Gutenberg issue: https://github.com/WordPress/gutenberg/issues/74358
> - Core PR: https://github.com/WordPress/wordpress-develop/pull/11168
> - Parent ticket (client-side media processing):
> https://core.trac.wordpress.org/ticket/62243
> - Previous Core backport PR: https://github.com/WordPress/wordpress-
> develop/pull/10868

New description:

 When client-side media processing is active, the editor handles image
 resizing, thumbnail generation, and format conversion in the browser using
 WebAssembly. This bypasses the `wp_generate_attachment_metadata` filter
 that normally fires during `wp_generate_attachment_metadata()` in `wp-
 admin/includes/image.php`.

 Many plugins rely on this filter to post-process uploads — for example,
 adding watermarks, syncing to a CDN, generating custom image sizes, or
 updating external indexes. When client-side processing is active, these
 plugins silently stop working because the filter never fires.

 === Proposed solution ===

 Add a `POST /wp/v2/media/{id}/finalize` REST API endpoint to
 `WP_REST_Attachments_Controller`. This endpoint:

 1. Retrieves the current attachment metadata
 2. Re-applies the `wp_generate_attachment_metadata` filter with context
 `'update'`
 3. Saves the (potentially modified) metadata back
 4. Returns the updated attachment object

 The endpoint is only registered when
 `wp_is_client_side_media_processing_enabled()` returns `true`, so it has
 zero impact on sites not using client-side processing.

 === How it works ===

 The client-side media pipeline calls this endpoint after all operations
 (upload, thumbnail sideloads, scaled image sideload) are complete. No new
 hooks are needed — the existing `wp_generate_attachment_metadata` filter
 is reused. Plugins that already hook into this filter will work without
 modification; they can distinguish client-side finalization by checking
 the `$context` parameter:

 {{{#!php
 <?php
 add_filter( 'wp_generate_attachment_metadata', function( $metadata,
 $attachment_id, $context ) {
     if ( 'update' === $context ) {
         // Called from finalize endpoint after client-side processing.
         my_plugin_process_attachment( $attachment_id, $metadata );
     }
     return $metadata;
 }, 10, 3 );
 }}}

 === Permissions ===

 The endpoint reuses `edit_media_item_permissions_check()`, consistent with
 the existing `sideload` and `edit` endpoints. A user must have permission
 to edit the attachment.

 === Related ===

 * Gutenberg PR (hooks + JS pipeline):
 https://github.com/WordPress/gutenberg/pull/74913
 * Gutenberg issue: https://github.com/WordPress/gutenberg/issues/74358
 * Core PR: https://github.com/WordPress/wordpress-develop/pull/11168
 * Parent ticket (client-side media processing): #62243
 * Previous Core backport PR: https://github.com/WordPress/wordpress-
 develop/pull/10868

--

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/64804#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list