apollo-http-client 0.3.0

HTTP client for Apollo platform
Documentation
use apollo_configuration::configuration;
use apollo_http_client::HttpBody;
use apollo_http_client::HttpClient;
use apollo_http_client::HttpClientConfig;
use apollo_opentelemetry::OpenTelemetryConfig;
use apollo_opentelemetry::Telemetry;
use http_body_util::BodyExt as _;
use std::time::Duration;
use tower::ServiceBuilder;
use tower::ServiceExt as _;
use tower_http::ServiceBuilderExt as _;

#[configuration]
struct Config {
    telemetry: OpenTelemetryConfig,
    client: HttpClientConfig,
}

const CONFIG: &str = r#"
    telemetry:
        # Literally just https://github.com/open-telemetry/opentelemetry-configuration/blob/main/examples/otel-getting-started.yaml
        tracer_provider:
          processors:
            - batch:
                schedule_delay: 500
                exporter:
                  otlp_http:
                    endpoint: http://localhost:4318/v1/traces

        meter_provider:
          readers:
            - periodic:
                interval: 500
                exporter:
                  otlp_http:
                    endpoint: http://localhost:4318/v1/metrics

        logger_provider:
          processors:
            - batch:
                schedule_delay: 500
                exporter:
                  otlp_http:
                    endpoint: http://localhost:4318/v1/logs
    client: {}
"#;

#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
    let config: Config = apollo_configuration::parse_yaml(CONFIG, &Default::default())?;

    let _telemetry = Telemetry::new(config.telemetry)?;

    let service = HttpClient::new(&config.client)?;

    let service = ServiceBuilder::new()
        .concurrency_limit(6)
        .timeout(Duration::from_secs(5))
        .follow_redirects()
        .service(service);

    let request = http::Request::get("https://apollographql.com/")
        .body(HttpBody::default())
        .expect("infallible");
    let response = service.oneshot(request).await?;
    if !response.status().is_success() {
        panic!("received {}", response.status());
    }

    let response = response.collect().await?.to_bytes();
    let response = String::from_utf8_lossy(&response);

    let (_, title) = response.split_once("<title>").expect("missing <title>?");
    let (title, _) = title.split_once("</title>").expect("missing </title>?");

    println!("{title}");

    Ok(())
}