use tokio_gemini::{ certs::{file_sscv::FileBasedCertVerifier, insecure::AllowAllCertVerifier}, dns::DnsClient, Client, LibError, }; // // cargo add tokio_gemini -F file-sscv,hickory // cargo add tokio -F macros,rt-multi-thread,io-util,fs // const USAGE: &str = "-k\t\tinsecure mode (trust all certs) -d \tuse custom DNS for resolving & DANE -h\t\tshow help"; struct Config { insecure: bool, dns: Option, url: String, } #[tokio::main] async fn main() -> Result<(), LibError> { let config = parse_args(); let client = build_client(&config).await?; let mut resp = client.request(&config.url).await?; { let status_code = resp.status().status_code(); let status_num: u8 = status_code.into(); eprintln!("{} {:?}", status_num, status_code); } if resp.status().reply_type() == tokio_gemini::ReplyType::Success { let mime = resp.mime()?; eprintln!("Mime: {}", mime); if mime.type_() == mime::TEXT { println!("{}", resp.text().await?); } else { eprintln!("Downloading into content.bin"); let mut f = tokio::fs::File::create("content.bin").await?; tokio::io::copy(&mut resp.stream(), &mut f).await?; } } else { eprintln!("Message: {}", resp.message()); } Ok(()) } fn parse_args() -> Config { let mut config = Config { insecure: false, dns: None, url: "gemini://geminiprotocol.net/".to_owned(), }; let mut expected_dns = false; for arg in std::env::args().skip(1) { match arg.as_str() { dns if expected_dns => { config.dns = Some(dns.to_owned()); expected_dns = false; } "-k" => config.insecure = true, "-d" => expected_dns = true, "-h" => { println!("{}", USAGE); std::process::exit(0); } url => { println!("URL: {}", url); config.url = url.to_owned(); break; } } } if expected_dns { println!("{}", USAGE); std::process::exit(0); } config } async fn build_client(config: &Config) -> Result { let dns = if let Some(addr) = &config.dns { Some(DnsClient::init(addr).await?) } else { None }; let client = tokio_gemini::Client::builder(); let client = if config.insecure { client.with_custom_verifier(AllowAllCertVerifier::yes_i_know_what_i_am_doing()) } else { client.with_selfsigned_cert_verifier( FileBasedCertVerifier::init("known_hosts", dns.clone()).await?, ) }; let client = if let Some(dns) = dns { client.with_dns_client(dns) } else { client }; Ok(client.build()) }