🏗️ Elegant & Highly Performant Async Gemini Server Framework for the Modern Age
async framework gemini-protocol protocol gemini rust
at main 142 lines 3.0 kB view raw
1//! Content and response handlers 2 3#[cfg(feature = "response-macros")] 4mod macros; 5 6macro_rules! response { 7 ($name:ident, $status:expr) => { 8 pub fn $name<S>(content: S) -> Self 9 where S: Into<String> + AsRef<str> { 10 Self::new($status, content.into()) 11 } 12 }; 13} 14 15/// The content and response type a handler should reply with. 16#[derive(Clone)] 17pub struct Response { 18 pub status: i32, 19 pub mime: Option<String>, 20 pub content: String, 21 pub character_set: Option<String>, 22 pub languages: Option<Vec<String>>, 23} 24 25impl Response { 26 response!(input, 10); 27 28 response!(sensitive_input, 11); 29 30 response!(temporary_redirect, 30); 31 32 response!(permanent_redirect, 31); 33 34 response!(temporary_failure, 40); 35 36 response!(server_unavailable, 41); 37 38 response!(cgi_error, 42); 39 40 response!(proxy_error, 43); 41 42 response!(slow_down, 44); 43 44 response!(permanent_failure, 50); 45 46 response!(not_found, 51); 47 48 response!(gone, 52); 49 50 response!(proxy_refused, 53); 51 52 response!(bad_request, 59); 53 54 response!(client_certificate_required, 60); 55 56 response!(certificate_not_authorised, 61); 57 58 response!(certificate_not_valid, 62); 59 60 #[allow(clippy::needless_pass_by_value)] 61 pub fn success(content: impl ToString) -> Self { 62 let mut response = Self::new(20, content.to_string()); 63 64 response 65 .with_mime("text/gemini") 66 .with_languages(["en"]) 67 .with_character_set("utf-8"); 68 69 response 70 } 71 72 #[must_use] 73 pub fn binary_success( 74 content: impl AsRef<[u8]>, 75 mime: impl Into<String> + AsRef<str>, 76 ) -> Self { 77 let mut response = Self::new(21, String::from_utf8_lossy(content.as_ref())); 78 79 response.with_mime(mime); 80 81 response 82 } 83 84 #[cfg(feature = "auto-deduce-mime")] 85 #[must_use] 86 pub fn binary_success_auto(content: &[u8]) -> Self { 87 let mut response = Self::new(22, String::from_utf8_lossy(content)); 88 89 response.with_mime(tree_magic_mini::from_u8(content)); 90 91 response 92 } 93 94 #[must_use] 95 pub fn new(status: i32, content: impl Into<String> + AsRef<str>) -> Self { 96 Self { 97 status, 98 mime: None, 99 content: content.into(), 100 character_set: None, 101 languages: None, 102 } 103 } 104 105 pub fn with_mime( 106 &mut self, 107 mime: impl Into<String> + AsRef<str>, 108 ) -> &mut Self { 109 self.mime = Some(mime.into()); 110 111 self 112 } 113 114 pub fn with_character_set( 115 &mut self, 116 character_set: impl Into<String> + AsRef<str>, 117 ) -> &mut Self { 118 self.character_set = Some(character_set.into()); 119 120 self 121 } 122 123 pub fn with_languages<S>(&mut self, languages: impl AsRef<[S]>) -> &mut Self 124 where S: Into<String> + AsRef<str> { 125 self.languages = Some( 126 languages 127 .as_ref() 128 .iter() 129 .map(|s| s.as_ref().to_string()) 130 .collect::<Vec<String>>(), 131 ); 132 133 self 134 } 135} 136 137impl std::future::IntoFuture for Response { 138 type IntoFuture = std::future::Ready<Self::Output>; 139 type Output = Self; 140 141 fn into_future(self) -> Self::IntoFuture { std::future::ready(self) } 142}