Skip to content

Conversation

@Aditya1404Sal
Copy link
Contributor

@Aditya1404Sal Aditya1404Sal commented Nov 5, 2025

Feature or Problem

This PR adds modular transport protocol support to the HTTP server plugin, with gRPC client support as the first implementation. The new architecture allows WebAssembly components to make outgoing requests using different transport protocols (HTTP/1.1, HTTP/2, gRPC, etc.) through a pluggable handler system.

Key Changes:

  1. New OutgoingHandler trait - Extensible interface for adding transport protocols
  2. CompositeOutgoingHandler - Chain-of-responsibility pattern for automatic protocol routing
  3. gRPC client support - HTTP/2-based gRPC transport with TLS and h2c (cleartext) support
  4. Clean separation of concerns - Transport configuration lives with HttpServer, not HostBuilder

Components can now make gRPC calls using the wasmcloud-grpc-client helper crate, and the runtime automatically routes requests to the appropriate transport based on headers and URI schemes.

Related Issues

Closes #112

Release Information

Target: next release

Architecture

Usage Example:

// Basic HTTP server (http support included in default behavior, no changes needed)
let http_server = HttpServer::new(router, addr);

let host = HostBuilder::new()
    .with_http_handler(Arc::new(http_server))
    .build()?;

Handler Chain:

Outgoing Request → CompositeOutgoingHandler
                   ├─ GrpcHandler (checks content-type: application/grpc)
                   ├─ [Future: WebSocketHandler, custom protocols, etc.]
                   └─ DefaultHttpHandler (fallback)

Consumer Impact

No Breaking Changes:

  • All changes are additive - existing code continues to work
  • Existing http/1.1 requests are routed normally
  • No changes required for components that don't use gRPC

Future Extensibility:

This architecture makes it trivial to add new transport protocols without modifying core structures:

// Example: Adding WebSocket support in the future
let outgoing = CompositeOutgoingHandler::new()
    .with_grpc(grpc_config)?
    .with_handler(Arc::new(WebSocketHandler::new(ws_config)));

Testing

Unit Tests

Integration Tests

Added three comprehensive integration tests using a test gRPC server and example component (grpc_hello_world.wasm):

  1. test_grpc_client_basic

    • Starts test gRPC server (Tonic-based Greeter service)
    • Starts host with gRPC client support
    • Component makes HTTP request → internally calls gRPC service
    • Verifies HTTP/2 protocol enforcement
    • Validates proper content-type: application/grpc header handling
    • Confirms cleartext HTTP/2 (h2c) connections work
  2. test_grpc_client_concurrent

    • Tests 5 concurrent gRPC calls
    • Verifies connection pooling works correctly
    • Ensures no race conditions in handler routing
  3. test_grpc_client_error_handling

    • Tests connection to non-existent gRPC server
    • Verifies graceful error handling
    • Confirms appropriate HTTP 500 responses

Manual Verification

Local Test Execution:

# Run all gRPC tests
cargo test --package wash-runtime --test integration_grpc_client --features grpc --  --nocapture

# Run specific tests
cargo test --package wash-runtime --test integration_grpc_client --features grpc -- test_grpc_client_basic --exact --nocapture
cargo test --package wash-runtime --test integration_grpc_client --features grpc -- test_grpc_client_concurrent  --exact --nocapture
cargo test --package wash-runtime --test integration_grpc_client --features grpc -- test_grpc_client_error_handling --exact --nocapture

Result: ✅ All tests pass successfully

Test Output Verification:

✓ gRPC server starts and accepts connections
✓ Component receives HTTP requests  
✓ Component makes gRPC calls to test server
✓ HTTP/2 protocol enforced for gRPC
✓ Content-Type headers handled correctly
✓ gRPC server processes requests successfully
✓ Component returns gRPC responses via HTTP
✓ Concurrent requests handled correctly
✓ Error cases fail gracefully

Benefits

  1. Modularity: Transport protocols are isolated and composable
  2. Extensibility: Add new protocols without modifying HttpServer or HostBuilder
  3. Type Safety: Compile-time guarantees for transport configuration
  4. Testability: Easy to inject mock transports for testing
  5. Performance: Negligible overhead (~50-200ns per request for routing)
  6. Backward Compatibility: Existing HTTP-only code works unchanged
  7. Clear Ownership: Each layer has a single responsibility

Future Work

This architecture enables future protocol support with minimal changes:

  • WebSocket transport
  • HTTP/3 (QUIC)
  • Custom internal protocols (e.g., internal://service-name)
  • Protocol-specific optimizations (connection pooling, multiplexing, etc.)

Each new protocol only requires implementing the OutgoingHandler trait so no changes to core infrastructure needed.

@Aditya1404Sal Aditya1404Sal changed the title WIP[feat: Add wasi-http-client with http/1.1 & http/2 support] feat: Add wasi-http-client and wasi-gRPC-client Hostplugin Nov 10, 2025
@Aditya1404Sal Aditya1404Sal force-pushed the http2_support branch 2 times, most recently from 64f4708 to 2018879 Compare November 10, 2025 14:23
@Aditya1404Sal Aditya1404Sal marked this pull request as ready for review November 10, 2025 14:23
@Aditya1404Sal Aditya1404Sal requested a review from a team as a code owner November 10, 2025 14:23
@Aditya1404Sal Aditya1404Sal force-pushed the http2_support branch 5 times, most recently from 2932621 to c68d37a Compare November 10, 2025 21:22
@Aditya1404Sal
Copy link
Contributor Author

Aditya1404Sal commented Nov 11, 2025

Hey @lxfontes @ricochet this PR is ready for a review!
also a question, how do we go along integrating this repository ? https://github.com/Aditya1404Sal/wasmcloud-grpc-client

&mut self.http
}

fn send_request(
Copy link
Member

Choose a reason for hiding this comment

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

Some nuances in this plugin selection code:
It expects/forces crate::plugin::wasi_grpc_client::GrpcClient or crate::plugin::wasi_http_client::HttpClient, which is not the expectation to downstream consumers ( ex: wash host ).
It relies on specific plugin names ( "grpc-client" ).

We need a bit more surgery to get this cleanly, specifically around HostPlugin trait and Ctx structure so we can walk thru bound plugins & get their http client.

With that, the logic in here would move to wasi_http plugin itself instead of split between 2 plugins.

Let me address this HostPlugin / Ctx situation in a PR and get back to you here.

Copy link
Member

Choose a reason for hiding this comment

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

getting the code up in #156
I've left comments where the HTTP / GRPC logic would come in.
should be done with it on monday

Mees-Molenaar added a commit to bettyblocks/wash that referenced this pull request Nov 20, 2025
Mees-Molenaar added a commit to bettyblocks/wash that referenced this pull request Nov 20, 2025
Mees-Molenaar added a commit to bettyblocks/wash that referenced this pull request Nov 20, 2025
Mees-Molenaar added a commit to bettyblocks/wash that referenced this pull request Nov 20, 2025
@Aditya1404Sal Aditya1404Sal changed the title feat: Add wasi-http-client and wasi-gRPC-client Hostplugin feat: Add gRPC-client support in runtime to allow outbound gRPC calls Nov 24, 2025
@Aditya1404Sal Aditya1404Sal changed the title feat: Add gRPC-client support in runtime to allow outbound gRPC calls feat: Add gRPC-client support in Host to allow outbound gRPC calls Nov 24, 2025
@Aditya1404Sal Aditya1404Sal changed the title feat: Add gRPC-client support in Host to allow outbound gRPC calls feat(Host): Add gRPC-client support in Host to allow outbound gRPC calls Nov 24, 2025
@Aditya1404Sal Aditya1404Sal changed the title feat(Host): Add gRPC-client support in Host to allow outbound gRPC calls feat(host): Introduce modular outbound transport system with initial gRPC client support Nov 25, 2025
@Aditya1404Sal Aditya1404Sal force-pushed the http2_support branch 2 times, most recently from 80a531d to a8151cb Compare November 25, 2025 09:23
wasmcloud_component::http::Response<impl wasmcloud_component::http::OutgoingBody>,
> {
// Use tokio to run the async code in a blocking context
let runtime = tokio::runtime::Builder::new_current_thread()

Choose a reason for hiding this comment

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

does it make sense to use tokio? or maybe use wit_bindgen block_on?

wasmcloud_component::http::Response<impl wasmcloud_component::http::OutgoingBody>,
> {
// Use tokio to run the async code in a blocking context
let runtime = tokio::runtime::Builder::new_current_thread()

Choose a reason for hiding this comment

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

does it make sense to use tokio? or maybe use wit_bindgen block_on?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sadly the wit_bindgen::block_on() does get our component to compile, It fails to run :( I'll ask around if this is expected behaviour or not but definitely worth the look, we should stick to using tokio here since I couldn't find other ways to bridge the sync-async of incoming-handler and the gRPC invocations (which are async).

Mees-Molenaar added a commit to bettyblocks/wash that referenced this pull request Dec 2, 2025
@Aditya1404Sal Aditya1404Sal force-pushed the http2_support branch 2 times, most recently from 32ec2c8 to 9015338 Compare December 8, 2025 15:30
@Aditya1404Sal
Copy link
Contributor Author

Hey @lxfontes, cc linking keeps flaking for the wash ubuntu workflow, what can be done ?
Also this PR is ready for a review!

@lxfontes lxfontes moved this to Discuss in wash v2 release Jan 7, 2026
@lxfontes lxfontes moved this from Discuss to Todo in wash v2 release Jan 7, 2026
@Aditya1404Sal Aditya1404Sal force-pushed the http2_support branch 2 times, most recently from bdb51bf to 654c89d Compare January 8, 2026 10:47
@Aditya1404Sal Aditya1404Sal changed the title feat(host): Introduce modular outbound transport system with initial gRPC client support feat(host): Introduce outbound transport system with initial gRPC client support Jan 8, 2026
@Aditya1404Sal
Copy link
Contributor Author

@lxfontes I've revamped the outgoing handler, it's no longer modular and now added as default in the HttpServer, this PR is good for a review!!

…itial gRPC client support

- Add `OutgoingHandler` trait to enable pluggable transport protocols
- Implement `CompositeOutgoingHandler` for automatic protocol routing
- Add gRPC client handler with HTTP/2, TLS, and h2c support
- Move transport configuration ownership to `HttpServer`
- Ensure full backward compatibility for existing HTTP-only hosts

Signed-off-by: Aditya <aditya.salunkh919@gmail.com>
Signed-off-by: Aditya <aditya.salunkh919@gmail.com>
…hanisms default

Signed-off-by: Aditya <aditya.salunkh919@gmail.com>
@Aditya1404Sal
Copy link
Contributor Author

CC @lxfontes

@lxfontes lxfontes moved this from Todo to In Progress in wash v2 release Jan 21, 2026
@Aditya1404Sal
Copy link
Contributor Author

Aditya1404Sal commented Jan 21, 2026

it seems the build error originated because of a conflicting dependency caused due to wasmtime-wasi getting pointed to wash-wasi package instead of upstream (which was added with the virtual tcp lookback PR)

…om wash-wasi

Signed-off-by: Aditya <aditya.salunkh919@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

[FEAT] HTTP Client Plugin

3 participants