Skip to content

refactor: simplify CF#18

Merged
alukach merged 14 commits intomainfrom
refactor/simplify-api
Mar 18, 2026
Merged

refactor: simplify CF#18
alukach merged 14 commits intomainfrom
refactor/simplify-api

Conversation

@alukach
Copy link
Member

@alukach alukach commented Mar 18, 2026

Push common Cloudflare Workers tooling into a multistore-cf-workers crate

alukach and others added 14 commits March 17, 2026 13:12
S3's ListObjectsV2 has no default delimiter — omitting it returns a flat
list of all matching objects. Multistore was defaulting to "/" which
caused grouped responses (with CommonPrefixes) even when clients didn't
request grouping.

- Default delimiter to empty string instead of "/"
- Pass None to PaginatedListOptions when delimiter is empty
- Skip serializing <Delimiter> element in XML when empty

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
UnsignedUrlSigner::from_config was S3-centric, reading only
"endpoint" and "bucket_name" options. For Azure backends, this
produced incorrect URLs like https://s3.amazonaws.com/<key>
instead of https://<account>.blob.core.windows.net/<container>/<key>.

Dispatch on parsed_backend_type to construct the correct
endpoint and bucket/container for each provider.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `ResponseBody` associated type and `forward` method to the
`ProxyBackend` trait, removing the standalone `Forwarder` trait.
`ForwardResponse` and `ForwardRequest` types remain accessible via
the `forwarder` module. Downstream code will be updated in follow-up
tasks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ProxyBackend now owns forwarding (via forward() + ResponseBody), so
ProxyGateway no longer needs a separate F type parameter. This removes
the forwarder field, updates handle_request to use B::ResponseBody,
replaces self.forwarder.forward() with self.backend.forward(), and
merges MockForwarder into MockBackend in tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move forward() and ResponseBody from separate Forwarder structs into each
runtime's ProxyBackend impl. Remove ServerForwarder, LambdaForwarder, and
WorkerForwarder. Update ProxyGateway construction to use 3 type params.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ForwardResponse now lives in backend::mod alongside ProxyBackend that
uses it.  The standalone forwarder.rs (which only held ForwardResponse
and a re-export after the Forwarder trait was merged into ProxyBackend)
is deleted and all imports are updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract generic Cloudflare Workers runtime adapters from the cf-workers
example into a proper library crate at crates/cf-workers/. This allows
other CF Workers deployments (like data.source.coop) to depend on shared
implementations without copy-pasting.

Modules:
- fetch_connector: HttpConnector for object_store using Workers Fetch API
- body: JsBody zero-copy ReadableStream wrapper + collect helper
- backend: WorkerBackend implementing ProxyBackend via Fetch API
- tracing_layer: WorkerSubscriber routing tracing to console.log
- response: web_sys::Response builders and header conversion helpers
- noop_creds: NoopCredentialRegistry for anonymous-only deployments

Also renames the example package to multistore-cf-workers-example to
avoid the workspace name conflict.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow bucket registries to specify an optional display name that is
used in the <Name> element of ListBucketResult XML responses instead
of the backend bucket name. This enables virtual bucket naming where
the client-facing name differs from the underlying storage bucket.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace inline WorkerBackend, FetchConnector, JsBody, WorkerSubscriber,
and response helper implementations in the example with imports from the
multistore-cf-workers crate. Remove client.rs, fetch_connector.rs, and
tracing_layer.rs which are now provided by the crate. Keep application-
specific code (OIDC wiring, rate limiting, bandwidth metering).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracts the URL-path-to-bucket-name mapping logic into a reusable crate.
PathMapping translates hierarchical paths like /{account}/{product}/{key}
into flat bucket names like account--product, and MappedRegistry wraps any
BucketRegistry to apply display_name and ListRewrite automatically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Forward azure and gcp features to multistore core so the
WorkerBackend's create_paginated_store handles all provider builders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ash in rewrite_key

The top-level <Prefix> element in ListBucketResult XML was not
including the add_prefix from ListRewrite, causing incorrect
responses for prefix-routed list requests. Also fixed rewrite_key
to avoid double-slashes when add_prefix already ends with '/'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

🚀 Latest commit deployed to https://multistore-proxy-pr-18.development-seed.workers.dev

  • Date: 2026-03-18T19:50:42Z
  • Commit: 4088261

@alukach alukach marked this pull request as ready for review March 18, 2026 20:12
@alukach alukach merged commit e0796e2 into main Mar 18, 2026
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant