docs: add doc-comments to lib.rs and client
This commit is contained in:
parent
307e54f256
commit
39b1009048
3 changed files with 57 additions and 3 deletions
|
@ -20,12 +20,15 @@ pub struct ClientBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ClientBuilder {
|
impl Default for ClientBuilder {
|
||||||
|
/// Same as [`ClientBuilder::new()`].
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientBuilder {
|
impl ClientBuilder {
|
||||||
|
/// Instantiate a builder with empty [`rustls::RootCertStore`],
|
||||||
|
/// no cert verifiers and default TLS versions.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ClientBuilder {
|
ClientBuilder {
|
||||||
root_certs: rustls::RootCertStore::empty(),
|
root_certs: rustls::RootCertStore::empty(),
|
||||||
|
@ -35,6 +38,7 @@ impl ClientBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a [`Client`] from the configuration.
|
||||||
pub fn build(self) -> Client {
|
pub fn build(self) -> Client {
|
||||||
let provider = rustls::crypto::CryptoProvider::get_default()
|
let provider = rustls::crypto::CryptoProvider::get_default()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -82,12 +86,17 @@ impl ClientBuilder {
|
||||||
Client::from(tls_config)
|
Client::from(tls_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Include webpki trust anchors.
|
||||||
|
/// Not recommended (useless) as most Gemini capsules use self-signed
|
||||||
|
/// TLS certs and properly configured TOFU policy is enough.
|
||||||
pub fn with_webpki_roots(mut self) -> Self {
|
pub fn with_webpki_roots(mut self) -> Self {
|
||||||
self.root_certs
|
self.root_certs
|
||||||
.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Include custom trust anchors.
|
||||||
|
/// Not recommended (useless), see note for [`ClientBuilder::with_webpki_roots`].
|
||||||
pub fn with_custom_roots(
|
pub fn with_custom_roots(
|
||||||
mut self,
|
mut self,
|
||||||
iter: impl IntoIterator<Item = TrustAnchor<'static>>,
|
iter: impl IntoIterator<Item = TrustAnchor<'static>>,
|
||||||
|
@ -96,6 +105,10 @@ impl ClientBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Include a self-signed cert verifier.
|
||||||
|
/// If you only need a known_hosts file, consider using
|
||||||
|
/// [`crate::certs::file_sscv::FileBasedCertVerifier`],
|
||||||
|
/// it will do all the work for you.
|
||||||
pub fn with_selfsigned_cert_verifier(
|
pub fn with_selfsigned_cert_verifier(
|
||||||
mut self,
|
mut self,
|
||||||
ss_verifier: impl SelfsignedCertVerifier + 'static,
|
ss_verifier: impl SelfsignedCertVerifier + 'static,
|
||||||
|
@ -104,6 +117,10 @@ impl ClientBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Include a custom TLS cert verifier implementing rustls' [`ServerCertVerifier`].
|
||||||
|
/// Normally need to be used only for [`crate::certs::insecure::AllowAllCertVerifier`].
|
||||||
|
/// Note: the webpki verifier and a self-signed cert verifier are not called
|
||||||
|
/// when a custom verifier is set.
|
||||||
pub fn with_custom_verifier(
|
pub fn with_custom_verifier(
|
||||||
mut self,
|
mut self,
|
||||||
custom_verifier: impl ServerCertVerifier + 'static,
|
custom_verifier: impl ServerCertVerifier + 'static,
|
||||||
|
@ -112,6 +129,8 @@ impl ClientBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Limit the supported TLS versions list to the specified ones.
|
||||||
|
/// Default is [`rustls::DEFAULT_VERSIONS`].
|
||||||
pub fn with_tls_versions(
|
pub fn with_tls_versions(
|
||||||
mut self,
|
mut self,
|
||||||
versions: &'static [&'static SupportedProtocolVersion],
|
versions: &'static [&'static SupportedProtocolVersion],
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Everything related to Gemini client except cert verification
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
|
|
||||||
use crate::{error::*, response::Response, status::*};
|
use crate::{error::*, response::Response, status::*};
|
||||||
|
@ -21,6 +23,8 @@ pub struct Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Client {
|
impl Default for Client {
|
||||||
|
/// Create a Client with webpki_roots trust anchors and no client auth cert.
|
||||||
|
/// Will be possibly removed in next versions.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let roots =
|
let roots =
|
||||||
rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||||
|
@ -32,6 +36,7 @@ impl Default for Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<rustls::ClientConfig> for Client {
|
impl From<rustls::ClientConfig> for Client {
|
||||||
|
/// Create a Client from a Rustls config.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(config: rustls::ClientConfig) -> Self {
|
fn from(config: rustls::ClientConfig) -> Self {
|
||||||
Client {
|
Client {
|
||||||
|
@ -41,18 +46,30 @@ impl From<rustls::ClientConfig> for Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
|
/// Create a Client with a customized configuration,
|
||||||
|
/// see [`ClientBuilder`] methods.
|
||||||
pub fn builder() -> ClientBuilder {
|
pub fn builder() -> ClientBuilder {
|
||||||
ClientBuilder::new()
|
ClientBuilder::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
|
/// Parse the given URL, do some checks,
|
||||||
|
/// take host and port (default is 1965) from the URL
|
||||||
|
/// and perform a Gemini request, returning [`Response`] on success.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Everything is converted into [`LibError`].
|
||||||
|
/// - [`InvalidUrl::ParseError`] means that the given URL cannot be parsed.
|
||||||
|
/// - [`InvalidUrl::SchemeNotGemini`] is returned when the scheme is not `gemini://`
|
||||||
|
/// (for proxying use [`Client::request_with_host`]).
|
||||||
|
/// - [`InvalidUrl::UserinfoPresent`] is returned when the URL contains userinfo -- `user:password@` --
|
||||||
|
/// which is forbidden by the Gemini specs.
|
||||||
|
/// - For the rest, see [`Client::request_with_host`].
|
||||||
pub async fn request(&self, url_str: &str) -> Result<Response, LibError> {
|
pub async fn request(&self, url_str: &str) -> Result<Response, LibError> {
|
||||||
let url = Url::parse(url_str).map_err(InvalidUrl::ParseError)?;
|
let url = Url::parse(url_str).map_err(InvalidUrl::ParseError)?;
|
||||||
// for proxying http(s) through gemini server,
|
// deny non-Gemini requests
|
||||||
// use Client::request_with_host
|
|
||||||
if url.scheme() != "gemini" {
|
if url.scheme() != "gemini" {
|
||||||
// deny non-Gemini req
|
|
||||||
return Err(InvalidUrl::SchemeNotGemini.into());
|
return Err(InvalidUrl::SchemeNotGemini.into());
|
||||||
}
|
}
|
||||||
// userinfo (user:pswd@) is not allowed in Gemini
|
// userinfo (user:pswd@) is not allowed in Gemini
|
||||||
|
@ -66,6 +83,21 @@ impl Client {
|
||||||
self.request_with_host(url_str, host, port).await
|
self.request_with_host(url_str, host, port).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform a Gemini request with the specified host, port and URL.
|
||||||
|
/// Non-`gemini://` URLs is OK if the remote server supports proxying.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Everything is converted into [`LibError`].
|
||||||
|
/// - [`InvalidUrl::ConvertError`] is an error while converting
|
||||||
|
/// host and port into [`std::net::SocketAddr`] or [`pki_types::ServerName`].
|
||||||
|
/// - [`std::io::Error`] is returned in nearly all cases:
|
||||||
|
/// could not open a TCP connection, perform a TLS handshake,
|
||||||
|
/// write to or read from the TCP stream.
|
||||||
|
/// Check the inner error if you need to determine what exactly happened
|
||||||
|
/// - [`LibError::StatusOutOfRange`] means that a server returned an incorrect status code
|
||||||
|
/// (less than 10 or greater than 69).
|
||||||
|
/// - [`LibError::MessageNotUtf8`] is returned when metadata (the text after the status code)
|
||||||
|
/// is not in UTF-8 and cannot be converted to string without errors.
|
||||||
pub async fn request_with_host(
|
pub async fn request_with_host(
|
||||||
&self,
|
&self,
|
||||||
url_str: &str,
|
url_str: &str,
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
//! Gemini client and server implementaion in async Rust with Tokio and Rustls.
|
||||||
|
//! You probably need [`Client::builder()`]
|
||||||
|
|
||||||
pub mod certs;
|
pub mod certs;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
Loading…
Add table
Reference in a new issue