use { crate::{response::success, route::track_mount}, tokio::io::{AsyncReadExt, AsyncWriteExt}, windmark::response::Response, }; pub fn module(router: &mut windmark::router::Router) { track_mount(router, "/finger", "Finger-to-Gemini Gateway", |context| { success( &r"# Finger-to-Gemini Gateway To use this gateway, simply append the address of your target resource to the end of the current route, minus the protocol. Routed paths are supported! To visit my personal Finger server, , you would visit . => /finger/fuwn.net Try it!".to_string(), &context, ) }); track_mount( router, "/finger/*uri", "-Finger-to-Gemini Gateway Router", |context| async move { if let Some(uri) = context.parameters.get("uri") { let path; let original_url = { let mut parts = uri.split('/'); let host = parts.next().unwrap(); path = parts.collect::>().join("/"); if host.contains(':') { host.to_string() } else { format!("{host}:79") } }; let url = url::Url::parse(&original_url).unwrap(); let mut stream = tokio::net::TcpStream::connect(url.to_string()).await.unwrap(); let mut buffer = [0; 1024]; stream.write_all(format!("{path}\n").as_bytes()).await.unwrap(); let mut response = String::new(); response.push_str(format!("=> finger://{uri}\n\n").as_str()); response.push_str("```\n"); loop { let bytes_read = match stream.read(&mut buffer).await { Ok(0) => break, Ok(n) => n, Err(e) => { eprintln!("error: failed to read from socket: {e:?}"); break; } }; #[allow(unsafe_code)] response.push_str(&unsafe { let content = std::str::from_utf8_unchecked(&buffer[..bytes_read]) .replace("finger://", "gemini://fuwn.net/finger/"); // let mut lines = content.lines().peekable(); // let mut result = String::new(); // while let Some(line) = lines.next() { // if !line.is_empty() { // result.push_str(line); // if lines // .peek() // .map_or(false, |&next_line| !next_line.is_empty()) // { // result.push(' '); // } else { // result.push('\n'); // } // } else { // result.push('\n'); // } // } // result content }); } response.push_str("\n```"); Response::success(response) } else { Response::bad_request("Invalid URI") } }, ); }