diff --git a/README.md b/README.md index 05eb17eeb..983426841 100644 --- a/README.md +++ b/README.md @@ -197,9 +197,10 @@ Ohkami::new(( ``` `.howls()` (`tls` feature only) is used to run Ohkami with TLS (HTTPS) support -with [`rustls`](https://github.com/rustls) ecosystem (described in `tls` feature section). +with `tokio` and [`rustls`](https://github.com/rustls) ecosystem +(currently `rt_tokio` only / described in `tls` feature section). -`howl(s)` supports graceful shutdown by `Ctrl-C` or `SIGTERM` signal on native runtimes. +`howl(s)` supports graceful shutdown by `Ctrl-C` ( `SIGINT` ) on native runtimes. @@ -309,9 +310,6 @@ async fn main() { ### `"ws"` : WebSocket -Ohkami only handles `ws://`.\ -Use some reverse proxy to do with `wss://`. - ```rust,no_run use ohkami::{Ohkami, Route}; use ohkami::ws::{WebSocketContext, WebSocket, Message}; @@ -443,7 +441,7 @@ $ openssl req -x509 -newkey rsa:4096 -nodes -keyout server.key -out server.crt - [dependencies] ohkami = { version = "0.24", features = ["rt_tokio", "tls"] } tokio = { version = "1", features = ["full"] } -rustls = { version = "0.22", features = ["ring"] } +rustls = { version = "0.23", features = ["ring"] } rustls-pemfile = "2.2" ``` diff --git a/examples/websocket/.gitignore b/examples/websocket/.gitignore new file mode 100644 index 000000000..fca5b1335 --- /dev/null +++ b/examples/websocket/.gitignore @@ -0,0 +1 @@ +/*.pem diff --git a/examples/websocket/Cargo.toml b/examples/websocket/Cargo.toml index 3e2c463a3..a60e51167 100644 --- a/examples/websocket/Cargo.toml +++ b/examples/websocket/Cargo.toml @@ -4,8 +4,11 @@ version = "0.1.0" edition = "2024" [dependencies] -ohkami = { workspace = true } -tokio = { workspace = true } +ohkami = { workspace = true } +tokio = { workspace = true } +rustls = { optional = true, version = "0.23", features = ["ring"] } +rustls-pemfile = { optional = true, version = "2.2" } [features] +tls = ["ohkami/tls", "dep:rustls", "dep:rustls-pemfile"] DEBUG = ["ohkami/DEBUG"] \ No newline at end of file diff --git a/examples/websocket/README.md b/examples/websocket/README.md new file mode 100644 index 000000000..cd4a2a6c1 --- /dev/null +++ b/examples/websocket/README.md @@ -0,0 +1,16 @@ +# WebSocket Example + +## Feature flags description + +- `DEBUG`: Enables Ohkami's debug logging. +- `tls`: Enables TLS support ( https://, wss:// ). + +## Prerequisites + +If you want to run this example with TLS support, you need to have +[`mkcert`](https://github.com/FiloSottile/mkcert) and run: + +```sh +# assuming you have mkcert installed and `mkcert -install` has already executed: +mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 +``` diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index 7f40d0761..fe51e5956 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -143,11 +143,54 @@ async fn main() { } } - Ohkami::new((Logger, - "/".Mount("./template").omit_extensions(&[".html"]), + #[cfg(feature="tls")] + let tls_config = { + use rustls::ServerConfig; + use rustls::pki_types::{CertificateDer, PrivateKeyDer}; + use std::fs::File; + use std::io::BufReader; + + // Initialize rustls crypto provider + rustls::crypto::ring::default_provider().install_default() + .expect("Failed to install rustls crypto provider"); + + // Load certificates and private key + let cert_file = File::open("./cert.pem").expect("Failed to open certificate file"); + let key_file = File::open("./key.pem").expect("Failed to open private key file"); + + let cert_chain = rustls_pemfile::certs(&mut BufReader::new(cert_file)) + .map(|cd| cd.map(CertificateDer::from)) + .collect::, _>>() + .expect("Failed to read certificate chain"); + + let key = rustls_pemfile::read_one(&mut BufReader::new(key_file)) + .expect("Failed to read private key") + .map(|p| match p { + rustls_pemfile::Item::Pkcs1Key(k) => PrivateKeyDer::Pkcs1(k), + rustls_pemfile::Item::Pkcs8Key(k) => PrivateKeyDer::Pkcs8(k), + _ => panic!("Unexpected private key type"), + }) + .expect("Failed to read private key"); + + // Build TLS configuration + ServerConfig::builder() + .with_no_client_auth() + .with_single_cert(cert_chain, key) + .expect("Failed to build TLS configuration") + }; + + let o = Ohkami::new(( + Logger, + "/".Mount("./template").omit_extensions(&["html"]), "/echo1".GET(echo_text), "/echo2/:name".GET(echo_text_2), "/echo3/:name".GET(echo_text_3), "/echo4/:name".GET(echo4), - )).howl("localhost:3030").await + )); + + #[cfg(not(feature="tls"))] + o.howl("localhost:3030").await; + + #[cfg(feature="tls")] + o.howls("localhost:3030", tls_config).await; } diff --git a/examples/websocket/template/index.html b/examples/websocket/template/index.html index 64683d94f..4248dc8c2 100644 --- a/examples/websocket/template/index.html +++ b/examples/websocket/template/index.html @@ -26,7 +26,13 @@ - Echo Text + Echo Text Sample + + + Press connect and see dev console. + Type some text and press send. + Finally send close to finish the connection. + @@ -49,53 +55,16 @@ Echo Text - -
connect
send
close