a2aproject / a2aproject/a2a-rs

Corporate HTTP proxy for JSON-RPC, HTTP+JSON, and gRPC

オープン
#162 コメント 0 件 リアクション 0 件 担当者 1 名 @muscariello が担当を希望しています GitHub で見る
enhancement
主要言語
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 はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。