diff --git a/README-websocket.md b/README-websocket.md index c15fa58..3c6ac31 100644 --- a/README-websocket.md +++ b/README-websocket.md @@ -168,10 +168,13 @@ bool is_open() const; // Timeouts void set_read_timeout(time_t sec, time_t usec = 0); void set_write_timeout(time_t sec, time_t usec = 0); +void set_connection_timeout(time_t sec, time_t usec = 0); template void set_read_timeout(const std::chrono::duration &duration); template void set_write_timeout(const std::chrono::duration &duration); +template +void set_connection_timeout(const std::chrono::duration &duration); // SSL configuration (wss:// only, requires CPPHTTPLIB_OPENSSL_SUPPORT) void set_ca_cert_path(const std::string &ca_cert_file_path, @@ -304,8 +307,14 @@ httplib::Headers headers = { }; httplib::ws::WebSocketClient ws("ws://localhost:8080/ws", headers); -ws.set_read_timeout(30, 0); // 30 seconds -ws.set_write_timeout(10, 0); // 10 seconds +ws.set_connection_timeout(5, 0); // 5 seconds +ws.set_read_timeout(30, 0); // 30 seconds +ws.set_write_timeout(10, 0); // 10 seconds + +// std::chrono is also supported +ws.set_connection_timeout(std::chrono::seconds(5)); +ws.set_read_timeout(std::chrono::seconds(30)); +ws.set_write_timeout(std::chrono::seconds(10)); if (ws.connect()) { std::string msg; diff --git a/README.md b/README.md index 8155b22..0fc69aa 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,41 @@ cli.set_server_certificate_verifier( }); ``` +### Mutual TLS (mTLS) + +Regular TLS only verifies the server certificate. With mTLS, the client also presents a certificate that the server verifies. + +```c++ +// Server: pass a CA to verify client certificates against +httplib::SSLServer svr("./cert.pem", "./key.pem", "./client-ca-cert.pem"); + +// Client: present a certificate +httplib::SSLClient cli("api.example.com", 443, + "./client-cert.pem", "./client-key.pem"); +``` + +Both `SSLServer` and `SSLClient` also accept an in-memory `PemMemory` struct instead of file paths — handy when certs come from an environment variable or a secrets manager: + +```c++ +httplib::SSLServer::PemMemory server_pem{}; +server_pem.cert_pem = server_cert.data(); +server_pem.cert_pem_len = server_cert.size(); +server_pem.key_pem = server_key.data(); +server_pem.key_pem_len = server_key.size(); +server_pem.client_ca_pem = client_ca.data(); +server_pem.client_ca_pem_len = client_ca.size(); +httplib::SSLServer svr(server_pem); + +httplib::SSLClient::PemMemory client_pem{}; +client_pem.cert_pem = client_cert.data(); +client_pem.cert_pem_len = client_cert.size(); +client_pem.key_pem = client_key.data(); +client_pem.key_pem_len = client_key.size(); +httplib::SSLClient cli("api.example.com", 443, client_pem); +``` + +`httplib::ws::WebSocketClient` has the same `PemMemory` constructor for `wss://` connections. See [README-websocket.md](README-websocket.md) for details. + ### Peer Certificate Inspection On the server side, you can inspect the client's peer certificate from a request handler: @@ -1290,6 +1325,8 @@ res->status; // 200 cli.set_interface("eth0"); // Interface name, IP address or host name ``` +The same method is available on `httplib::ws::WebSocketClient`. + ### Override the connection target for a hostname `set_hostname_addr_map` redirects where the socket connects, without changing