use http::{HeaderValue, header::USER_AGENT};
use pretty_assertions::assert_eq;
use reqwest::Client;
use tower::ServiceBuilder;
use tower_http::ServiceBuilderExt;
use tower_http_client::client::ServiceExt as _;
use tower_reqwest::HttpClientLayer;
use wiremock::{
Mock, ResponseTemplate,
matchers::{method, path},
};
mod utils;
#[tokio::test]
async fn test_service_ext_execute() -> anyhow::Result<()> {
let (mock_server, mock_uri) = utils::start_mock_server().await;
Mock::given(method("GET"))
.and(path("/hello"))
.respond_with(ResponseTemplate::new(200))
.mount(&mock_server)
.await;
let client = ServiceBuilder::new()
.override_response_header(USER_AGENT, HeaderValue::from_static("tower-reqwest"))
.layer(HttpClientLayer)
.service(Client::new());
let response = client
.clone()
.execute(
http::request::Builder::new()
.method(http::Method::GET)
.uri(format!("{mock_uri}/hello"))
.body("")?,
)
.await?;
assert!(response.status().is_success());
assert_eq!(
response.headers().get(USER_AGENT).unwrap(),
HeaderValue::from_static("tower-reqwest")
);
Ok(())
}
#[tokio::test]
async fn test_service_ext_get() -> anyhow::Result<()> {
let (mock_server, mock_uri) = utils::start_mock_server().await;
Mock::given(method("GET"))
.and(path("/hello"))
.respond_with(ResponseTemplate::new(200))
.mount(&mock_server)
.await;
let client = ServiceBuilder::new()
.layer(HttpClientLayer)
.service(Client::new());
let response = client
.clone()
.get(format!("{mock_uri}/hello"))
.send()
.await?;
assert!(response.status().is_success());
Ok(())
}
#[tokio::test]
async fn test_service_ext_without_body() -> anyhow::Result<()> {
let (mock_server, mock_uri) = utils::start_mock_server().await;
Mock::given(method("GET"))
.and(path("/hello"))
.respond_with(ResponseTemplate::new(200))
.mount(&mock_server)
.await;
let client = ServiceBuilder::new()
.layer(HttpClientLayer)
.service(Client::new());
let response = client
.clone()
.get(format!("{mock_uri}/hello"))
.without_body()
.send()
.await?;
assert!(response.status().is_success());
Ok(())
}
#[tokio::test]
#[cfg(feature = "json")]
async fn test_service_ext_put_json() -> anyhow::Result<()> {
use http::header::CONTENT_TYPE;
use tower_http_client::client::ResponseExt as _;
use wiremock::Request;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Data {
id: String,
next: String,
}
let (mock_server, mock_uri) = utils::start_mock_server().await;
let data = Data {
id: "req-1".to_owned(),
next: "resp-1".to_owned(),
};
Mock::given(method("PUT"))
.and(path("/hello"))
.respond_with(|req: &Request| {
let value: Data = req.body_json().unwrap();
assert_eq!(value.id, "req-1");
assert_eq!(req.headers.get(CONTENT_TYPE).unwrap(), "application/json");
ResponseTemplate::new(200).set_body_json(Data {
id: value.next,
next: "wiremock-1".to_owned(),
})
})
.mount(&mock_server)
.await;
let client = ServiceBuilder::new()
.layer(HttpClientLayer)
.service(Client::new());
let response = client
.clone()
.put(format!("{mock_uri}/hello"))
.json(&data)?
.send()
.await?;
let value: Data = response.body_reader().json().await?;
assert_eq!(value.id, "resp-1");
assert_eq!(value.next, "wiremock-1");
Ok(())
}
#[tokio::test]
#[cfg(feature = "typed-header")]
async fn test_request_ext_typed_header() -> anyhow::Result<()> {
use headers::{HeaderMapExt as _, UserAgent};
use wiremock::Request;
let (mock_server, mock_uri) = utils::start_mock_server().await;
Mock::given(method("GET"))
.and(path("/hello"))
.respond_with(|req: &Request| {
assert_eq!(
req.headers.typed_get::<UserAgent>().unwrap(),
UserAgent::from_static("wiremock")
);
ResponseTemplate::new(200)
})
.mount(&mock_server)
.await;
let mut client = ServiceBuilder::new()
.layer(HttpClientLayer)
.service(Client::new());
let response = client
.get(format!("{mock_uri}/hello"))
.typed_header(UserAgent::from_static("wiremock"))
.send()
.await?;
assert!(response.status().is_success());
Ok(())
}
#[tokio::test]
#[cfg(feature = "query")]
async fn test_request_ext_query() -> anyhow::Result<()> {
use wiremock::Request;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Query {
id: &'static str,
next: &'static str,
}
let (mock_server, mock_uri) = utils::start_mock_server().await;
Mock::given(method("GET"))
.and(path("/hello"))
.respond_with(|req: &Request| {
let query = req.url.query().unwrap();
assert_eq!(query, "id=uid.1234&next=uid.1235");
ResponseTemplate::new(200)
})
.mount(&mock_server)
.await;
let mut client = ServiceBuilder::new()
.layer(HttpClientLayer)
.service(Client::new());
let response = client
.get(format!("{mock_uri}/hello"))
.query(&Query {
id: "uid.1234",
next: "uid.1235",
})?
.send()
.await?;
assert!(response.status().is_success());
Ok(())
}