HSTS (HTTP Strict Transport Security)
aioduct supports automatic HTTP-to-HTTPS upgrade via the Strict-Transport-Security header (RFC 6797). When a server sends this header over HTTPS, subsequent HTTP requests to that domain are transparently upgraded to HTTPS.
Enabling HSTS
Create an HstsStore and pass it to the client builder:
#![allow(unused)]
fn main() {
use aioduct::{TokioClient, HstsStore};
let hsts = HstsStore::new();
let client = TokioClient::builder()
.tls(aioduct::tls::RustlsConnector::with_webpki_roots())
.hsts(hsts)
.build()?;
}
How It Works
- When an HTTPS response contains a
Strict-Transport-Securityheader, the domain and its policy are recorded in the store - On subsequent requests to the same domain over
http://, the URL is transparently upgraded tohttps:// - If the header includes
includeSubDomains, all subdomains of the host are also upgraded - A
max-age=0directive removes the domain from the store
Header Format
Strict-Transport-Security: max-age=31536000
Strict-Transport-Security: max-age=31536000; includeSubDomains
max-age— how long (in seconds) the browser/client should remember to use HTTPSincludeSubDomains— also apply the policy to all subdomains
Subdomain Matching
When includeSubDomains is set for example.com:
http://example.com→ upgraded tohttps://example.comhttp://api.example.com→ upgraded tohttps://api.example.comhttp://deep.sub.example.com→ upgraded tohttps://deep.sub.example.com
Without includeSubDomains, only the exact domain is upgraded.
Host matching is case-insensitive. HstsStore also canonicalizes host inputs with a single port suffix, so storing Example.Com:443 matches later checks for example.com, example.com:80, and subdomains when includeSubDomains is present.
Shared State
HstsStore uses Arc<Mutex<...>> internally, so cloning a store shares state between clients:
#![allow(unused)]
fn main() {
use aioduct::HstsStore;
let store = HstsStore::new();
let store2 = store.clone(); // shares the same data
}
Clearing the Store
#![allow(unused)]
fn main() {
use aioduct::HstsStore;
let store = HstsStore::new();
// ... use with client ...
store.clear();
}