rocket_community/local/blocking/
client.rs1use std::cell::RefCell;
2use std::fmt;
3
4use crate::http::{uri::Origin, Method};
5use crate::local::{
6 asynchronous,
7 blocking::{LocalRequest, LocalResponse},
8};
9use crate::{Error, Ignite, Orbit, Phase, Rocket};
10
11pub struct Client {
32 pub(crate) inner: Option<asynchronous::Client>,
33 runtime: RefCell<tokio::runtime::Runtime>,
34}
35
36impl Client {
37 fn _new<P: Phase>(rocket: Rocket<P>, tracked: bool, secure: bool) -> Result<Client, Error> {
38 let runtime = tokio::runtime::Builder::new_multi_thread()
39 .thread_name("rocket-local-client-worker-thread")
40 .worker_threads(1)
41 .enable_all()
42 .build()
43 .expect("create tokio runtime");
44
45 let inner = Some(runtime.block_on(asynchronous::Client::_new(rocket, tracked, secure))?);
47 Ok(Self {
48 inner,
49 runtime: RefCell::new(runtime),
50 })
51 }
52
53 #[doc(hidden)]
55 pub fn _test<T, F>(f: F) -> T
56 where
57 F: FnOnce(&Self, LocalRequest<'_>, LocalResponse<'_>) -> T + Send,
58 {
59 let client = Client::debug(crate::build()).unwrap();
60 let request = client.get("/");
61 let response = request.clone().dispatch();
62 f(&client, request, response)
63 }
64
65 #[inline(always)]
66 pub(crate) fn inner(&self) -> &asynchronous::Client {
67 self.inner
68 .as_ref()
69 .expect("internal invariant broken: self.inner is Some")
70 }
71
72 #[inline(always)]
73 pub(crate) fn block_on<F, R>(&self, fut: F) -> R
74 where
75 F: std::future::Future<Output = R>,
76 {
77 self.runtime.borrow_mut().block_on(fut)
78 }
79
80 #[inline(always)]
81 fn _rocket(&self) -> &Rocket<Orbit> {
82 self.inner()._rocket()
83 }
84
85 #[inline(always)]
86 pub(crate) fn _with_raw_cookies<F, T>(&self, f: F) -> T
87 where
88 F: FnOnce(&cookie::CookieJar) -> T,
89 {
90 self.inner()._with_raw_cookies(f)
91 }
92
93 pub(crate) fn _terminate(mut self) -> Rocket<Ignite> {
94 let runtime = tokio::runtime::Builder::new_current_thread()
95 .build()
96 .unwrap();
97 let runtime = self.runtime.replace(runtime);
98 let inner = self
99 .inner
100 .take()
101 .expect("invariant broken: self.inner is Some");
102 let rocket = runtime.block_on(inner._terminate());
103 runtime.shutdown_timeout(std::time::Duration::from_secs(1));
104 rocket
105 }
106
107 #[inline(always)]
108 fn _req<'c, 'u: 'c, U>(&'c self, method: Method, uri: U) -> LocalRequest<'c>
109 where
110 U: TryInto<Origin<'u>> + fmt::Display,
111 {
112 LocalRequest::new(self, method, uri)
113 }
114
115 pub_client_impl!("use rocket::local::blocking::Client;");
117}
118
119impl std::fmt::Debug for Client {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 self._rocket().fmt(f)
122 }
123}
124
125impl Drop for Client {
126 fn drop(&mut self) {
127 if let Some(client) = self.inner.take() {
128 self.block_on(async { drop(client) });
129 }
130 }
131}
132
133#[cfg(doctest)]
134mod doctest {
135 #[allow(dead_code)]
142 fn test_not_sync() {}
143}