use crate::cert::ContentEncoding;
use crate::tests::TestResult;
use crate::{
cert::Identity,
errors::{ConnectionError, ResponseError},
request::{FetchWith, IntoRequest},
tests::helpers::client_with_cert,
};
#[cfg(test)]
use crate::{errors::DeboaError, request::DeboaRequest, response::DeboaResponse, Client};
use deboa_tests::mock_response;
use deboa_tests::utils::{start_mock_server, CA_CERT};
#[cfg(any(feature = "tokio-rust-tls", feature = "smol-rust-tls"))]
use deboa_tests::utils::{CLIENT_CERT, CLIENT_KEY};
#[cfg(any(feature = "tokio-native-tls", feature = "smol-native-tls"))]
use deboa_tests::utils::{CLIENT_CERT_PEM, CLIENT_KEY_PEM, CLIENT_P12};
use http::StatusCode;
#[cfg(feature = "smol-rt")]
use macro_rules_attribute::apply;
#[cfg(feature = "smol-rt")]
use smol_macros::test;
async fn do_get_http() -> TestResult<()> {
let mut server = start_mock_server(|req| async move {
if req.method() == "GET" && req.uri().path() == "/posts/1" {
Ok(mock_response(StatusCode::OK, "Hello World!"))
} else {
Ok(mock_response(StatusCode::NOT_FOUND, "Not found"))
}
})
.await;
let client = client_with_cert();
let request = DeboaRequest::get(server.url("/posts/1"))?.build()?;
let response: DeboaResponse = client
.execute(request)
.await?;
assert_eq!(
response.status(),
StatusCode::OK,
"Status code is {} and should be {}",
response
.status()
.as_u16(),
StatusCode::OK.as_u16()
);
server
.stop()
.await?;
Ok(())
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_get_http() -> TestResult<()> {
do_get_http().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_get_http() -> TestResult<()> {
do_get_http().await
}
async fn skip_cert_verification_helper(skip: bool) -> TestResult<()> {
let mut server = start_mock_server(|req| async move {
if req.method() == "GET" && req.uri().path() == "/posts/1" {
Ok(mock_response(StatusCode::OK, "Hello World!"))
} else {
Ok(mock_response(StatusCode::NOT_FOUND, "Not found"))
}
})
.await;
let client = Client::builder()
.skip_cert_verification(skip)
.build();
let request = DeboaRequest::get(server.url("/posts/1"))?.build()?;
let response = client
.execute(request)
.await;
if skip {
#[cfg(any(feature = "http1", feature = "http2"))]
{
let response = response?;
assert_eq!(response.status(), StatusCode::OK);
}
#[cfg(feature = "http3")]
{
let error = DeboaError::Connection(ConnectionError::Udp {
host: "localhost".to_string(),
message: "Could not connect to server: aborted by peer: the cryptographic handshake failed: error 120: peer doesn't support any known protocol".to_string(),
});
assert_eq!(response.unwrap_err(), error);
}
} else {
#[cfg(all(
any(feature = "http1", feature = "http2"),
any(feature = "tokio-rust-tls", feature = "smol-rust-tls")
))]
let error = DeboaError::Connection(ConnectionError::Tls {
host: "localhost".to_string(),
message: "Could not connect to server: invalid peer certificate: UnknownIssuer"
.to_string(),
});
#[cfg(all(feature = "http3", any(feature = "tokio-rust-tls", feature = "smol-rust-tls")))]
let error = DeboaError::Connection(ConnectionError::Udp {
host: "localhost".to_string(),
message: "Could not connect to server: the cryptographic handshake failed: error 48: invalid peer certificate: UnknownIssuer".to_string(),
});
#[cfg(any(feature = "tokio-native-tls", feature = "smol-native-tls"))]
let error = DeboaError::Connection(ConnectionError::Tls {
host: "localhost".to_string(),
message: "Could not connect to server: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:../ssl/statem/statem_clnt.c:1889: (self-signed certificate in certificate chain)".to_string(),
});
assert_eq!(response.unwrap_err(), error);
}
server
.stop()
.await?;
Ok(())
}
async fn do_get_http_skip_verification() -> TestResult<()> {
skip_cert_verification_helper(true).await
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_get_http_skip_verification() -> TestResult<()> {
do_get_http_skip_verification().await?;
Ok(())
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_get_http_skip_verification() -> TestResult<()> {
do_get_http_skip_verification().await
}
async fn do_get_http_verify() -> TestResult<()> {
skip_cert_verification_helper(false).await
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_get_http_verify() -> TestResult<()> {
do_get_http_verify().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_get_http_verify() -> TestResult<()> {
do_get_http_verify().await
}
async fn do_get_http_mutual_authentication() -> TestResult<()> {
let mut server = start_mock_server(|req| async move {
if req.method() == "GET" && req.uri().path() == "/posts/1" {
Ok(mock_response(StatusCode::OK, "Hello World!"))
} else {
Ok(mock_response(StatusCode::NOT_FOUND, "Not found"))
}
})
.await;
#[cfg(any(feature = "tokio-rust-tls", feature = "smol-rust-tls"))]
let identity = Identity::from_pkcs8(CLIENT_CERT, CLIENT_KEY, ContentEncoding::DER);
#[cfg(any(feature = "tokio-native-tls", feature = "smol-native-tls"))]
let identity = Identity::from_pkcs8(CLIENT_CERT_PEM, CLIENT_KEY_PEM, ContentEncoding::PEM);
let client = Client::builder()
.certificate(crate::cert::Certificate::from_slice(CA_CERT, ContentEncoding::DER))
.identity(identity)
.build();
let request = DeboaRequest::get(server.url("/posts/1"))?.build()?;
let response = client
.execute(request)
.await;
assert_eq!(response?.status(), StatusCode::OK);
server
.stop()
.await?;
Ok(())
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_get_http_mutual_authentication() -> TestResult<()> {
do_get_http_mutual_authentication().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_get_http_mutual_authentication() -> TestResult<()> {
do_get_http_mutual_authentication().await
}
#[cfg(any(feature = "tokio-native-tls", feature = "smol-native-tls"))]
async fn do_get_http_mutual_authentication_with_password() -> TestResult<()> {
let mut server = start_mock_server(|req| async move {
if req.method() == "GET" && req.uri().path() == "/posts/1" {
Ok(mock_response(StatusCode::OK, "Hello World!"))
} else {
Ok(mock_response(StatusCode::NOT_FOUND, "Not found"))
}
})
.await;
let identity = Identity::from_pkcs12(CLIENT_P12, Some("test".to_string()));
let client = Client::builder()
.certificate(crate::cert::Certificate::from_slice(CA_CERT, ContentEncoding::DER))
.identity(identity)
.build();
let request = DeboaRequest::get(server.url("/posts/1"))?.build()?;
let response = client
.execute(request)
.await;
assert_eq!(response?.status(), StatusCode::OK);
server
.stop()
.await?;
Ok(())
}
#[cfg(all(feature = "tokio-rt", any(feature = "tokio-native-tls", feature = "smol-native-tls")))]
#[tokio::test]
async fn test_get_http_mutual_authentication_with_password() -> TestResult<()> {
do_get_http_mutual_authentication_with_password().await
}
#[cfg(all(feature = "smol-rt", any(feature = "tokio-native-tls", feature = "smol-native-tls")))]
#[apply(test!)]
async fn test_get_http_mutual_authentication_with_password() -> TestResult<()> {
do_get_http_mutual_authentication_with_password().await
}
async fn do_get_not_found() -> TestResult<()> {
let mut server =
start_mock_server(|_| async move { Ok(mock_response(StatusCode::NOT_FOUND, "Not found")) })
.await;
let client = client_with_cert();
let response: crate::Result<DeboaResponse> =
DeboaRequest::get(server.url("/asasa/posts/1ddd"))?
.send_with(client)
.await;
assert!(response.is_err());
assert_eq!(
response.unwrap_err(),
DeboaError::Response(ResponseError::Receive {
status_code: StatusCode::NOT_FOUND,
message: "Could not process request (404 Not Found): Not found".to_string()
})
);
server
.stop()
.await?;
Ok(())
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_get_not_found() -> TestResult<()> {
do_get_not_found().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_get_not_found() -> TestResult<()> {
do_get_not_found().await
}
async fn do_get_invalid_server() -> TestResult<()> {
let api = Client::default();
let request = DeboaRequest::get("https://invalid-server.com/posts")?
.text("test")
.build()?;
let response: crate::Result<DeboaResponse> = api
.execute(request)
.await;
let error = DeboaError::Connection(ConnectionError::Tcp {
host: "invalid-server.com".to_string(),
message: "Could not resolve host: invalid-server.com.".to_string(),
});
assert!(response.is_err());
assert_eq!(response.unwrap_err(), error);
Ok(())
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_get_invalid_server() -> TestResult<()> {
do_get_invalid_server().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_get_invalid_server() -> TestResult<()> {
do_get_invalid_server().await
}
async fn do_get_by_query() -> TestResult<()> {
let mut server = start_mock_server(|req| async move {
if req.method() == "GET" && req.uri().path() == "/comments/1" {
Ok(mock_response(StatusCode::OK, "My comment"))
} else {
Ok(mock_response(StatusCode::NOT_FOUND, "Not found"))
}
})
.await;
let client = client_with_cert();
let response = DeboaRequest::get(server.url("/comments/1"))?
.send_with(client)
.await?;
assert_eq!(
response.status(),
StatusCode::OK,
"Status code is {} and should be {}",
response
.status()
.as_u16(),
StatusCode::OK.as_u16()
);
let comments = response
.text()
.await;
assert!(comments.is_ok());
assert_eq!(comments.unwrap(), "My comment");
server
.stop()
.await?;
Ok(())
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_get_by_query() -> TestResult<()> {
do_get_by_query().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_get_by_query() -> TestResult<()> {
do_get_by_query().await
}
async fn try_intro() -> TestResult<()> {
let mut server = start_mock_server(|req| async move {
if req.method() == "GET" && req.uri().path() == "/posts/1" {
Ok(mock_response(StatusCode::OK, ""))
} else {
Ok(mock_response(StatusCode::NOT_FOUND, "Not found"))
}
})
.await;
let client = client_with_cert();
let first_post = server.url("/posts/1");
let response = client
.execute(first_post.into_request()?)
.await?;
assert_eq!(response.status(), 200);
server
.stop()
.await?;
Ok(())
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_try_into() -> TestResult<()> {
try_intro().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_try_into() -> TestResult<()> {
try_intro().await
}
async fn fetch_from_str() -> TestResult<()> {
let mut server = start_mock_server(|req| async move {
if req.method() == "GET" && req.uri().path() == "/posts/1" {
Ok(mock_response(StatusCode::OK, ""))
} else {
Ok(mock_response(StatusCode::NOT_FOUND, "Not found"))
}
})
.await;
let client = client_with_cert();
let first_post = server.url("/posts/1");
let response = first_post
.fetch_with(&client)
.await?;
assert_eq!(response.status(), 200);
server
.stop()
.await?;
Ok(())
}
#[cfg(feature = "tokio-rt")]
#[tokio::test]
async fn test_fetch_from_str() -> TestResult<()> {
fetch_from_str().await
}
#[cfg(feature = "smol-rt")]
#[apply(test!)]
async fn test_fetch_from_str() -> TestResult<()> {
fetch_from_str().await
}