Skip to content

Commit e0ca328

Browse files
committed
Convert core to async and add support for async routes.
Minimum rustc bump required for rust-lang/rust#61775
1 parent 7bf59f4 commit e0ca328

37 files changed

+812
-646
lines changed

core/codegen/src/attribute/catch.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub fn _catch(args: TokenStream, input: TokenStream) -> Result<TokenStream> {
5151
let status_code = status.0.code;
5252

5353
// Variables names we'll use and reuse.
54-
define_vars_and_mods!(req, catcher, response, Request, Response);
54+
define_vars_and_mods!(req, catcher, Request, Response, ErrorHandlerFuture);
5555

5656
// Determine the number of parameters that will be passed in.
5757
let (fn_sig, inputs) = match catch.function.sig.inputs.len() {
@@ -83,12 +83,14 @@ pub fn _catch(args: TokenStream, input: TokenStream) -> Result<TokenStream> {
8383
#user_catcher_fn
8484

8585
/// Rocket code generated wrapping catch function.
86-
#vis fn #generated_fn_name<'_b>(#req: &'_b #Request) -> #response::Result<'_b> {
87-
let __response = #catcher_response;
88-
#Response::build()
89-
.status(#status)
90-
.merge(__response)
91-
.ok()
86+
#vis fn #generated_fn_name<'_b>(#req: &'_b #Request) -> #ErrorHandlerFuture<'_b> {
87+
Box::pin(async move {
88+
let __response = #catcher_response;
89+
#Response::build()
90+
.status(#status)
91+
.merge(__response)
92+
.ok()
93+
})
9294
}
9395

9496
/// Rocket code generated static catcher info.

core/codegen/src/attribute/route.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
178178
define_vars_and_mods!(req, data, FromData, Outcome, Transform);
179179
let span = ident.span().unstable().join(ty.span()).unwrap().into();
180180
quote_spanned! { span =>
181-
let __transform = <#ty as #FromData>::transform(#req, #data);
181+
let __transform = <#ty as #FromData>::transform(#req, #data).await;
182182

183183
#[allow(unreachable_patterns, unreachable_code)]
184184
let __outcome = match __transform {
@@ -195,7 +195,7 @@ fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
195195
};
196196

197197
#[allow(non_snake_case, unreachable_patterns, unreachable_code)]
198-
let #ident: #ty = match <#ty as #FromData>::from_data(#req, __outcome) {
198+
let #ident: #ty = match <#ty as #FromData>::from_data(#req, __outcome).await {
199199
#Outcome::Success(__d) => __d,
200200
#Outcome::Forward(__d) => return #Outcome::Forward(__d),
201201
#Outcome::Failure((__c, _)) => return #Outcome::Failure(__c),
@@ -368,8 +368,18 @@ fn generate_respond_expr(route: &Route) -> TokenStream2 {
368368
let parameter_names = route.inputs.iter()
369369
.map(|(_, rocket_ident, _)| rocket_ident);
370370

371+
let responder_stmt = if route.function.sig.asyncness.is_some() {
372+
quote_spanned! { ret_span =>
373+
let ___responder = #user_handler_fn_name(#(#parameter_names),*).await;
374+
}
375+
} else {
376+
quote_spanned! { ret_span =>
377+
let ___responder = #user_handler_fn_name(#(#parameter_names),*);
378+
}
379+
};
380+
371381
quote_spanned! { ret_span =>
372-
let ___responder = #user_handler_fn_name(#(#parameter_names),*);
382+
#responder_stmt
373383
#handler::Outcome::from(#req, ___responder)
374384
}
375385
}
@@ -402,7 +412,7 @@ fn codegen_route(route: Route) -> Result<TokenStream> {
402412
}
403413

404414
// Gather everything we need.
405-
define_vars_and_mods!(req, data, handler, Request, Data, StaticRouteInfo);
415+
define_vars_and_mods!(req, data, Request, Data, StaticRouteInfo, HandlerFuture);
406416
let (vis, user_handler_fn) = (&route.function.vis, &route.function);
407417
let user_handler_fn_name = &user_handler_fn.sig.ident;
408418
let generated_fn_name = user_handler_fn_name.prepend(ROUTE_FN_PREFIX);
@@ -422,12 +432,14 @@ fn codegen_route(route: Route) -> Result<TokenStream> {
422432
#vis fn #generated_fn_name<'_b>(
423433
#req: &'_b #Request,
424434
#data: #Data
425-
) -> #handler::Outcome<'_b> {
426-
#(#req_guard_definitions)*
427-
#(#parameter_definitions)*
428-
#data_stmt
429-
430-
#generated_respond_expr
435+
) -> #HandlerFuture<'_b> {
436+
Box::pin(async move {
437+
#(#req_guard_definitions)*
438+
#(#parameter_definitions)*
439+
#data_stmt
440+
441+
#generated_respond_expr
442+
})
431443
}
432444

433445
/// Rocket code generated wrapping URI macro.

core/codegen/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![feature(proc_macro_diagnostic, proc_macro_span)]
2+
#![feature(async_await)]
23
#![recursion_limit="128"]
34

45
#![doc(html_root_url = "https://api.rocket.rs/v0.5")]
@@ -96,6 +97,8 @@ vars_and_mods! {
9697
Data => rocket::Data,
9798
StaticRouteInfo => rocket::StaticRouteInfo,
9899
SmallVec => rocket::http::private::SmallVec,
100+
HandlerFuture => rocket::handler::HandlerFuture,
101+
ErrorHandlerFuture => rocket::handler::ErrorHandlerFuture,
99102
}
100103

101104
macro_rules! define_vars_and_mods {

core/codegen/tests/route.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(proc_macro_hygiene)]
1+
#![feature(proc_macro_hygiene, async_await)]
22

33
// Rocket sometimes generates mangled identifiers that activate the
44
// non_snake_case lint. We deny the lint in this test to ensure that

core/http/Cargo.toml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ edition = "2018"
1616

1717
[features]
1818
default = []
19-
tls = ["rustls", "hyper-sync-rustls"]
19+
tls = ["tokio-rustls"]
2020
private-cookies = ["cookie/secure"]
2121

2222
[dependencies]
@@ -27,16 +27,11 @@ http = "0.1.17"
2727
mime = "0.3.13"
2828
time = "0.1"
2929
indexmap = "1.0"
30-
rustls = { version = "0.15", optional = true }
3130
state = "0.4"
31+
tokio-rustls = { version = "0.9.2", optional = true }
3232
cookie = { version = "0.12", features = ["percent-encode"] }
3333
pear = "0.1"
3434
unicode-xid = "0.1"
3535

36-
[dependencies.hyper-sync-rustls]
37-
version = "=0.3.0-rc.5"
38-
features = ["server"]
39-
optional = true
40-
4136
[dev-dependencies]
4237
rocket = { version = "0.5.0-dev", path = "../lib" }

core/http/src/cookies.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use std::fmt;
2-
use std::cell::RefMut;
32

43
use crate::Header;
54
use cookie::Delta;
@@ -128,7 +127,7 @@ mod key {
128127
/// 32`.
129128
pub enum Cookies<'a> {
130129
#[doc(hidden)]
131-
Jarred(RefMut<'a, CookieJar>, &'a Key),
130+
Jarred(CookieJar, &'a Key, Box<dyn FnOnce(CookieJar) + Send + 'a>),
132131
#[doc(hidden)]
133132
Empty(CookieJar)
134133
}
@@ -137,8 +136,8 @@ impl<'a> Cookies<'a> {
137136
/// WARNING: This is unstable! Do not use this method outside of Rocket!
138137
#[inline]
139138
#[doc(hidden)]
140-
pub fn new(jar: RefMut<'a, CookieJar>, key: &'a Key) -> Cookies<'a> {
141-
Cookies::Jarred(jar, key)
139+
pub fn new<F: FnOnce(CookieJar) + Send + 'a>(jar: CookieJar, key: &'a Key, on_drop: F) -> Cookies<'a> {
140+
Cookies::Jarred(jar, key, Box::new(on_drop))
142141
}
143142

144143
/// WARNING: This is unstable! Do not use this method outside of Rocket!
@@ -160,7 +159,7 @@ impl<'a> Cookies<'a> {
160159
#[inline]
161160
#[doc(hidden)]
162161
pub fn add_original(&mut self, cookie: Cookie<'static>) {
163-
if let Cookies::Jarred(ref mut jar, _) = *self {
162+
if let Cookies::Jarred(ref mut jar, _, _) = *self {
164163
jar.add_original(cookie)
165164
}
166165
}
@@ -180,7 +179,7 @@ impl<'a> Cookies<'a> {
180179
/// ```
181180
pub fn get(&self, name: &str) -> Option<&Cookie<'static>> {
182181
match *self {
183-
Cookies::Jarred(ref jar, _) => jar.get(name),
182+
Cookies::Jarred(ref jar, _, _) => jar.get(name),
184183
Cookies::Empty(_) => None
185184
}
186185
}
@@ -205,7 +204,7 @@ impl<'a> Cookies<'a> {
205204
/// }
206205
/// ```
207206
pub fn add(&mut self, cookie: Cookie<'static>) {
208-
if let Cookies::Jarred(ref mut jar, _) = *self {
207+
if let Cookies::Jarred(ref mut jar, _, _) = *self {
209208
jar.add(cookie)
210209
}
211210
}
@@ -231,7 +230,7 @@ impl<'a> Cookies<'a> {
231230
/// }
232231
/// ```
233232
pub fn remove(&mut self, cookie: Cookie<'static>) {
234-
if let Cookies::Jarred(ref mut jar, _) = *self {
233+
if let Cookies::Jarred(ref mut jar, _, _) = *self {
235234
jar.remove(cookie)
236235
}
237236
}
@@ -252,7 +251,7 @@ impl<'a> Cookies<'a> {
252251
/// ```
253252
pub fn iter(&self) -> impl Iterator<Item=&Cookie<'static>> {
254253
match *self {
255-
Cookies::Jarred(ref jar, _) => jar.iter(),
254+
Cookies::Jarred(ref jar, _, _) => jar.iter(),
256255
Cookies::Empty(ref jar) => jar.iter()
257256
}
258257
}
@@ -262,12 +261,22 @@ impl<'a> Cookies<'a> {
262261
#[doc(hidden)]
263262
pub fn delta(&self) -> Delta<'_> {
264263
match *self {
265-
Cookies::Jarred(ref jar, _) => jar.delta(),
264+
Cookies::Jarred(ref jar, _, _) => jar.delta(),
266265
Cookies::Empty(ref jar) => jar.delta()
267266
}
268267
}
269268
}
270269

270+
impl<'a> Drop for Cookies<'a> {
271+
fn drop(&mut self) {
272+
if let Cookies::Jarred(ref mut jar, _, ref mut on_drop) = *self {
273+
let jar = std::mem::replace(jar, CookieJar::new());
274+
let on_drop = std::mem::replace(on_drop, Box::new(|_| {}));
275+
on_drop(jar);
276+
}
277+
}
278+
}
279+
271280
#[cfg(feature = "private-cookies")]
272281
impl Cookies<'_> {
273282
/// Returns a reference to the `Cookie` inside this collection with the name
@@ -290,7 +299,7 @@ impl Cookies<'_> {
290299
/// ```
291300
pub fn get_private(&mut self, name: &str) -> Option<Cookie<'static>> {
292301
match *self {
293-
Cookies::Jarred(ref mut jar, key) => jar.private(key).get(name),
302+
Cookies::Jarred(ref mut jar, key, _) => jar.private(key).get(name),
294303
Cookies::Empty(_) => None
295304
}
296305
}
@@ -326,7 +335,7 @@ impl Cookies<'_> {
326335
/// }
327336
/// ```
328337
pub fn add_private(&mut self, mut cookie: Cookie<'static>) {
329-
if let Cookies::Jarred(ref mut jar, key) = *self {
338+
if let Cookies::Jarred(ref mut jar, key, _) = *self {
330339
Cookies::set_private_defaults(&mut cookie);
331340
jar.private(key).add(cookie)
332341
}
@@ -336,7 +345,7 @@ impl Cookies<'_> {
336345
/// WARNING: This is unstable! Do not use this method outside of Rocket!
337346
#[doc(hidden)]
338347
pub fn add_original_private(&mut self, mut cookie: Cookie<'static>) {
339-
if let Cookies::Jarred(ref mut jar, key) = *self {
348+
if let Cookies::Jarred(ref mut jar, key, _) = *self {
340349
Cookies::set_private_defaults(&mut cookie);
341350
jar.private(key).add_original(cookie)
342351
}
@@ -390,7 +399,7 @@ impl Cookies<'_> {
390399
/// }
391400
/// ```
392401
pub fn remove_private(&mut self, mut cookie: Cookie<'static>) {
393-
if let Cookies::Jarred(ref mut jar, key) = *self {
402+
if let Cookies::Jarred(ref mut jar, key, _) = *self {
394403
if cookie.path().is_none() {
395404
cookie.set_path("/");
396405
}
@@ -403,7 +412,7 @@ impl Cookies<'_> {
403412
impl fmt::Debug for Cookies<'_> {
404413
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405414
match *self {
406-
Cookies::Jarred(ref jar, _) => jar.fmt(f),
415+
Cookies::Jarred(ref jar, _, _) => jar.fmt(f),
407416
Cookies::Empty(ref jar) => jar.fmt(f)
408417
}
409418
}

core/http/src/hyper.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
//! These types will, with certainty, be removed with time, but they reside here
55
//! while necessary.
66
7-
#[doc(hidden)] pub use hyper::{Body, Request, Response};
7+
#[doc(hidden)] pub use hyper::{Body, Request, Response, Server};
88
#[doc(hidden)] pub use hyper::body::Payload as Payload;
99
#[doc(hidden)] pub use hyper::error::Error;
10-
#[doc(hidden)] pub use hyper::server::Server;
1110
#[doc(hidden)] pub use hyper::service::{MakeService, Service};
1211

1312
#[doc(hidden)] pub use hyper::Chunk;
13+
#[doc(hidden)] pub use http::header::HeaderMap;
1414
#[doc(hidden)] pub use http::header::HeaderName as HeaderName;
1515
#[doc(hidden)] pub use http::header::HeaderValue as HeaderValue;
1616
#[doc(hidden)] pub use http::method::Method;
17-
#[doc(hidden)] pub use http::request::Parts;
17+
#[doc(hidden)] pub use http::request::Parts as RequestParts;
1818
#[doc(hidden)] pub use http::status::StatusCode;
1919
#[doc(hidden)] pub use http::uri::Uri;
2020

core/http/src/tls.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
pub use hyper_sync_rustls::{util, WrappedStream, ServerSession, TlsServer};
2-
pub use rustls::{Certificate, PrivateKey};
1+
pub use tokio_rustls::TlsAcceptor;
2+
pub use tokio_rustls::rustls;
3+
4+
pub use rustls::internal::pemfile;
5+
pub use rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig};

core/lib/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ tls = ["rocket_http/tls"]
2424
private-cookies = ["rocket_http/private-cookies"]
2525

2626
[dependencies]
27-
futures = "0.1"
2827
rocket_codegen = { version = "0.5.0-dev", path = "../codegen" }
2928
rocket_http = { version = "0.5.0-dev", path = "../http" }
29+
futures-preview = { version = "0.3.0-alpha.14", features = ["compat", "io-compat"] }
3030
tokio = "0.1.16"
3131
yansi = "0.5"
32-
log = "0.4"
32+
log = { version = "0.4", features = ["std"] }
3333
toml = "0.4.7"
3434
num_cpus = "1.0"
3535
state = "0.4.1"

core/lib/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
use yansi::{Paint, Color::{Red, Yellow, Blue}};
44

55
// Specifies the minimum nightly version needed to compile Rocket.
6-
const MIN_DATE: &'static str = "2019-04-05";
7-
const MIN_VERSION: &'static str = "1.35.0-nightly";
6+
const MIN_DATE: &'static str = "2019-07-03";
7+
const MIN_VERSION: &'static str = "1.37.0-nightly";
88

99
macro_rules! err {
1010
($version:expr, $date:expr, $msg:expr) => (

core/lib/src/catcher.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use futures::future::Future;
2+
13
use crate::response;
24
use crate::handler::ErrorHandler;
35
use crate::codegen::StaticCatchInfo;
@@ -98,7 +100,7 @@ impl Catcher {
98100
}
99101

100102
#[inline(always)]
101-
pub(crate) fn handle<'r>(&self, req: &'r Request<'_>) -> response::Result<'r> {
103+
pub(crate) fn handle<'r>(&self, req: &'r Request<'_>) -> impl Future<Output = response::Result<'r>> {
102104
(self.handler)(req)
103105
}
104106

@@ -149,10 +151,12 @@ macro_rules! default_catchers {
149151
let mut map = HashMap::new();
150152

151153
$(
152-
fn $fn_name<'r>(req: &'r Request<'_>) -> response::Result<'r> {
153-
status::Custom(Status::from_code($code).unwrap(),
154-
content::Html(error_page_template!($code, $name, $description))
155-
).respond_to(req)
154+
fn $fn_name<'r>(req: &'r Request<'_>) -> std::pin::Pin<Box<dyn std::future::Future<Output = response::Result<'r>> + Send + 'r>> {
155+
(async move {
156+
status::Custom(Status::from_code($code).unwrap(),
157+
content::Html(error_page_template!($code, $name, $description))
158+
).respond_to(req)
159+
}).boxed()
156160
}
157161

158162
map.insert($code, Catcher::new_default($code, $fn_name));
@@ -164,6 +168,7 @@ macro_rules! default_catchers {
164168

165169
pub mod defaults {
166170
use super::Catcher;
171+
use futures::future::FutureExt;
167172

168173
use std::collections::HashMap;
169174

core/lib/src/codegen.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
use futures::future::Future;
2+
13
use crate::{Request, Data};
24
use crate::handler::{Outcome, ErrorHandler};
35
use crate::http::{Method, MediaType};
46

57
/// Type of a static handler, which users annotate with Rocket's attribute.
6-
pub type StaticHandler = for<'r> fn(&'r Request<'_>, Data) -> Outcome<'r>;
8+
pub type StaticHandler = for<'r> fn(&'r Request<'_>, Data) -> std::pin::Pin<Box<dyn Future<Output = Outcome<'r>> + Send + 'r>>;
79

810
/// Information generated by the `route` attribute during codegen.
911
pub struct StaticRouteInfo {

0 commit comments

Comments
 (0)