[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