You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Progenitor previously only supported the reqwest HTTP backend, which adds bundle size overhead for WASM/browser applications. The gloo-net library is specifically designed for WASM targets and leverages the browser's native Fetch API.
This means we get smaller bundle sizes, better integration with browser APIs (WebSocket, streaming, etc.), and the native browser behavior for connection pooling, timeouts, and TLS. This change adds first-class support for gloo-net as an alternative HTTP backend.
progenitor-impl: Added HttpBackend enum (Reqwest | Gloo) to represent backend choice throughout code generation
progenitor-client: Implemented gloo_impl.rs with feature parity to reqwest_impl.rs:
Error handling with Error<E> enum
ResponseValue<T> wrapper for responses with status/headers
ByteStream support via wasm_streams for streaming responses
WebSocket support using web_sys::WebSocket directly, rather than HTTP upgrade (since browsers don't expose WebSocket as an HTTP upgrade)
Shared code extracted to shared.rs for both backends
cargo-progenitor: Added --backend CLI flag (defaults to reqwest) to generate backend-specific code and dependencies
Added backend parameter to generate_api! macro
build.rs: Added with_backend() method to GenerationSettings
example-wasm/ was updated to demonstrate gloo backend usage with HttpBackend::Gloo in build.rs
Design Decisions
I chose to separate out reqwest-client and gloo-client into mutually exclusive features, for the following reasons:
Different dependency sets (reqwest vs gloo-net/web-sys), including some existing dependencies that need to have optional features enabled
Different error types (reqwest::Error vs String/serde_json::Error)
progenitor-client/src/lib.rs enforces this with compile-time errors. To avoid the same error, example-wasm is excluded from the workspace: it depends on progenitor-client with gloo-client, whereas cargo-progenitor depends on progenitor-client with reqwest-client.
I also also chose not to support --backend gloo with the --include-client flag, which is supposed to inline progenitor-client code. It's theoretically possible, but I realized the following:
The Gloo backend requires WASM-specific dependencies (wasm-bindgen, web-sys, js-sys) that we'd have to enable
For other dependencies, we also have to enable specific features for WASM support
The file merging becomes fragile because we have to filter out some of the duplicated use statements
People targeting wasm32-unknown-unknown usually have some form of more complex build process using tools like wasm-pack or trunk anyway
Instead it returns an error message directing users to use the dependency instead.
The backends use different customization mechanisms reflecting their underlying architectures.
reqwest does something like Client::new_with_client(url, reqwest::Client), and all configuration happens at construction time. gloo-net uses the ClientHooks trait with the pre() and post() hooks, which allow per-request customization of the Fetch API RequestInit options.
Usage
For WASM applications wanting to use the gloo backend:
# Cargo.toml
[dependencies]
progenitor-client = { version = "0.11", features = ["gloo-client"] }
// build.rsletmut generator = progenitor::Generator::new(
progenitor::GenerationSettings::default().with_backend(progenitor::HttpBackend::Gloo),);// or with the macro:
progenitor::generate_api!(
spec = "path/to/spec.json",
backend = Gloo,);
I haven't taken a thorough look, but on first glance this looks like quite a lot of complexity that isn't particularly of use to us at Oxide. I'd like to propose an alternative approach to see if it might enable what you're building:
I don't think reqwest is doing much for us at this point. We chose it early in the life of progenitor, but over time it became clear that was was very convenient for building hand-written clients was unnecessary complexity for generated clients. We're contemplated a more flexible approach: rather than assuming reqwest, define a HttpClient trait and generate against that. We could implement this trait for a reqwest::Client (or whatever) and allow for other implementations such as gloo or a lower-level hyper-based client.
I haven't taken a thorough look, but on first glance this looks like quite a lot of complexity that isn't particularly of use to us at Oxide. I'd like to propose an alternative approach to see if it might enable what you're building:
I don't think reqwest is doing much for us at this point. We chose it early in the life of progenitor, but over time it became clear that was was very convenient for building hand-written clients was unnecessary complexity for generated clients. We're contemplated a more flexible approach: rather than assuming reqwest, define a HttpClient trait and generate against that. We could implement this trait for a reqwest::Client (or whatever) and allow for other implementations such as gloo or a lower-level hyper-based client.
If you're interested in working on this approach, I'd suggest we first define a trait, then create an implementation for reqwest and then modify generation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Progenitor previously only supported the
reqwestHTTP backend, which adds bundle size overhead for WASM/browser applications. Thegloo-netlibrary is specifically designed for WASM targets and leverages the browser's native Fetch API.This means we get smaller bundle sizes, better integration with browser APIs (WebSocket, streaming, etc.), and the native browser behavior for connection pooling, timeouts, and TLS. This change adds first-class support for
gloo-netas an alternative HTTP backend.progenitor-impl: AddedHttpBackendenum (Reqwest|Gloo) to represent backend choice throughout code generationprogenitor-client: Implementedgloo_impl.rswith feature parity toreqwest_impl.rs:Error<E>enumResponseValue<T>wrapper for responses with status/headersByteStreamsupport viawasm_streamsfor streaming responsesweb_sys::WebSocketdirectly, rather than HTTP upgrade (since browsers don't exposeWebSocketas an HTTP upgrade)shared.rsfor both backendscargo-progenitor: Added--backendCLI flag (defaults toreqwest) to generate backend-specific code and dependenciesbackendparameter togenerate_api!macrobuild.rs: Addedwith_backend()method toGenerationSettingsexample-wasm/was updated to demonstrate gloo backend usage withHttpBackend::Glooinbuild.rsDesign Decisions
reqwest-clientandgloo-clientinto mutually exclusive features, for the following reasons:reqwestvsgloo-net/web-sys), including some existing dependencies that need to have optional features enabledreqwest::ErrorvsString/serde_json::Error)progenitor-client/src/lib.rsenforces this with compile-time errors. To avoid the same error,example-wasmis excluded from the workspace: it depends onprogenitor-clientwithgloo-client, whereascargo-progenitordepends onprogenitor-clientwithreqwest-client.--backend gloowith the--include-clientflag, which is supposed to inlineprogenitor-clientcode. It's theoretically possible, but I realized the following:wasm-bindgen,web-sys,js-sys) that we'd have to enableusestatementswasm32-unknown-unknownusually have some form of more complex build process using tools likewasm-packortrunkanywayInstead it returns an error message directing users to use the dependency instead.
reqwestdoes something likeClient::new_with_client(url, reqwest::Client), and all configuration happens at construction time.gloo-netuses theClientHookstrait with thepre()andpost()hooks, which allow per-request customization of the Fetch APIRequestInitoptions.Usage
For WASM applications wanting to use the gloo backend: