use std::error; use std::fmt; use std::io; use std::thread; use std::time::Duration; use std::{env, sync::Arc}; use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; use rustls::ClientConfig; use rustls_pki_types::{CertificateDer, ServerName, UnixTime}; use ureq; #[derive(Debug)] struct StringError(String); impl error::Error for StringError {} impl fmt::Display for StringError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) } } impl From for StringError { fn from(source: String) -> Self { Self(source) } } #[derive(Debug)] struct Error { source: Box, } impl error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.source) } } impl From for Error { fn from(source: StringError) -> Self { Error { source: source.into(), } } } impl From for Error { fn from(source: ureq::Error) -> Self { Error { source: source.into(), } } } impl From for Error { fn from(source: io::Error) -> Self { Error { source: source.into(), } } } fn perform( agent: &ureq::Agent, method: &str, url: &str, data: &[u8], print_headers: bool, ) -> Result<(), Error> { let req = agent.request(method, url); let response = if method == "GET" && data.len() == 0 { req.call()? } else { req.send_bytes(data)? }; if print_headers { println!( "{} {} {}", response.http_version(), response.status(), response.status_text() ); for h in response.headers_names() { println!("{}: {}", h, response.header(&h).unwrap_or_default()); } println!(); } let mut reader = response.into_reader(); io::copy(&mut reader, &mut io::stdout())?; Ok(()) } #[derive(Debug)] struct AcceptAll {} impl ServerCertVerifier for AcceptAll { fn verify_server_cert( &self, _end_entity: &CertificateDer, _intermediates: &[CertificateDer], _server_name: &ServerName, _ocsp_response: &[u8], _now: UnixTime, ) -> Result { Ok(ServerCertVerified::assertion()) } fn verify_tls12_signature( &self, _message: &[u8], _cert: &CertificateDer<'_>, _dss: &rustls::DigitallySignedStruct, ) -> Result { Ok(HandshakeSignatureValid::assertion()) } fn verify_tls13_signature( &self, _message: &[u8], _cert: &CertificateDer<'_>, _dss: &rustls::DigitallySignedStruct, ) -> Result { Ok(HandshakeSignatureValid::assertion()) } fn supported_verify_schemes(&self) -> Vec { todo!() } } fn main() { match main2() { Ok(()) => {} Err(e) => { eprintln!("{}", e); std::process::exit(1); } } } fn main2() -> Result<(), Error> { let mut args = env::args(); if args.next().is_none() { println!( r##"Usage: {:#?} url [url ...] -i Include headers when printing response -X Use the given request method (GET, POST, etc) -d Use the given data as the request body (useful for POST) --wait Wait n seconds between requests -k Ignore certificate errors -m