From 4667b10c0a720f996110060fa456f491635b87d2 Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Mon, 25 Jan 2021 16:35:15 +0100 Subject: [PATCH] feat: http/2 + tls support --- Cargo.lock | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 +- src/config.rs | 12 ++++++++++++ src/server.rs | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ 4 files changed, 263 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67707c0..ec68c17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,6 +171,12 @@ dependencies = [ ] [[package]] +name = "bumpalo" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07aa6688c702439a1be0307b6a94dffe1168569e45b9500c1372bc580740d59" + +[[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -597,6 +603,15 @@ dependencies = [ ] [[package]] +name = "js-sys" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" +dependencies = [ + "wasm-bindgen", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1011,6 +1026,34 @@ dependencies = [ ] [[package]] +name = "ring" +version = "0.16.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "024a1e66fea74c66c66624ee5622a7ff0e4b73a13b4f5c326ddb50c708944226" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustls" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b" +dependencies = [ + "base64", + "log", + "ring", + "sct", + "webpki", +] + +[[package]] name = "ryu" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1029,6 +1072,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] +name = "sct" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] name = "serde" version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1125,6 +1178,12 @@ dependencies = [ ] [[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] name = "static-web-server" version = "2.0.0-beta.1" dependencies = [ @@ -1254,6 +1313,17 @@ dependencies = [ ] [[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] name = "tokio-stream" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1471,6 +1541,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] name = "url" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1538,6 +1614,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "tokio", + "tokio-rustls", "tokio-stream", "tokio-tungstenite", "tokio-util", @@ -1559,6 +1636,80 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9" [[package]] +name = "wasm-bindgen" +version = "0.2.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" + +[[package]] +name = "web-sys" +version = "0.3.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index 1a6f913..1ba0b47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ path = "src/bin/server.rs" [dependencies] tokio = { version = "1", features = ["rt-multi-thread"] } -warp = { git = "https://github.com/joseluisq/warp.git", branch = "0.3.x", features = ["compression"] } +warp = { git = "https://github.com/joseluisq/warp.git", branch = "0.3.x", features = ["tls","compression"] } anyhow = "1.0" tracing = "0.1" tracing-subscriber = "0.2" diff --git a/src/config.rs b/src/config.rs index 7631c96..4589e6d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -60,4 +60,16 @@ pub struct Config { )] /// Specify a optional CORS list of allowed origin hosts separated by comas. Host ports or protocols aren't being checked. Use an asterisk (*) to allow any host. pub cors_allow_origins: String, + + #[structopt(long, short = "t", env = "SERVER_HTTP2_TLS")] + /// Enables HTTP/2 with TLS support. + pub http2: bool, + + #[structopt(long, default_value = "", env = "SERVER_HTTP2_TLS_CERT")] + /// Specify the file path to read the certificate. + pub http2_tls_cert: String, + + #[structopt(long, default_value = "", env = "SERVER_HTTP2_TLS_KEY")] + /// Specify the file path to read the private key. + pub http2_tls_key: String, } diff --git a/src/server.rs b/src/server.rs index e0ce105..ced7479 100644 --- a/src/server.rs +++ b/src/server.rs @@ -75,6 +75,11 @@ impl Server { // Public GET endpoint (default) let public_get_default = warp::get().and(base_dir_filter.clone()); + // HTTP/2 + TLS + let http2 = opts.http2; + let http2_tls_cert_path = opts.http2_tls_cert; + let http2_tls_key_path = opts.http2_tls_key; + // Public GET/HEAD endpoints with compression (deflate, gzip, brotli, none) match opts.compression.as_ref() { "brotli" => tokio::task::spawn(async move { @@ -93,24 +98,40 @@ impl Server { cors_enabled = ?true, allowed_origins = ?cors_allowed_origins ); - warp::serve( + let server = warp::serve( public_head.with(cors_filter.clone()).or(warp::get() .and(filters::has_accept_encoding("br")) .and(with_dir) .with(cors_filter.clone()) .or(public_get_default.with(cors_filter))), - ) - .run(addr) - .await + ); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } else { - warp::serve( + let server = warp::serve( public_head.or(warp::get() .and(filters::has_accept_encoding("br")) .and(with_dir) .or(public_get_default)), - ) - .run(addr) - .await + ); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } }), "deflate" => tokio::task::spawn(async move { @@ -129,24 +150,40 @@ impl Server { cors_enabled = ?true, allowed_origins = ?cors_allowed_origins ); - warp::serve( + let server = warp::serve( public_head.with(cors_filter.clone()).or(warp::get() .and(filters::has_accept_encoding("deflate")) .and(with_dir) .with(cors_filter.clone()) .or(public_get_default.with(cors_filter))), - ) - .run(addr) - .await + ); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } else { - warp::serve( + let server = warp::serve( public_head.or(warp::get() .and(filters::has_accept_encoding("deflate")) .and(with_dir) .or(public_get_default)), - ) - .run(addr) - .await + ); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } }), "gzip" => tokio::task::spawn(async move { @@ -165,24 +202,40 @@ impl Server { cors_enabled = ?true, allowed_origins = ?cors_allowed_origins ); - warp::serve( + let server = warp::serve( public_head.with(cors_filter.clone()).or(warp::get() .and(filters::has_accept_encoding("gzip")) .and(with_dir) .with(cors_filter.clone()) .or(public_get_default.with(cors_filter))), - ) - .run(addr) - .await + ); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } else { - warp::serve( + let server = warp::serve( public_head.or(warp::get() .and(filters::has_accept_encoding("gzip")) .and(with_dir) .or(public_get_default)), - ) - .run(addr) - .await + ); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } }), _ => tokio::task::spawn(async move { @@ -194,13 +247,29 @@ impl Server { let public_get_default = warp::get() .and(base_dir_filter.clone()) .with(cors_filter.clone()); - warp::serve(public_head.or(public_get_default.with(cors_filter))) - .run(addr) - .await + let server = warp::serve(public_head.or(public_get_default.with(cors_filter))); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } else { - warp::serve(public_head.or(public_get_default)) - .run(addr) - .await + let server = warp::serve(public_head.or(public_get_default)); + if http2 { + server + .tls() + .cert_path(http2_tls_cert_path) + .key_path(http2_tls_key_path) + .run(addr) + .await; + } else { + server.run(addr).await + } } }), }; -- libgit2 1.7.2