Skip to main content

Crate unitycatalog_storage_proxy

Crate unitycatalog_storage_proxy 

Source
Expand description

Same-origin Unity Catalog storage byte-proxy.

A browser/wasm query engine points a stock object_store::http::HttpStore at this proxy instead of reaching cloud object storage directly. The proxy authorizes the request, vends a scoped credential, and streams object bytes (read + write) to/from storage server-side. Because the wasm side never speaks a cloud-native protocol (SigV4 / Azure SAS / GCS auth) this makes S3/GCP work on wasm for free and removes the per-cloud CORS configuration burden — the browser only ever talks to its own origin.

The crate owns the proxy semantics behind a narrow port: the wire contract (ranged GET / HEAD / whole-object PUT with a server-enforced If-Match), the streaming HTTP mapping, and the confused-deputy path-scope guard. Any server serves the identical surface by implementing StorageProxyBackend over its own storage, credential vending, and authorization.

§Wire contract

GET  {base}/{securable}/{key}            -> 200 + body + Content-Length + ETag
GET  {base}/{securable}/{key}  Range: .. -> 206 + Content-Range (+ Accept-Ranges)
HEAD {base}/{securable}/{key}            -> headers only
PUT  {base}/{securable}/{key}  [body]    -> 200 + ETag   (whole-object upload)

{securable} is a single typed path segment — table:<fqn>, vol:<fqn>, or path:<percent-encoded cloud URL> (see Securable) — and {key} is the object key relative to that securable’s root. GET/HEAD open a read-scoped store; PUT opens a write-scoped store. A conditional write rides an If-Match HTTP header the proxy relays to storage, mapping a mismatch to 412 Precondition Failed.

§Example

Implement StorageProxyBackend over your own storage, then mount it with router_with_context. Here the in-memory backend from the testing feature stands in for a real one:

use std::sync::Arc;
use unitycatalog_storage_proxy::{ContextExtractor, router_with_context_at};
use unitycatalog_storage_proxy::testing::InMemoryStorageProxyBackend;

let backend = InMemoryStorageProxyBackend::table("main.default.events");
let extract_cx: ContextExtractor<()> = Arc::new(|_parts| Box::pin(async { Ok(()) }));
// `base = ""` yields relative routes; a host adds the `/storage-proxy` prefix
// via `.nest`. Pass `"/storage-proxy"` instead to `.merge` the surface directly.
let proxy: axum::Router = router_with_context_at("", Arc::new(backend), extract_cx);

Re-exports§

pub use auth::AuthLayer;bin
pub use auth::AuthMode;bin
pub use auth::ForwardedIdentity;bin
pub use backend::ForwardedUser;server
pub use backend::ProxyCapabilities;server
pub use backend::ProxyReq;server
pub use backend::ProxyVerb;server
pub use backend::Securable;server
pub use backend::StorageProxyBackend;server
pub use client::UnityFactoryProxyBackend;client-arm
pub use error::ProxyError;server
pub use error::ProxyResult;server
pub use handler::StorageProxyHandler;server
pub use router::ContextExtractor;server
pub use router::router_from_extension;server
pub use router::router_from_extension_at;server
pub use router::router_with_context;server
pub use router::router_with_context_at;server

Modules§

authbin
Self-contained request authentication for the standalone storage-proxy binary.
backendserver
The StorageProxyBackend port and its request vocabulary.
clibin
CLI surface for the standalone storage-proxy binary.
clientclient-arm
The portable client arm: a StorageProxyBackend backed by a UnityObjectStoreFactory.
configserver
The storageAccess capability helper.
errorserver
The storage-proxy error contract, decoupled from any server’s internal error.
handlerserver
The streaming HTTP handler: a blanket StorageProxyHandler over any StorageProxyBackend.
routerserver
Axum router for the storage byte-proxy (/storage-proxy/{securable}/{*key}).
testingtesting
An in-memory StorageProxyBackend for exercising the wire contract without a cloud.