apollo-http-client 0.3.0

HTTP client for Apollo platform
Documentation
//! `HttpClient` accepts any request body whose data is `Bytes`. Each test sends
//! a concrete body and asserts it round-trips through a local echo server.

#[macro_use]
mod common;

use apollo_http_client::HttpBody;
use axum::Router;
use axum::routing::post;
use bytes::Bytes;
use futures::stream;
use http_body::{Body, Frame};
use http_body_util::{BodyExt as _, Full, StreamBody};
use tower::{BoxError, ServiceExt as _};

use common::*;

fn echo_router() -> Router {
    Router::new().route("/", post(|body: Bytes| async move { body }))
}

/// Dispatches `body` to a fresh echo server and returns the echoed bytes.
async fn echo<B>(body: B) -> Bytes
where
    B: Body<Data = Bytes> + Send + Sync + 'static,
    B::Error: Into<BoxError> + Send + Sync + 'static,
{
    let addr = spawn_server(echo_router()).await;
    let req = http::Request::builder()
        .method(http::Method::POST)
        .uri(format!("http://{addr}/"))
        .body(body)
        .unwrap();

    let resp = new_client(&default_config())
        .oneshot(req)
        .await
        .expect("request ok");
    resp.into_body().collect().await.unwrap().to_bytes()
}

#[tokio::test]
async fn round_trips_full_body_without_boxing() {
    let echoed = echo(Full::new(Bytes::from_static(b"full body"))).await;
    assert_eq!(echoed, Bytes::from_static(b"full body"));
}

#[tokio::test]
async fn round_trips_stream_body_without_boxing() {
    let frames = vec![
        Ok::<_, std::io::Error>(Frame::data(Bytes::from_static(b"chunk-1 "))),
        Ok(Frame::data(Bytes::from_static(b"chunk-2"))),
    ];
    let echoed = echo(StreamBody::new(stream::iter(frames))).await;
    assert_eq!(echoed, Bytes::from_static(b"chunk-1 chunk-2"));
}

#[tokio::test]
async fn round_trips_boxed_body() {
    let body: HttpBody = bytes_body(Bytes::from_static(b"boxed body"));
    let echoed = echo(body).await;
    assert_eq!(echoed, Bytes::from_static(b"boxed body"));
}