diff --git a/Cargo.lock b/Cargo.lock index d16a6ed..1b52ac0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,6 +151,8 @@ name = "libra" version = "0.1.0" dependencies = [ "clap", + "mime", + "percent-encoding", "rustls", "strum", "url", @@ -177,6 +179,12 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + [[package]] name = "once_cell" version = "1.10.0" diff --git a/Cargo.toml b/Cargo.toml index 8e2bb2c..b8cb564 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] +mime = "0.3.16" +percent-encoding = "2.1.0" url = "2.2.2" [dependencies.clap] diff --git a/src/main.rs b/src/main.rs index 0292587..655238a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -116,7 +116,57 @@ fn get_gemini(url: &Url) -> Response { fn main() { let args = Args::parse(); - println!("Connecting to {}", args.url); - let response = get_gemini(&args.url); - println!("Received: {:?}", response); + let mut url = args.url; + let (mime, body) = loop { + println!("Requesting {}", url); + let response = get_gemini(&url); + + use ResponseStatus::*; + match response.status { + Success => { + let mime: mime::Mime = response.meta.parse().unwrap(); + break (mime, response.body); + } + TemporaryRedirect | PermanentRedirect => { + url = response.meta.as_str().try_into().unwrap(); + println!("Redirected to {}", url); + } + Input | SensitiveInput => { + use std::io::Write; + print!("[Input]\n {}\n=> ", response.meta); + std::io::stdout().flush().unwrap(); + + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let input = input.trim(); + + use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode}; + let ascii_set = NON_ALPHANUMERIC; + let encoded = utf8_percent_encode(&input, &ascii_set); + url.set_query(Some(&encoded.to_string())); + }, + e => { + eprintln!("Received error status {}", e); + std::process::exit(1); + } + } + }; + + match mime.type_().as_str() { + "text" => { + let body = String::from_utf8(body).unwrap(); + match mime.subtype().as_str() { + "plain" => println!("Plain text:\n{}", body), + "gemini" => println!("Gemtext:\n{}", body), + _ => { + eprintln!("Unsupported mime type {}", mime); + std::process::exit(1); + } + } + } + mime => { + eprintln!("Unsupported mime type {}", mime); + std::process::exit(1); + } + } }