axum_webtools/tests/
request.rs1use 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}