rocket_community/local/asynchronous/
request.rs1use std::fmt;
2
3use rocket_http::HttpVersion;
4
5use crate::http::uri::Origin;
6use crate::http::{Method, Status};
7use crate::{Data, Request};
8
9use super::{Client, LocalResponse};
10
11pub struct LocalRequest<'c> {
37 pub(super) client: &'c Client,
38 pub(super) request: Request<'c>,
39 data: Vec<u8>,
40 uri: Result<Origin<'c>, Origin<'static>>,
42}
43
44impl<'c> LocalRequest<'c> {
45 pub(crate) fn new<'u: 'c, U>(client: &'c Client, method: Method, uri: U) -> Self
46 where
47 U: TryInto<Origin<'u>> + fmt::Display,
48 {
49 let uri_str = uri.to_string();
51 let try_origin = uri.try_into().map_err(|_| Origin::path_only(uri_str));
52
53 let origin = try_origin.clone().unwrap_or_else(|bad| bad);
55 let mut request = Request::new(client.rocket(), method, origin, None);
56
57 if client.tracked {
59 client._with_raw_cookies(|jar| {
60 for cookie in jar.iter() {
61 request.cookies_mut().add_original(cookie.clone());
62 }
63 })
64 }
65
66 LocalRequest {
67 client,
68 request,
69 uri: try_origin,
70 data: vec![],
71 }
72 }
73
74 #[inline]
75 pub fn override_version(&mut self, version: HttpVersion) {
76 self.version = Some(version);
77 }
78
79 pub(crate) fn _request(&self) -> &Request<'c> {
80 &self.request
81 }
82
83 pub(crate) fn _request_mut(&mut self) -> &mut Request<'c> {
84 &mut self.request
85 }
86
87 pub(crate) fn _body_mut(&mut self) -> &mut Vec<u8> {
88 &mut self.data
89 }
90
91 async fn _dispatch(mut self) -> LocalResponse<'c> {
93 let rocket = self.client.rocket();
97 if let Err(ref invalid) = self.uri {
98 if self.inner().uri() == invalid {
101 error!("invalid request URI: {:?}", invalid.path());
102 return LocalResponse::new(self.request, move |req| {
103 rocket.dispatch_error(Status::BadRequest, req)
104 })
105 .await;
106 }
107 }
108
109 let mut data = Data::local(self.data);
111 let token = rocket.preprocess(&mut self.request, &mut data).await;
112 let response =
113 LocalResponse::new(self.request, move |req| rocket.dispatch(token, req, data)).await;
114
115 if self.client.tracked {
118 self.client._with_raw_cookies_mut(|jar| {
119 let current_time = time::OffsetDateTime::now_utc();
120 for cookie in response.cookies().iter() {
121 if let Some(expires) = cookie.expires_datetime() {
122 if expires <= current_time {
123 jar.force_remove(cookie.name());
124 continue;
125 }
126 }
127
128 jar.add_original(cookie.clone());
129 }
130 })
131 }
132
133 response
134 }
135
136 pub_request_impl!("# use rocket::local::asynchronous::Client;\n\
137 use rocket::local::asynchronous::LocalRequest;" async await);
138}
139
140impl<'c> Clone for LocalRequest<'c> {
141 fn clone(&self) -> Self {
142 LocalRequest {
143 client: self.client,
144 request: self.request.clone(),
145 data: self.data.clone(),
146 uri: self.uri.clone(),
147 }
148 }
149}
150
151impl std::fmt::Debug for LocalRequest<'_> {
152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153 self._request().fmt(f)
154 }
155}
156
157impl<'c> std::ops::Deref for LocalRequest<'c> {
158 type Target = Request<'c>;
159
160 fn deref(&self) -> &Self::Target {
161 self.inner()
162 }
163}
164
165impl<'c> std::ops::DerefMut for LocalRequest<'c> {
166 fn deref_mut(&mut self) -> &mut Self::Target {
167 self.inner_mut()
168 }
169}