2024-08-21 16:01:21 +04:00
|
|
|
use async_trait::async_trait;
|
2024-08-06 12:32:42 +04:00
|
|
|
use tokio_gemini::{
|
2024-08-15 17:47:43 +04:00
|
|
|
certs::{fingerprint::CertFingerprint, SelfsignedCertVerifier},
|
2024-08-06 12:32:42 +04:00
|
|
|
Client, LibError,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Much simpler than examples/main.rs
|
|
|
|
// Hardcoded URL, no cert check, always write to stdout
|
|
|
|
//
|
|
|
|
// cargo add tokio-gemini
|
|
|
|
// cargo add tokio -F macros,rt-multi-thread
|
|
|
|
//
|
|
|
|
|
|
|
|
const URL: &str = "gemini://geminiprotocol.net/docs/protocol-specification.gmi";
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<(), LibError> {
|
|
|
|
let client = Client::builder()
|
|
|
|
.with_selfsigned_cert_verifier(CertVerifier)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
match client.request(URL).await?.ensure_ok() {
|
|
|
|
Ok(mut resp) => {
|
|
|
|
println!("{}", resp.text().await?);
|
|
|
|
}
|
|
|
|
Err(resp) => {
|
|
|
|
println!("{} {}", resp.status().num(), resp.message());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CertVerifier;
|
|
|
|
|
2024-08-21 16:01:21 +04:00
|
|
|
#[async_trait]
|
2024-08-06 12:32:42 +04:00
|
|
|
impl SelfsignedCertVerifier for CertVerifier {
|
2024-08-21 16:01:21 +04:00
|
|
|
async fn verify(
|
2024-08-06 12:32:42 +04:00
|
|
|
&self,
|
2024-08-21 16:01:21 +04:00
|
|
|
cert: &tokio_gemini::certs::CertificateDer<'_>,
|
2024-08-06 12:32:42 +04:00
|
|
|
host: &str,
|
2024-08-21 15:46:52 +04:00
|
|
|
port: u16,
|
|
|
|
) -> Result<bool, tokio_gemini::LibError> {
|
|
|
|
// For real verification example with known_hosts and DANE
|
2024-08-06 12:32:42 +04:00
|
|
|
// see examples/main.rs
|
|
|
|
eprintln!(
|
2024-08-21 15:46:52 +04:00
|
|
|
"Host = {}:{}\nFingerprint = {}",
|
2024-08-06 12:32:42 +04:00
|
|
|
host,
|
2024-08-21 15:46:52 +04:00
|
|
|
port,
|
2024-08-15 17:47:43 +04:00
|
|
|
CertFingerprint::new_sha256(cert).base64(),
|
2024-08-06 12:32:42 +04:00
|
|
|
);
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
}
|