Skip to content

Monark/images binding parity - #15305

Open
Monark-Arkmon wants to merge 3 commits into
cloudflare:mainfrom
Monark-Arkmon:monark/images-binding-parity
Open

Monark/images binding parity#15305
Monark-Arkmon wants to merge 3 commits into
cloudflare:mainfrom
Monark-Arkmon:monark/images-binding-parity

Conversation

@Monark-Arkmon

@Monark-Arkmon Monark-Arkmon commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Fixes IMAGES-2371, IMAGES-2381, IMAGES-2409.

Adds local dev parity for three Images binding features that already shipped in workerd/@cloudflare/workers-types: metadata filtering on list(), signedUrl(), and createDirectUpload().

  • list({ filter: { metadata } }) now filters locally using the same operators as production (eq, in, gt, gte, lt, lte), including dot-notation nested fields.
  • image(id).signedUrl() generates and verifies signed delivery URLs locally using a fixed dev-only signing secret. Images with requireSignedURLs: true now return 401 from the local delivery endpoint without a valid signature.
  • createDirectUpload() creates a draft image and returns an uploadURL served by a new local endpoint that accepts the completed upload as multipart/form-data. Matches production's expiresIn bounds and single-use/expiry behaviour.
  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: the public binding behaviour for these features is already documented; this PR only brings local dev simulation in line with it.

A picture of a cute animal (not mandatory, but encouraged)


Open in Devin Review

@github-project-automation github-project-automation Bot moved this to Untriaged in workers-sdk Aug 21, 2026
@workers-devprod
workers-devprod requested review from a team and edmundhung and removed request for a team August 21, 2026 16:17
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/images-binding-direct-upload.md: [@cloudflare/wrangler]
  • .changeset/images-binding-metadata-filter.md: [@cloudflare/wrangler]
  • .changeset/images-binding-signed-url.md: [@cloudflare/wrangler]
  • packages/miniflare/src/workers/core/constants.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/workers/core/entry.worker.ts: [@cloudflare/wrangler]
  • packages/miniflare/src/workers/images/images.worker.ts: [@cloudflare/wrangler]
  • packages/miniflare/test/plugins/images/index.spec.ts: [@cloudflare/wrangler]

@pkg-pr-new

pkg-pr-new Bot commented Aug 21, 2026

Copy link
Copy Markdown
@cloudflare/autoconfig

npm i https://pkg.pr.new/@cloudflare/autoconfig@15305

@cloudflare/build-output-utils

npm i https://pkg.pr.new/@cloudflare/build-output-utils@15305

@cloudflare/codemods

npm i https://pkg.pr.new/@cloudflare/codemods@15305

@cloudflare/config

npm i https://pkg.pr.new/@cloudflare/config@15305

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@15305

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@15305

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@15305

miniflare

npm i https://pkg.pr.new/miniflare@15305

@cloudflare/pages-functions

npm i https://pkg.pr.new/@cloudflare/pages-functions@15305

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@15305

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@15305

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@15305

@cloudflare/vitest-plugin

npm i https://pkg.pr.new/@cloudflare/vitest-plugin@15305

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@15305

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@15305

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@15305

wrangler

npm i https://pkg.pr.new/wrangler@15305

commit: f36db9f

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread packages/miniflare/src/workers/images/images.worker.ts

@edmundhung edmundhung left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few minor questions with regards to production parity.

Please get a review from your team too as we might not know the product as well as the images team. Thanks!

creator: options?.creator,
};

await this.env.IMAGES_STORE.put(id, new ArrayBuffer(0), { metadata });

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean we will serve a zero-byte image if a user tries to retrieve it while it's still a draft? Just wanna check if this matches production.

@Monark-Arkmon Monark-Arkmon Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that is correct, a draft image has no content until the upload is completed, so retrieving it before that point returns empty content in prod too. not necessarily an image but a 0 bytes response with 200 OK

requireSignedURLs: options?.requireSignedURLs ?? false,
meta: options?.metadata ?? {},
variants: ["public"],
draft: true,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to exclude draft image from .list()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, we keep it in. production includes them in list()/get() results and marks them via the draft field so callers can distinguish them

const duration = expiresIn ?? DEFAULT_DIRECT_UPLOAD_EXPIRES_IN;
if (
duration <= MIN_DIRECT_UPLOAD_EXPIRES_IN ||
duration >= MAX_DIRECT_UPLOAD_EXPIRES_IN

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it accept MIN_DIRECT_UPLOAD_EXPIRES_IN or MAX_DIRECT_UPLOAD_EXPIRES_IN as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know its a bit weird but we have it as an exclusive heck so we have to keep it like that here too 😅

const metadata: ImageMetadata = {
id,
uploaded: new Date().toISOString(),
requireSignedURLs: options?.requireSignedURLs ?? false,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the docs suggest that images with a custom ID cannot be made private with signed URL tokens (requireSignedURLs=true), but local dev accepts the combination. Should we reject it for parity?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, nice catch 😁. Yes it should be as u said, its fixed now.

@Monark-Arkmon
Monark-Arkmon force-pushed the monark/images-binding-parity branch from 67b183e to f36db9f Compare August 25, 2026 11:14
@changeset-bot

changeset-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f36db9f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
miniflare Minor
@cloudflare/deploy-helpers Patch
@cloudflare/pages-shared Patch
@cloudflare/remote-bindings Patch
@cloudflare/runtime-types Patch
@cloudflare/vite-plugin Patch
@cloudflare/vitest-plugin Patch
wrangler Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

3 participants