fire_http_api/
testing.rs

1// todo if this should ever be used outside of testing the uri parameter
2// should be replaced with a hashmap or something simiar
3use crate::error::ApiError;
4
5use fire::header::{HeaderValues, Method, Mime, StatusCode};
6use fire::resources::Resources;
7use fire::routes::ParamsNames;
8use fire::{Body, Error, FirePit, Request, Response};
9
10use representation::request::DeserializeError;
11use serde::de::DeserializeOwned;
12
13pub struct FirePitApi {
14	inner: FirePit,
15}
16
17impl FirePitApi {
18	pub fn new(inner: FirePit) -> Self {
19		Self { inner }
20	}
21
22	pub fn data(&self) -> &Resources {
23		self.inner.data()
24	}
25
26	/// Routes the request to normal routes and returns their result.
27	///
28	/// Useful for tests and niche applications.
29	///
30	/// Returns None if no route was found matching the request.
31	pub async fn route(
32		&self,
33		req: &mut Request,
34	) -> Option<Result<Response, Error>> {
35		self.inner.route(req).await
36	}
37
38	pub async fn request<R>(&self, req: &R) -> Result<R::Response, R::Error>
39	where
40		R: crate::Request,
41		R::Error: DeserializeOwned + Send + 'static,
42		R::Response: Send + 'static,
43	{
44		let params = ParamsNames::parse(R::PATH);
45		assert!(params.is_empty(), "path parameters are not allowed");
46
47		self.request_with_header(R::PATH, req, HeaderValues::new())
48			.await
49	}
50
51	pub async fn request_with_uri<R>(
52		&self,
53		uri: impl AsRef<str>,
54		req: &R,
55	) -> Result<R::Response, R::Error>
56	where
57		R: crate::Request,
58		R::Error: DeserializeOwned + Send + 'static,
59		R::Response: Send + 'static,
60	{
61		self.request_with_header(uri.as_ref(), req, HeaderValues::new())
62			.await
63	}
64
65	pub async fn request_with_header<R>(
66		&self,
67		uri: impl AsRef<str>,
68		req: &R,
69		header: HeaderValues,
70	) -> Result<R::Response, R::Error>
71	where
72		R: crate::Request,
73		R::Error: DeserializeOwned + Send + 'static,
74		R::Response: Send + 'static,
75	{
76		let mut raw_req =
77			Request::builder(uri.as_ref().parse().unwrap()).method(R::METHOD);
78		*raw_req.values_mut() = header;
79
80		let mut req = if R::METHOD == &Method::GET {
81			raw_req.serialize_query(req).unwrap().build()
82		} else {
83			raw_req
84				.content_type(Mime::JSON)
85				.body(Body::serialize(req).unwrap())
86				.build()
87		};
88
89		self.request_raw::<R>(&mut req).await
90	}
91
92	pub async fn request_raw<R>(
93		&self,
94		req: &mut Request,
95	) -> Result<R::Response, R::Error>
96	where
97		R: crate::Request,
98		R::Error: DeserializeOwned + Send + 'static,
99		R::Response: Send + 'static,
100	{
101		let mut resp = self
102			.route(req)
103			.await
104			.unwrap()
105			.map_err(crate::error::Error::Fire)
106			.map_err(R::Error::from_error)?;
107
108		if resp.header().status_code() != &StatusCode::OK {
109			let e = resp
110				.body
111				.deserialize()
112				.await
113				.map_err(DeserializeError::Json)
114				.map_err(crate::error::Error::Deserialize)
115				.map_err(R::Error::from_error)?;
116
117			return Err(e);
118		}
119
120		resp.take_body()
121			.deserialize()
122			.await
123			.map_err(DeserializeError::Json)
124			.map_err(crate::error::Error::Deserialize)
125			.map_err(R::Error::from_error)
126	}
127}