diff --git a/src/client/connection/response/certificate.rs b/src/client/connection/response/certificate.rs index 160e2f0..e9f76c7 100644 --- a/src/client/connection/response/certificate.rs +++ b/src/client/connection/response/certificate.rs @@ -9,11 +9,20 @@ const NOT_VALID: (u8, &str) = (11, "Certificate not valid"); /// https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates pub enum Certificate { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-60 - Required { message: Option }, + Required { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-61-certificate-not-authorized - NotAuthorized { message: Option }, + NotAuthorized { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-62-certificate-not-valid - NotValid { message: Option }, + NotValid { + header: String, + message: Option, + }, } impl Certificate { @@ -39,11 +48,20 @@ impl Certificate { .0 } + pub fn header(&self) -> &str { + match self { + Self::Required { header, .. } + | Self::NotAuthorized { header, .. } + | Self::NotValid { header, .. } => header, + } + .as_str() + } + pub fn message(&self) -> Option<&str> { match self { - Self::Required { message } => message, - Self::NotAuthorized { message } => message, - Self::NotValid { message } => message, + Self::Required { message, .. } + | Self::NotAuthorized { message, .. } + | Self::NotValid { message, .. } => message, } .as_deref() } @@ -69,16 +87,19 @@ impl std::str::FromStr for Certificate { fn from_str(header: &str) -> Result { if let Some(postfix) = header.strip_prefix("60") { return Ok(Self::Required { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("61") { return Ok(Self::NotAuthorized { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("62") { return Ok(Self::NotValid { + header: header.to_string(), message: message(postfix), }); } diff --git a/src/client/connection/response/failure.rs b/src/client/connection/response/failure.rs index 40c8abf..8e85e84 100644 --- a/src/client/connection/response/failure.rs +++ b/src/client/connection/response/failure.rs @@ -45,6 +45,13 @@ impl Failure { } } + pub fn header(&self) -> &str { + match self { + Self::Permanent(permanent) => permanent.header(), + Self::Temporary(temporary) => temporary.header(), + } + } + pub fn message(&self) -> Option<&str> { match self { Self::Permanent(permanent) => permanent.message(), diff --git a/src/client/connection/response/failure/permanent.rs b/src/client/connection/response/failure/permanent.rs index e2ab9e0..e69510c 100644 --- a/src/client/connection/response/failure/permanent.rs +++ b/src/client/connection/response/failure/permanent.rs @@ -10,15 +10,30 @@ const BAD_REQUEST: (u8, &str) = (59, "bad-request"); /// https://geminiprotocol.net/docs/protocol-specification.gmi#permanent-failure pub enum Permanent { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-50 - Default { message: Option }, + Default { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-51-not-found - NotFound { message: Option }, + NotFound { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-52-gone - Gone { message: Option }, + Gone { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-53-proxy-request-refused - ProxyRequestRefused { message: Option }, + ProxyRequestRefused { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-59-bad-request - BadRequest { message: Option }, + BadRequest { + header: String, + message: Option, + }, } impl Permanent { @@ -46,13 +61,24 @@ impl Permanent { .0 } + pub fn header(&self) -> &str { + match self { + Self::Default { header, .. } + | Self::NotFound { header, .. } + | Self::Gone { header, .. } + | Self::ProxyRequestRefused { header, .. } + | Self::BadRequest { header, .. } => header, + } + .as_str() + } + pub fn message(&self) -> Option<&str> { match self { - Self::Default { message } => message, - Self::NotFound { message } => message, - Self::Gone { message } => message, - Self::ProxyRequestRefused { message } => message, - Self::BadRequest { message } => message, + Self::Default { message, .. } + | Self::NotFound { message, .. } + | Self::Gone { message, .. } + | Self::ProxyRequestRefused { message, .. } + | Self::BadRequest { message, .. } => message, } .as_deref() } @@ -80,26 +106,31 @@ impl std::str::FromStr for Permanent { fn from_str(header: &str) -> Result { if let Some(postfix) = header.strip_prefix("50") { return Ok(Self::Default { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("51") { return Ok(Self::NotFound { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("52") { return Ok(Self::Gone { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("53") { return Ok(Self::ProxyRequestRefused { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("59") { return Ok(Self::BadRequest { + header: header.to_string(), message: message(postfix), }); } diff --git a/src/client/connection/response/failure/temporary.rs b/src/client/connection/response/failure/temporary.rs index 768bdcd..c9d8083 100644 --- a/src/client/connection/response/failure/temporary.rs +++ b/src/client/connection/response/failure/temporary.rs @@ -10,15 +10,30 @@ const SLOW_DOWN: (u8, &str) = (44, "Slow down"); /// https://geminiprotocol.net/docs/protocol-specification.gmi#temporary-failure pub enum Temporary { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-40 - Default { message: Option }, + Default { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-41-server-unavailable - ServerUnavailable { message: Option }, + ServerUnavailable { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-42-cgi-error - CgiError { message: Option }, + CgiError { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-43-proxy-error - ProxyError { message: Option }, + ProxyError { + header: String, + message: Option, + }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-44-slow-down - SlowDown { message: Option }, + SlowDown { + header: String, + message: Option, + }, } impl Temporary { @@ -46,13 +61,24 @@ impl Temporary { .0 } + pub fn header(&self) -> &str { + match self { + Self::Default { header, .. } + | Self::ServerUnavailable { header, .. } + | Self::CgiError { header, .. } + | Self::ProxyError { header, .. } + | Self::SlowDown { header, .. } => header, + } + .as_str() + } + pub fn message(&self) -> Option<&str> { match self { - Self::Default { message } => message, - Self::ServerUnavailable { message } => message, - Self::CgiError { message } => message, - Self::ProxyError { message } => message, - Self::SlowDown { message } => message, + Self::Default { message, .. } + | Self::ServerUnavailable { message, .. } + | Self::CgiError { message, .. } + | Self::ProxyError { message, .. } + | Self::SlowDown { message, .. } => message, } .as_deref() } @@ -80,26 +106,31 @@ impl std::str::FromStr for Temporary { fn from_str(header: &str) -> Result { if let Some(postfix) = header.strip_prefix("40") { return Ok(Self::Default { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("41") { return Ok(Self::ServerUnavailable { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("42") { return Ok(Self::CgiError { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("43") { return Ok(Self::ProxyError { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("44") { return Ok(Self::SlowDown { + header: header.to_string(), message: message(postfix), }); } diff --git a/src/client/connection/response/input.rs b/src/client/connection/response/input.rs index b62276b..c524b9a 100644 --- a/src/client/connection/response/input.rs +++ b/src/client/connection/response/input.rs @@ -5,8 +5,14 @@ const DEFAULT: (u8, &str) = (10, "Input"); const SENSITIVE: (u8, &str) = (11, "Sensitive input"); pub enum Input { - Default { message: Option }, - Sensitive { message: Option }, + Default { + header: String, + message: Option, + }, + Sensitive { + header: String, + message: Option, + }, } impl Input { @@ -31,10 +37,16 @@ impl Input { .0 } + pub fn header(&self) -> &str { + match self { + Self::Default { header, .. } | Self::Sensitive { header, .. } => header, + } + .as_str() + } + pub fn message(&self) -> Option<&str> { match self { - Self::Default { message } => message, - Self::Sensitive { message } => message, + Self::Default { message, .. } | Self::Sensitive { message, .. } => message, } .as_deref() } @@ -59,11 +71,13 @@ impl std::str::FromStr for Input { fn from_str(header: &str) -> Result { if let Some(postfix) = header.strip_prefix("10") { return Ok(Self::Default { + header: header.to_string(), message: message(postfix), }); } if let Some(postfix) = header.strip_prefix("11") { return Ok(Self::Sensitive { + header: header.to_string(), message: message(postfix), }); } diff --git a/src/client/connection/response/redirect.rs b/src/client/connection/response/redirect.rs index 2554fdf..cc838df 100644 --- a/src/client/connection/response/redirect.rs +++ b/src/client/connection/response/redirect.rs @@ -8,9 +8,9 @@ const PERMANENT: (u8, &str) = (31, "Permanent redirect"); pub enum Redirect { /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-30-temporary-redirection - Temporary { target: String }, + Temporary { header: String, target: String }, /// https://geminiprotocol.net/docs/protocol-specification.gmi#status-31-permanent-redirection - Permanent { target: String }, + Permanent { header: String, target: String }, } impl Redirect { @@ -87,10 +87,15 @@ impl Redirect { // Getters + pub fn header(&self) -> &str { + match self { + Self::Permanent { header, .. } | Self::Temporary { header, .. } => header, + } + } + pub fn target(&self) -> &str { match self { - Self::Permanent { target } => target, - Self::Temporary { target } => target, + Self::Permanent { target, .. } | Self::Temporary { target, .. } => target, } } } @@ -124,9 +129,11 @@ impl std::str::FromStr for Redirect { match regex.get(1) { Some(code) => match code.as_str() { "0" => Ok(Self::Temporary { + header: header.to_string(), target: target(regex.get(2))?, }), "1" => Ok(Self::Permanent { + header: header.to_string(), target: target(regex.get(2))?, }), _ => todo!(), diff --git a/src/client/connection/response/success.rs b/src/client/connection/response/success.rs index e5ad6f4..f862fd9 100644 --- a/src/client/connection/response/success.rs +++ b/src/client/connection/response/success.rs @@ -4,7 +4,7 @@ pub use error::Error; const DEFAULT: (u8, &str) = (20, "Success"); pub enum Success { - Default { mime: String }, + Default { header: String, mime: String }, // reserved for 2* codes } @@ -30,9 +30,16 @@ impl Success { // Getters + pub fn header(&self) -> &str { + match self { + Self::Default { header, .. } => header, + } + .as_str() + } + pub fn mime(&self) -> &str { match self { - Self::Default { mime } => mime, + Self::Default { mime, .. } => mime, } } } @@ -53,7 +60,6 @@ impl std::str::FromStr for Success { type Err = Error; fn from_str(header: &str) -> Result { use glib::{Regex, RegexCompileFlags, RegexMatchFlags}; - match Regex::split_simple( r"^20\s([^\/]+\/[^\s;]+)", header, @@ -68,6 +74,7 @@ impl std::str::FromStr for Success { Err(Error::Mime) } else { Ok(Self::Default { + header: header.to_string(), mime: mime.to_lowercase(), }) }