a2aproject / a2aproject/a2a-rs
Corporate HTTP proxy for JSON-RPC, HTTP+JSON, and gRPC
- 主要言語
- Rust
- スター
- 75
- フォーク
- 19
- 平均マージ
- 11時間 27分
- マージ済み PR(30日)
- 21
説明
## Summary
A2A clients behind a corporate forward proxy need HTTP `CONNECT` (then origin TLS) on every non-mesh binding. **SLIMRPC already has this** via the SLIM dataplane `ProxyConfig` (explicit URL or system proxy, optional proxy TLS/auth/headers, `hyper_util` `Tunnel`). JSON-RPC, HTTP+JSON (REST), and gRPC do not expose the same capability.
Consumers cannot reach a gRPC/JSON-RPC peer through a corp proxy without reinventing CONNECT in each app.
## Current state
| Binding | Crate | Corporate HTTP proxy |
| --- | --- | --- |
| SLIMRPC | `a2a-slimrpc` + SLIM `ClientConfig.proxy` | Supported: CONNECT tunnel, then TLS to the SLIM node. See `slim_config::grpc::proxy::ProxyConfig` / `build_proxy_tunnel`. |
| JSON-RPC | `a2a-client` `JsonRpcTransport` (reqwest) | Incidental only: reqwest is built with `system-proxy`, but there is no SDK `ProxyConfig`, no documented `HTTPS_PROXY`/`NO_PROXY` contract, and no tests. |
| HTTP+JSON | `a2a-client` REST transport (reqwest) | Same as JSON-RPC. |
| gRPC | `a2a-grpc` `GrpcTransport::connect` | **Not supported.** `Endpoint::from_shared(url).connect()` has no proxy hook. The rustls path uses `connect_with_connector(tonic_tls)`, which bypasses any future tonic default CONNECT. tonic 0.14.x also has no `Endpoint::proxy_uri` / `proxy_from_env`. |
Setting `HTTPS_PROXY` therefore does not give a uniform A2A client path. gRPC is a hard gap.
## What we want
First-class proxy support on **JSON-RPC, HTTP+JSON, and gRPC**, aligned with SLIMRPC:
1. **HTTP CONNECT**, then TLS 1.3 to the **origin** (SNI = A2A host). The proxy sees dest host:port only, not A2A frames.
2. Explicit config (URL, optional proxy-hop TLS, optional proxy auth/headers) **and** env (`HTTPS_PROXY` / `NO_PROXY`), matching SLIM `ProxyConfig` (`url` empty → system proxy).
3. `NO_PROXY` must include loopback (`127.0.0.1`, `localhost`, `::1`) so local fixtures do not leave the box.
4. No TLS intercept at the proxy (no MITM, no skip-verify because a proxy is present). Origin trust stays the A2A server CA.
5. Document the contract in the crate READMEs. Proxy credentials must not be hardcoded; they belong in env/config supplied by the caller.
Suggested seam: gRPC should compose CONNECT then rustls inside `a2a-grpc` (or `GrpcTransport::from_channel` plus a documented connector helper). JSON-RPC/REST should take the same `ProxyConfig` (or wrap reqwest so `system-proxy` is explicit and testable), not a one-off in each application.
If tonic later ships `proxy_uri` / `proxy_from_env`, gRPC should call that instead of a homegrown tunnel.
## Out of scope
- SOCKS5 (different from CONNECT; some sandboxes inject `HTTPS_PROXY=socks5h://…` — do not treat that as an HTTP proxy).
- Reverse proxies / grpc-web / Envoy transcoding.
- Server-side listen (`a2a-server`); this is client dial-out only.
## Why in this repo
This is the A2A binding layer. Implementing CONNECT only in a downstream (e.g. SHADI) would leave CSIT and every other `a2a-grpc` / `a2a-client` user with the same hole. SLIMRPC already solved the dataplane hop; the HTTP bindings should match.
コントリビューションガイド
評価
この issue はまだ評価されていません。