parent
b44fd575a9
commit
7a1a2297d4
@ -1,13 +1,13 @@ |
||||
pub mod acme; |
||||
pub mod checker; |
||||
mod config; |
||||
pub mod gemini; |
||||
pub mod manager; |
||||
mod name; |
||||
mod settings; |
||||
pub mod store; |
||||
mod tls; |
||||
|
||||
mod config; |
||||
mod name; |
||||
mod settings; |
||||
pub use config::*; |
||||
pub use name::*; |
||||
pub use settings::*; |
||||
|
@ -0,0 +1,131 @@ |
||||
use crate::error::unexpected::{self, Mappable}; |
||||
use serde::{Deserialize, Serialize}; |
||||
|
||||
fn addr_from_url( |
||||
url: &str, |
||||
expected_scheme: &str, |
||||
default_port: u16, |
||||
) -> unexpected::Result<String> { |
||||
let parsed: http::Uri = url |
||||
.parse() |
||||
.map_unexpected_while(|| format!("could not parse as url"))?; |
||||
|
||||
let scheme = parsed |
||||
.scheme() |
||||
.map_unexpected_while(|| format!("scheme is missing"))?; |
||||
|
||||
if scheme != expected_scheme { |
||||
return Err(unexpected::Error::from( |
||||
format!("scheme should be {expected_scheme}").as_str(), |
||||
)); |
||||
} |
||||
|
||||
if let Some(path_and_query) = parsed.path_and_query() { |
||||
let path_and_query = path_and_query.as_str(); |
||||
if path_and_query != "" && path_and_query != "/" { |
||||
return Err(unexpected::Error::from( |
||||
format!("path must be empty").as_str(), |
||||
)); |
||||
} |
||||
} |
||||
|
||||
match parsed.authority() { |
||||
None => Err(unexpected::Error::from(format!("host is missing").as_str())), |
||||
Some(authority) => { |
||||
let port = authority.port().map(|p| p.as_u16()).unwrap_or(default_port); |
||||
Ok(format!("{}:{port}", authority.host())) |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[derive(Deserialize, Serialize, Clone)] |
||||
pub struct GeminiUrl { |
||||
pub original_url: String, |
||||
pub addr: String, |
||||
} |
||||
|
||||
impl TryFrom<String> for GeminiUrl { |
||||
type Error = unexpected::Error; |
||||
fn try_from(url: String) -> Result<Self, Self::Error> { |
||||
let addr = addr_from_url(&url, "gemini", 1965)?; |
||||
Ok(Self { |
||||
original_url: url, |
||||
addr, |
||||
}) |
||||
} |
||||
} |
||||
|
||||
impl From<GeminiUrl> for String { |
||||
fn from(u: GeminiUrl) -> Self { |
||||
u.original_url |
||||
} |
||||
} |
||||
|
||||
#[derive(Deserialize, Serialize, Clone)] |
||||
pub struct HttpUrl { |
||||
pub original_url: String, |
||||
pub addr: String, |
||||
} |
||||
|
||||
impl TryFrom<String> for HttpUrl { |
||||
type Error = unexpected::Error; |
||||
fn try_from(url: String) -> Result<Self, Self::Error> { |
||||
let addr = addr_from_url(&url, "http", 80)?; |
||||
Ok(Self { |
||||
original_url: url, |
||||
addr, |
||||
}) |
||||
} |
||||
} |
||||
|
||||
impl From<HttpUrl> for String { |
||||
fn from(u: HttpUrl) -> Self { |
||||
u.original_url |
||||
} |
||||
} |
||||
|
||||
#[derive(Deserialize, Serialize, Clone)] |
||||
pub struct HttpRequestHeader { |
||||
name: String, |
||||
value: String, |
||||
} |
||||
|
||||
#[derive(Clone)] |
||||
pub struct HttpRequestHeaders(pub http::header::HeaderMap); |
||||
|
||||
impl Default for HttpRequestHeaders { |
||||
fn default() -> Self { |
||||
Self(http::header::HeaderMap::default()) |
||||
} |
||||
} |
||||
|
||||
impl TryFrom<HttpRequestHeaders> for Vec<HttpRequestHeader> { |
||||
type Error = http::header::ToStrError; |
||||
|
||||
fn try_from(h: HttpRequestHeaders) -> Result<Self, Self::Error> { |
||||
let mut v = vec![]; |
||||
for (name, value) in &h.0 { |
||||
v.push(HttpRequestHeader { |
||||
name: name.to_string(), |
||||
value: value.to_str()?.to_string(), |
||||
}) |
||||
} |
||||
Ok(v) |
||||
} |
||||
} |
||||
|
||||
impl TryFrom<Vec<HttpRequestHeader>> for HttpRequestHeaders { |
||||
type Error = unexpected::Error; |
||||
|
||||
fn try_from(v: Vec<HttpRequestHeader>) -> Result<Self, Self::Error> { |
||||
use http::header::{HeaderMap, HeaderName, HeaderValue}; |
||||
|
||||
let mut h = HeaderMap::new(); |
||||
for pair in v { |
||||
let name: HeaderName = pair.name.parse().or_unexpected()?; |
||||
let value: HeaderValue = pair.value.parse().or_unexpected()?; |
||||
h.insert(name, value); |
||||
} |
||||
Ok(Self(h)) |
||||
} |
||||
} |
@ -1,79 +1,20 @@ |
||||
use crate::domain; |
||||
use crate::error::unexpected::{self, Mappable}; |
||||
|
||||
use serde::{Deserialize, Serialize}; |
||||
use serde_with::{serde_as, TryFromInto}; |
||||
|
||||
use std::{collections, net, str::FromStr}; |
||||
use std::net; |
||||
|
||||
fn default_gemini_addr() -> Option<net::SocketAddr> { |
||||
Some(net::SocketAddr::from_str("[::]:3965").unwrap()) |
||||
} |
||||
|
||||
#[derive(Deserialize, Serialize, Clone)] |
||||
pub struct ConfigProxiedDomainUrl { |
||||
pub url: String, |
||||
pub addr: String, |
||||
} |
||||
|
||||
impl From<ConfigProxiedDomainUrl> for String { |
||||
fn from(url: ConfigProxiedDomainUrl) -> Self { |
||||
url.url |
||||
} |
||||
} |
||||
|
||||
impl TryFrom<String> for ConfigProxiedDomainUrl { |
||||
type Error = unexpected::Error; |
||||
|
||||
fn try_from(url: String) -> Result<Self, Self::Error> { |
||||
// use http's implementation, should be the same
|
||||
let parsed = http::Uri::from_str(url.as_str()) |
||||
.map_unexpected_while(|| format!("parsing proxy url {url}"))?; |
||||
|
||||
let scheme = parsed.scheme().map_unexpected_while(|| { |
||||
format!("expected a scheme of gemini in the proxy url {url}") |
||||
})?; |
||||
|
||||
if scheme != "gemini" { |
||||
return Err(unexpected::Error::from( |
||||
format!("scheme of proxy url {url} should be 'gemini'",).as_str(), |
||||
)); |
||||
} |
||||
|
||||
match parsed.authority() { |
||||
None => Err(unexpected::Error::from( |
||||
format!("proxy url {url} should have a host",).as_str(), |
||||
)), |
||||
Some(authority) => { |
||||
let port = authority.port().map(|p| p.as_u16()).unwrap_or(1965); |
||||
Ok(ConfigProxiedDomainUrl { |
||||
url: url, |
||||
addr: format!("{}:{port}", authority.host()), |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[serde_as] |
||||
#[derive(Deserialize, Serialize, Clone)] |
||||
pub struct ConfigProxiedDomain { |
||||
#[serde_as(as = "TryFromInto<String>")] |
||||
pub url: ConfigProxiedDomainUrl, |
||||
Some("[::]:3965".parse().unwrap()) |
||||
} |
||||
|
||||
#[derive(Deserialize, Serialize, Clone)] |
||||
pub struct Config { |
||||
#[serde(default = "default_gemini_addr")] |
||||
pub gemini_addr: Option<net::SocketAddr>, |
||||
pub proxied_domains: collections::HashMap<domain::Name, ConfigProxiedDomain>, |
||||
} |
||||
|
||||
impl Default for Config { |
||||
fn default() -> Self { |
||||
Self { |
||||
gemini_addr: default_gemini_addr(), |
||||
proxied_domains: Default::default(), |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue