use std::fmt;
use parking_lot::RwLock;
use crate::{Rocket, Phase, Orbit, Ignite, Error};
use crate::local::asynchronous::{LocalRequest, LocalResponse};
use crate::http::{Method, uri::Origin, private::cookie};
pub struct Client {
rocket: Rocket<Orbit>,
cookies: RwLock<cookie::CookieJar>,
pub(in super) tracked: bool,
}
impl Client {
pub(crate) async fn _new<P: Phase>(
rocket: Rocket<P>,
tracked: bool
) -> Result<Client, Error> {
let rocket = rocket.local_launch().await?;
let cookies = RwLock::new(cookie::CookieJar::new());
Ok(Client { rocket, cookies, tracked })
}
#[doc(hidden)]
pub fn _test<T, F>(f: F) -> T
where F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send
{
crate::async_test(async {
let client = Client::debug(crate::build()).await.unwrap();
let request = client.get("/");
let response = request.clone().dispatch().await;
f(&client, request, response)
})
}
#[inline(always)]
pub(crate) fn _rocket(&self) -> &Rocket<Orbit> {
&self.rocket
}
#[inline(always)]
pub(crate) fn _with_raw_cookies<F, T>(&self, f: F) -> T
where F: FnOnce(&cookie::CookieJar) -> T
{
f(&*self.cookies.read())
}
#[inline(always)]
pub(crate) fn _with_raw_cookies_mut<F, T>(&self, f: F) -> T
where F: FnOnce(&mut cookie::CookieJar) -> T
{
f(&mut *self.cookies.write())
}
#[inline(always)]
fn _req<'c, 'u: 'c, U>(&'c self, method: Method, uri: U) -> LocalRequest<'c>
where U: TryInto<Origin<'u>> + fmt::Display
{
LocalRequest::new(self, method, uri)
}
pub(crate) async fn _terminate(self) -> Rocket<Ignite> {
let rocket = self.rocket;
rocket.shutdown().notify();
rocket.fairings.handle_shutdown(&rocket).await;
rocket.into_ignite()
}
pub_client_impl!("use rocket::local::asynchronous::Client;" @async await);
}
impl std::fmt::Debug for Client {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self._rocket().fmt(f)
}
}
#[cfg(test)]
mod test {
#[test]
fn test_local_client_impl_send_sync() {
fn assert_sync_send<T: Sync + Send>() {}
assert_sync_send::<super::Client>();
}
}