exec-server/src/client/rpc_http_client.rs
88 lines
//! JSON-RPC-backed `HttpClient` implementation.//!//! This code runs in the orchestrator process. It does not issue network//! requests directly; instead it forwards `http/request` to the remote runtime//! and then reconstructs streamed bodies from `http/request/bodyDelta`//! notifications on the shared connection.use std::sync::Arc;use futures::FutureExt;use futures::future::BoxFuture;use tokio::sync::mpsc;use super::HttpResponseBodyStream;use super::response_body_stream::HttpBodyStreamRegistration;use crate::HttpClient;use crate::client::ExecServerClient;use crate::client::ExecServerError;use crate::protocol::HTTP_REQUEST_METHOD;use crate::protocol::HttpRequestParams;use crate::protocol::HttpRequestResponse;/// Maximum queued body frames per streamed HTTP response.const HTTP_BODY_DELTA_CHANNEL_CAPACITY: usize = 256;impl ExecServerClient { /// Performs an HTTP request and buffers the response body. pub async fn http_request( &self, mut params: HttpRequestParams, ) -> Result<HttpRequestResponse, ExecServerError> { params.stream_response = false; self.call(HTTP_REQUEST_METHOD, ¶ms).await } /// Performs an HTTP request and returns a body stream. /// /// The method sets `stream_response` and replaces any caller-supplied /// `request_id` with a connection-local id, so late deltas from abandoned /// streams cannot be confused with later requests. pub async fn http_request_stream( &self, mut params: HttpRequestParams, ) -> Result<(HttpRequestResponse, HttpResponseBodyStream), ExecServerError> { params.stream_response = true; let request_id = self.inner.next_http_body_stream_request_id(); params.request_id = request_id.clone(); let (tx, rx) = mpsc::channel(HTTP_BODY_DELTA_CHANNEL_CAPACITY); self.inner .insert_http_body_stream(request_id.clone(), tx) .await?; let mut registration = HttpBodyStreamRegistration::new(Arc::clone(&self.inner), request_id.clone()); let response = match self.call(HTTP_REQUEST_METHOD, ¶ms).await { Ok(response) => response, Err(error) => { self.inner.remove_http_body_stream(&request_id).await; registration.disarm(); return Err(error); } }; registration.disarm(); Ok(( response, HttpResponseBodyStream::remote(Arc::clone(&self.inner), request_id, rx), )) }}impl HttpClient for ExecServerClient { /// Orchestrator-side adapter that forwards buffered HTTP requests to the /// remote runtime over the shared JSON-RPC connection. fn http_request( &self, params: HttpRequestParams, ) -> BoxFuture<'_, Result<HttpRequestResponse, ExecServerError>> { async move { ExecServerClient::http_request(self, params).await }.boxed() } /// Orchestrator-side adapter that forwards streamed HTTP requests to the /// remote runtime and exposes body deltas as a byte stream. fn http_request_stream( &self, params: HttpRequestParams, ) -> BoxFuture<'_, Result<(HttpRequestResponse, HttpResponseBodyStream), ExecServerError>> { async move { ExecServerClient::http_request_stream(self, params).await }.boxed() }}