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