🏗️ Elegant & Highly Performant Async Gemini Server Framework for the Modern Age
async framework gemini-protocol protocol gemini rust
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(context): fix async sharing

Fuwn 4444f64e c30b7625

+82 -110
+18 -25
examples/windmark.rs
··· 80 80 r.mount("/module", success!("This is a module!")); 81 81 }); 82 82 router.attach_async(Clicker::default()); 83 - router.set_pre_route_callback(|context| { 84 - info!( 85 - "accepted connection from {} to {}", 86 - context.tcp.peer_addr().unwrap().ip(), 87 - context.url.to_string() 88 - ) 89 - }); 90 - router.set_post_route_callback(|context, content| { 91 - content.content = 92 - content.content.replace("Welcome!", "Welcome to Windmark!"); 93 - 94 - info!( 95 - "closed connection from {}", 96 - context.tcp.peer_addr().unwrap().ip() 97 - ) 98 - }); 83 + // router.set_pre_route_callback(|context| { 84 + // info!( 85 + // "accepted connection from {} to {}", 86 + // context.tcp.peer_addr().unwrap().ip(), 87 + // context.url.to_string() 88 + // ) 89 + // }); 90 + // router.set_post_route_callback(|context, content| { 91 + // content.content = 92 + // content.content.replace("Welcome!", "Welcome to Windmark!"); 93 + // 94 + // info!( 95 + // "closed connection from {}", 96 + // context.tcp.peer_addr().unwrap().ip() 97 + // ) 98 + // }); 99 99 router.add_header(|_| "```\nART IS COOL\n```\nhi".to_string()); 100 100 router.add_footer(|_| "Copyright 2022".to_string()); 101 101 router.add_footer(|context| { ··· 110 110 .with_mime("text/plain") 111 111 .clone() 112 112 }); 113 - router.mount( 114 - "/ip", 115 - success!( 116 - context, 117 - format!("Hello, {}", context.tcp.peer_addr().unwrap().ip()) 118 - ), 119 - ); 120 113 router.mount("/test", success!("hi there\n=> / back")); 121 114 router.mount( 122 115 "/temporary-failure", ··· 211 204 Response::success(*clicks) 212 205 } 213 206 }); 214 - router.mount("/async-nothing", |_| { 215 - async { Response::success("This is an async route.") } 207 + router.mount("/async-nothing", |context| { 208 + async move { Response::success(context.url.path()) } 216 209 }); 217 210 router.mount( 218 211 "/async-macro",
+6 -12
src/context/error.rs
··· 17 17 // SPDX-License-Identifier: GPL-3.0-only 18 18 19 19 use openssl::x509::X509; 20 - use tokio::net::TcpStream; 21 20 use url::Url; 22 21 23 22 #[allow(clippy::module_name_repetitions)] 24 - pub struct ErrorContext<'a> { 25 - pub tcp: &'a TcpStream, 26 - pub url: &'a Url, 27 - pub certificate: &'a Option<X509>, 23 + pub struct ErrorContext { 24 + pub url: Url, 25 + pub certificate: Option<X509>, 28 26 } 29 27 30 - impl<'a> ErrorContext<'a> { 31 - pub const fn new( 32 - tcp: &'a TcpStream, 33 - url: &'a Url, 34 - certificate: &'a Option<X509>, 35 - ) -> Self { 28 + impl ErrorContext { 29 + #[must_use] 30 + pub const fn new(url: Url, certificate: Option<X509>) -> Self { 36 31 Self { 37 - tcp, 38 32 url, 39 33 certificate, 40 34 }
+7 -10
src/context/hook.rs
··· 18 18 19 19 use matchit::Params; 20 20 use openssl::x509::X509; 21 - use tokio::net::TcpStream; 22 21 use url::Url; 23 22 24 23 #[allow(clippy::module_name_repetitions)] 25 24 pub struct HookContext<'a> { 26 - pub tcp: &'a TcpStream, 27 - pub url: &'a Url, 28 - pub params: Option<&'a Params<'a, 'a>>, 29 - pub certificate: &'a Option<X509>, 25 + pub url: Url, 26 + pub params: Option<Params<'a, 'a>>, 27 + pub certificate: Option<X509>, 30 28 } 31 29 32 30 impl<'a> HookContext<'a> { 31 + #[must_use] 33 32 pub const fn new( 34 - tcp: &'a TcpStream, 35 - url: &'a Url, 36 - params: Option<&'a Params<'a, 'a>>, 37 - certificate: &'a Option<X509>, 33 + url: Url, 34 + params: Option<Params<'a, 'a>>, 35 + certificate: Option<X509>, 38 36 ) -> Self { 39 37 Self { 40 - tcp, 41 38 url, 42 39 params, 43 40 certificate,
+8 -10
src/context/route.rs
··· 18 18 19 19 use matchit::Params; 20 20 use openssl::x509::X509; 21 - use tokio::net::TcpStream; 22 21 use url::Url; 23 22 24 23 #[allow(clippy::module_name_repetitions)] 24 + #[derive(Clone)] 25 25 pub struct RouteContext<'a> { 26 - pub tcp: &'a TcpStream, 27 - pub url: &'a Url, 28 - pub params: &'a Params<'a, 'a>, 29 - pub certificate: &'a Option<X509>, 26 + pub url: Url, 27 + pub params: Params<'a, 'a>, 28 + pub certificate: Option<X509>, 30 29 } 31 30 32 31 impl<'a> RouteContext<'a> { 32 + #[must_use] 33 33 pub const fn new( 34 - tcp: &'a TcpStream, 35 - url: &'a Url, 36 - params: &'a Params<'a, 'a>, 37 - certificate: &'a Option<X509>, 34 + url: Url, 35 + params: Params<'a, 'a>, 36 + certificate: Option<X509>, 38 37 ) -> Self { 39 38 Self { 40 - tcp, 41 39 url, 42 40 params, 43 41 certificate,
+2 -5
src/handler/response/error.rs
··· 19 19 use crate::{context::ErrorContext, Response}; 20 20 21 21 #[allow(clippy::module_name_repetitions)] 22 - pub trait ErrorResponse: 23 - FnMut(ErrorContext<'_>) -> Response + Send + Sync 24 - { 25 - } 22 + pub trait ErrorResponse: FnMut(ErrorContext) -> Response + Send + Sync {} 26 23 27 - impl<T> ErrorResponse for T where T: FnMut(ErrorContext<'_>) -> Response + Send + Sync 24 + impl<T> ErrorResponse for T where T: FnMut(ErrorContext) -> Response + Send + Sync 28 25 {}
+41 -48
src/router.rs
··· 348 348 for module in &mut *self.async_modules.lock().await { 349 349 module 350 350 .on_pre_route(HookContext::new( 351 - stream.get_ref(), 352 - &url, 353 - route.as_ref().map_or(None, |route| Some(&route.params)), 354 - &stream.ssl().peer_certificate(), 351 + url.clone(), 352 + route 353 + .as_ref() 354 + .map_or(None, |route| Some(route.params.clone())), 355 + stream.ssl().peer_certificate().clone(), 355 356 )) 356 357 .await; 357 358 } 358 359 359 360 for module in &mut *self.modules.lock().unwrap() { 360 361 module.on_pre_route(HookContext::new( 361 - stream.get_ref(), 362 - &url, 363 - route.as_ref().map_or(None, |route| Some(&route.params)), 364 - &stream.ssl().peer_certificate(), 362 + url.clone(), 363 + route 364 + .as_ref() 365 + .map_or(None, |route| Some(route.params.clone())), 366 + stream.ssl().peer_certificate().clone(), 365 367 )); 366 368 } 367 369 368 370 (*self.pre_route_callback).lock().unwrap()(HookContext::new( 369 - stream.get_ref(), 370 - &url, 371 - route.as_ref().map_or(None, |route| Some(&route.params)), 372 - &stream.ssl().peer_certificate(), 371 + url.clone(), 372 + route 373 + .as_ref() 374 + .map_or(None, |route| Some(route.params.clone())), 375 + stream.ssl().peer_certificate(), 373 376 )); 374 377 375 378 let peer_certificate = stream.ssl().peer_certificate(); 376 379 let mut content = if let Ok(ref route) = route { 377 380 let footers_length = (*self.footers.lock().unwrap()).len(); 381 + let route_context = RouteContext::new( 382 + url.clone(), 383 + route.params.clone(), 384 + stream.ssl().peer_certificate(), 385 + ); 378 386 379 387 for partial_header in &mut *self.headers.lock().unwrap() { 380 - header.push_str(&format!( 381 - "{}\n", 382 - partial_header(RouteContext::new( 383 - stream.get_ref(), 384 - &url, 385 - &route.params, 386 - &stream.ssl().peer_certificate() 387 - )), 388 - )); 388 + header 389 + .push_str(&format!("{}\n", partial_header(route_context.clone()),)); 389 390 } 390 391 391 392 for (i, partial_footer) in { ··· 394 395 } { 395 396 footer.push_str(&format!( 396 397 "{}{}", 397 - partial_footer(RouteContext::new( 398 - stream.get_ref(), 399 - &url, 400 - &route.params, 401 - &stream.ssl().peer_certificate() 402 - )), 398 + partial_footer(route_context.clone()), 403 399 if footers_length > 1 && i != footers_length - 1 { 404 400 "\n" 405 401 } else { ··· 409 405 } 410 406 411 407 let mut lock = (*route.value).lock().await; 412 - let handler = lock.call(RouteContext::new( 413 - stream.get_ref(), 414 - &url, 415 - &route.params, 416 - &peer_certificate, 417 - )); 408 + let handler = lock.call(route_context); 418 409 419 410 handler.await 420 411 } else { 421 412 (*self.error_handler).lock().unwrap()(ErrorContext::new( 422 - stream.get_ref(), 423 - &url, 424 - &peer_certificate, 413 + url.clone(), 414 + peer_certificate.clone(), 425 415 )) 426 416 }; 427 417 428 418 for module in &mut *self.async_modules.lock().await { 429 419 module 430 420 .on_post_route(HookContext::new( 431 - stream.get_ref(), 432 - &url, 433 - route.as_ref().map_or(None, |route| Some(&route.params)), 434 - &stream.ssl().peer_certificate(), 421 + url.clone(), 422 + route 423 + .as_ref() 424 + .map_or(None, |route| Some(route.params.clone())), 425 + stream.ssl().peer_certificate().clone(), 435 426 )) 436 427 .await; 437 428 } 438 429 439 430 for module in &mut *self.modules.lock().unwrap() { 440 431 module.on_post_route(HookContext::new( 441 - stream.get_ref(), 442 - &url, 443 - route.as_ref().map_or(None, |route| Some(&route.params)), 444 - &stream.ssl().peer_certificate(), 432 + url.clone(), 433 + route 434 + .as_ref() 435 + .map_or(None, |route| Some(route.params.clone())), 436 + stream.ssl().peer_certificate().clone(), 445 437 )); 446 438 } 447 439 448 440 (*self.post_route_callback).lock().unwrap()( 449 441 HookContext::new( 450 - stream.get_ref(), 451 - &url, 452 - route.as_ref().map_or(None, |route| Some(&route.params)), 453 - &stream.ssl().peer_certificate(), 442 + url.clone(), 443 + route 444 + .as_ref() 445 + .map_or(None, |route| Some(route.params.clone())), 446 + stream.ssl().peer_certificate(), 454 447 ), 455 448 &mut content, 456 449 );