Skip to main content

axum_webtools/tests/
request.rs

1use crate::security::jwt::Claims;
2use axum::body::Body;
3use axum::http::{HeaderMap, Request, StatusCode};
4use axum::Router;
5use http_body_util::BodyExt;
6use serde::de::DeserializeOwned;
7use serde::Serialize;
8use tower::ServiceExt;
9
10pub struct Response<T: DeserializeOwned> {
11    pub body: Option<T>,
12    pub status_code: StatusCode,
13    pub headers: HeaderMap,
14}
15
16pub async fn request<T: Serialize, R: DeserializeOwned>(
17    router: Router,
18    uri: &str,
19    method: &str,
20    body: T,
21    claims: Option<Claims>,
22) -> Response<R> {
23    let request_body = Body::from(serde_json::to_vec(&body).unwrap());
24
25    let claims = claims.unwrap_or(Claims {
26        sub: "sub".to_string(),
27        aud: "aud".to_string(),
28        iss: "iss".to_string(),
29        issued_at: chrono::Utc::now().timestamp() as u64,
30        exp: (chrono::Utc::now() + chrono::Duration::days(7)).timestamp() as u64,
31        scopes: vec![],
32    });
33    let request = Request::builder()
34        .header("Content-Type", "application/json")
35        .header("X-Claims-Subject", claims.sub)
36        .header("X-Claims-Audience", claims.aud)
37        .header("X-Claims-Issuer", claims.iss)
38        .header("X-Claims-Issued-At", claims.issued_at.to_string())
39        .header("X-Claims-Expiration", claims.exp.to_string())
40        .header(
41            "X-Claims-Scopes",
42            claims.scopes.iter().fold(String::new(), |acc, s| {
43                if acc.is_empty() {
44                    s.to_string()
45                } else {
46                    format!("{},{}", acc, s)
47                }
48            }),
49        )
50        .uri(uri)
51        .method(method)
52        .body(request_body)
53        .unwrap();
54
55    let response = router.oneshot(request).await.unwrap();
56    let status_code = response.status();
57    let headers = response.headers().clone();
58
59    let body = match status_code.as_u16() {
60        200..=299 => {
61            let body = response.into_body().collect().await.unwrap().to_bytes();
62            let r = serde_json::from_slice::<R>(&body).unwrap();
63            Some(r)
64        }
65        _ => None,
66    };
67    Response {
68        body,
69        status_code,
70        headers,
71    }
72}