diff --git a/contrib/db_pools/lib/src/config.rs b/contrib/db_pools/lib/src/config.rs index 8d45ea63fc..cd423e7a47 100644 --- a/contrib/db_pools/lib/src/config.rs +++ b/contrib/db_pools/lib/src/config.rs @@ -50,7 +50,7 @@ use rocket::serde::{Deserialize, Serialize}; /// For higher-level details on configuring a database, see the [crate-level /// docs](crate#configuration). // NOTE: Defaults provided by the figment created in the `Initializer` fairing. -#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(crate = "rocket::serde")] pub struct Config { /// Database-specific connection and configuration URL. @@ -93,3 +93,28 @@ pub struct Config { /// _Default:_ `None`. pub extensions: Option>, } + +impl Default for Config { + fn default() -> Self { + Self { + url: Default::default(), + min_connections: Default::default(), + max_connections: rocket::Config::default().workers * 4, + connect_timeout: 5, + idle_timeout: Default::default(), + extensions: Default::default(), + } + } +} + +#[cfg(test)] +mod tests { + use super::Config; + + #[test] + fn default_values_sane() { + let config = Config::default(); + assert_ne!(config.max_connections, 0); + assert_eq!(config.connect_timeout, 5); + } +} diff --git a/contrib/db_pools/lib/src/pool.rs b/contrib/db_pools/lib/src/pool.rs index b37fecced4..3d54dc485d 100644 --- a/contrib/db_pools/lib/src/pool.rs +++ b/contrib/db_pools/lib/src/pool.rs @@ -276,14 +276,12 @@ mod sqlx { } } - sqlx::pool::PoolOptions::new() + Ok(sqlx::pool::PoolOptions::new() .max_connections(config.max_connections as u32) .acquire_timeout(Duration::from_secs(config.connect_timeout)) .idle_timeout(config.idle_timeout.map(Duration::from_secs)) .min_connections(config.min_connections.unwrap_or_default()) - .connect_with(opts) - .await - .map_err(Error::Init) + .connect_lazy_with(opts)) } async fn get(&self) -> Result { diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs index 86950c2428..d81d3e58c6 100644 --- a/core/http/src/lib.rs +++ b/core/http/src/lib.rs @@ -39,3 +39,19 @@ pub use crate::method::Method; pub use crate::status::{Status, StatusClass}; pub use crate::raw_str::{RawStr, RawStrBuf}; pub use crate::header::*; + +/// HTTP Protocol version +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum HttpVersion { + /// `HTTP/0.9` + Http09, + /// `HTTP/1.0` + Http10, + /// `HTTP/1.1` + Http11, + /// `HTTP/2` + Http2, + /// `HTTP/3` + Http3, +} diff --git a/core/http/src/uri/uri.rs b/core/http/src/uri/uri.rs index 14360e7bc1..03ba0297fe 100644 --- a/core/http/src/uri/uri.rs +++ b/core/http/src/uri/uri.rs @@ -79,7 +79,7 @@ impl<'a> Uri<'a> { /// // Invalid URIs fail to parse. /// Uri::parse::("foo bar").expect_err("invalid URI"); /// ``` - pub fn parse(string: &'a str) -> Result, Error<'_>> + pub fn parse(string: &'a str) -> Result, Error<'a>> where T: Into> + TryFrom<&'a str, Error = Error<'a>> { T::try_from(string).map(|v| v.into()) @@ -127,7 +127,7 @@ impl<'a> Uri<'a> { /// let uri: Origin = uri!("/a/b/c?query"); /// let uri: Reference = uri!("/a/b/c?query#fragment"); /// ``` - pub fn parse_any(string: &'a str) -> Result, Error<'_>> { + pub fn parse_any(string: &'a str) -> Result, Error<'a>> { crate::parse::uri::from_str(string) } diff --git a/core/lib/src/form/context.rs b/core/lib/src/form/context.rs index b733c83607..e91b281f8d 100644 --- a/core/lib/src/form/context.rs +++ b/core/lib/src/form/context.rs @@ -219,7 +219,7 @@ impl<'v> Context<'v> { /// let foo_bar = form.context.field_errors("foo.bar"); /// } /// ``` - pub fn field_errors<'a, N>(&'a self, name: N) -> impl Iterator> + '_ + pub fn field_errors<'a, N>(&'a self, name: N) -> impl Iterator> + 'a where N: AsRef + 'a { self.errors.values() @@ -267,7 +267,7 @@ impl<'v> Context<'v> { /// let foo_bar = form.context.exact_field_errors("foo.bar"); /// } /// ``` - pub fn exact_field_errors<'a, N>(&'a self, name: N) -> impl Iterator> + '_ + pub fn exact_field_errors<'a, N>(&'a self, name: N) -> impl Iterator> + 'a where N: AsRef + 'a { self.errors.values() diff --git a/core/lib/src/local/asynchronous/request.rs b/core/lib/src/local/asynchronous/request.rs index 4c85c02024..b9f2c777dc 100644 --- a/core/lib/src/local/asynchronous/request.rs +++ b/core/lib/src/local/asynchronous/request.rs @@ -1,5 +1,7 @@ use std::fmt; +use rocket_http::HttpVersion; + use crate::{Request, Data}; use crate::http::{Status, Method}; use crate::http::uri::Origin; @@ -48,7 +50,7 @@ impl<'c> LocalRequest<'c> { // Create a request. We'll handle bad URIs later, in `_dispatch`. let origin = try_origin.clone().unwrap_or_else(|bad| bad); - let mut request = Request::new(client.rocket(), method, origin); + let mut request = Request::new(client.rocket(), method, origin, None); // Add any cookies we know about. if client.tracked { @@ -62,6 +64,11 @@ impl<'c> LocalRequest<'c> { LocalRequest { client, request, uri: try_origin, data: vec![] } } + #[inline] + pub fn override_version(&mut self, version: HttpVersion) { + self.version = Some(version); + } + pub(crate) fn _request(&self) -> &Request<'c> { &self.request } diff --git a/core/lib/src/local/blocking/request.rs b/core/lib/src/local/blocking/request.rs index 4d8e35373e..8e34dd7192 100644 --- a/core/lib/src/local/blocking/request.rs +++ b/core/lib/src/local/blocking/request.rs @@ -1,5 +1,7 @@ use std::fmt; +use rocket_http::HttpVersion; + use crate::{Request, http::Method, local::asynchronous}; use crate::http::uri::Origin; @@ -42,6 +44,11 @@ impl<'c> LocalRequest<'c> { Self { inner, client } } + #[inline] + pub fn override_version(&mut self, version: HttpVersion) { + self.inner.override_version(version); + } + #[inline] fn _request(&self) -> &Request<'c> { self.inner._request() diff --git a/core/lib/src/request/request.rs b/core/lib/src/request/request.rs index e99e721d3b..4721bf83d7 100644 --- a/core/lib/src/request/request.rs +++ b/core/lib/src/request/request.rs @@ -6,6 +6,8 @@ use std::str::FromStr; use std::future::Future; use std::net::IpAddr; +use http::Version; +use rocket_http::HttpVersion; use state::{TypeMap, InitCell}; use futures::future::BoxFuture; use ref_swap::OptionRefSwap; @@ -31,6 +33,7 @@ pub struct Request<'r> { method: AtomicMethod, uri: Origin<'r>, headers: HeaderMap<'r>, + pub(crate) version: Option, pub(crate) errors: Vec, pub(crate) connection: ConnectionMeta, pub(crate) state: RequestState<'r>, @@ -84,12 +87,14 @@ impl<'r> Request<'r> { pub(crate) fn new<'s: 'r>( rocket: &'r Rocket, method: Method, - uri: Origin<'s> + uri: Origin<'s>, + version: Option, ) -> Request<'r> { Request { uri, method: AtomicMethod::new(method), headers: HeaderMap::new(), + version, errors: Vec::new(), connection: ConnectionMeta::default(), state: RequestState { @@ -104,6 +109,22 @@ impl<'r> Request<'r> { } } + /// Retrieve http protocol version, when applicable. + /// + /// # Example + /// + /// ```rust + /// use rocket::http::HttpVersion; + /// + /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); + /// # let mut req = c.get("/"); + /// # req.override_version(HttpVersion::Http11); + /// assert_eq!(req.version(), Some(HttpVersion::Http11)); + /// ``` + pub fn version(&self) -> Option { + self.version + } + /// Retrieve the method from `self`. /// /// # Example @@ -1130,7 +1151,14 @@ impl<'r> Request<'r> { }); // Construct the request object; fill in metadata and headers next. - let mut request = Request::new(rocket, method, uri); + let mut request = Request::new(rocket, method, uri, match hyper.version { + Version::HTTP_09 => Some(HttpVersion::Http09), + Version::HTTP_10 => Some(HttpVersion::Http10), + Version::HTTP_11 => Some(HttpVersion::Http11), + Version::HTTP_2 => Some(HttpVersion::Http2), + Version::HTTP_3 => Some(HttpVersion::Http3), + _ => None, + }); request.errors = errors; // Set the passed in connection metadata. diff --git a/core/lib/src/response/stream/bytes.rs b/core/lib/src/response/stream/bytes.rs index 52782aa241..d3a8eeb8be 100644 --- a/core/lib/src/response/stream/bytes.rs +++ b/core/lib/src/response/stream/bytes.rs @@ -61,10 +61,10 @@ impl From for ByteStream { } } -impl<'r, S: Stream> Responder<'r, 'r> for ByteStream - where S: Send + 'r, S::Item: AsRef<[u8]> + Send + Unpin + 'r +impl<'r, 'o, S: Stream> Responder<'r, 'o> for ByteStream + where S: Send + 'o, S::Item: AsRef<[u8]> + Send + Unpin + 'o, 'o: 'r { - fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> { + fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { Response::build() .header(ContentType::Binary) .streamed_body(ReaderStream::from(self.0.map(std::io::Cursor::new))) diff --git a/core/lib/src/response/stream/reader.rs b/core/lib/src/response/stream/reader.rs index d3a3da71bf..b4db5886ea 100644 --- a/core/lib/src/response/stream/reader.rs +++ b/core/lib/src/response/stream/reader.rs @@ -139,10 +139,10 @@ impl From for ReaderStream { } } -impl<'r, S: Stream> Responder<'r, 'r> for ReaderStream - where S: Send + 'r, S::Item: AsyncRead + Send, +impl<'r, 'o, S: Stream> Responder<'r, 'o> for ReaderStream + where S: Send + 'o, S::Item: AsyncRead + Send, 'o: 'r { - fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> { + fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { Response::build() .streamed_body(self) .ok() diff --git a/core/lib/src/response/stream/sse.rs b/core/lib/src/response/stream/sse.rs index de24ad2816..af9aabdc46 100644 --- a/core/lib/src/response/stream/sse.rs +++ b/core/lib/src/response/stream/sse.rs @@ -568,8 +568,8 @@ impl> From for EventStream { } } -impl<'r, S: Stream + Send + 'r> Responder<'r, 'r> for EventStream { - fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> { +impl<'r, 'o: 'r, S: Stream + Send + 'o> Responder<'r, 'o> for EventStream { + fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { Response::build() .header(ContentType::EventStream) .raw_header("Cache-Control", "no-cache") diff --git a/core/lib/src/response/stream/text.rs b/core/lib/src/response/stream/text.rs index 3064e0f0e2..fb14a70af0 100644 --- a/core/lib/src/response/stream/text.rs +++ b/core/lib/src/response/stream/text.rs @@ -62,10 +62,10 @@ impl From for TextStream { } } -impl<'r, S: Stream> Responder<'r, 'r> for TextStream - where S: Send + 'r, S::Item: AsRef + Send + Unpin + 'r +impl<'r, 'o, S: Stream> Responder<'r, 'o> for TextStream + where S: Send + 'o, S::Item: AsRef + Send + Unpin + 'o, 'o: 'r { - fn respond_to(self, _: &'r Request<'_>) -> response::Result<'r> { + fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { struct ByteStr(T); impl> AsRef<[u8]> for ByteStr { diff --git a/docs/guide/11-deploying.md b/docs/guide/11-deploying.md index 245683ccec..8bdd4f8ade 100644 --- a/docs/guide/11-deploying.md +++ b/docs/guide/11-deploying.md @@ -262,9 +262,9 @@ WORKDIR /app COPY --from=build /build/main ./ ## copy runtime assets which may or may not exist -COPY --from=build /build/Rocket.tom[l] ./static -COPY --from=build /build/stati[c] ./static -COPY --from=build /build/template[s] ./templates +COPY --from=build /build/Rocket.tom[l] ./ +COPY --from=build /build/stati[c] ./static/ +COPY --from=build /build/template[s] ./templates/ ## ensure the container listens globally on port 8080 ENV ROCKET_ADDRESS=0.0.0.0 diff --git a/docs/guide/12-pastebin.md b/docs/guide/12-pastebin.md index 7b41470720..96176b12f6 100644 --- a/docs/guide/12-pastebin.md +++ b/docs/guide/12-pastebin.md @@ -470,7 +470,7 @@ We note the following Rocket APIs being used in our implementation: * [`Data::open()`] to open [`Data`] as a [`DataStream`]. * [`DataStream::into_file()`] for writing the data stream into a file. * The [`UriDisplayPath`] derive, allowing `PasteId` to be used in [`uri!`]. - * The [`uri!`] macro to crate type-safe, URL-safe URIs. + * The [`uri!`] macro to create type-safe, URL-safe URIs. [`Data::open()`]: @api/master/rocket/data/struct.Data.html#method.open [`Data`]: @api/master/rocket/data/struct.Data.html diff --git a/examples/tls/private/client.pem b/examples/tls/private/client.pem index a5ba33910b..182f482090 100644 --- a/examples/tls/private/client.pem +++ b/examples/tls/private/client.pem @@ -1,58 +1,58 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCjle13u/R/0+zw -eycXhdF7ZNYQfqXfkMpw9GlerbqRrxSLEc/YXXBuIO5AZKkXYeP8iM9KbSBD4p8F -wZD7LL47601c5WwWpNfOravCaSjYgvaYyhnoNzmG8NYaVYKB9kup6lOyQmesNXEK -NGNSrKpsoaQ7jBk+l+VV1jNBjMhNVWuz4AdFMsVD09QyL1GvQ0OvT/BbUKypaFFw -YcHruYvHuKGnrlXkvw05aZmKtKiSE6UQoDKtZWfV8yV2M6Sr75i9GKaGMyUZIl88 -MxVLGcGwO6To2wNFKfLkHLOGIWrKA7m/Bb2n1k2OT+6iOnDzU62BoAzG/j8dhNPL -mZ6a7cZfAgMBAAECggEANwiZe06gUuDZNY44+JDsiLbDzYjOBQiREq8nQ9LukVR1 -dNPpOME2sdYiUUeMG3GzYaIlGsTbtfrnxOf5/oZu+XmP7VDBrFyIvd9viVgXhb+J -dp2HWbg6gktDvFhIL7DMg71xqubsOeNAxE4bnBS6wREgT2gylfxECzykwci7Gki4 -AkeihvaxqdHk9WP8dtFOuCYhX5pyKd9veS1/L01dVMpoFrq72PHupplKYb3HIo+v -ga02DhNVcH3fomEbXzazC64k2h5Vz+8mgpu5/V1thKiB2izOwt/hv4tkf2iDNz43 -xdSYUEFsk80M97VI1dM1+TBe/JO0auZvKLkuOWUjAQKBgQDlBMr+d+guajgQ863I -uEFK4veEXrD51L6AKT+cqFUi894fhOodnnmK8l3JBKzO0zjgsaez8exKZPRN8An8 -4MejM+hMYciJsP7uDpPkhlI5zHd9CR7EFPWXXpt4PecQLvBbnJ/lDnWCrE4m5Zhs -9OR7izLMBAmaiPlTNAaXj22iqwKBgQC226wzXGr//lnTggZX+u9UdkZKewAYlgnB -Ywj3+JB6Q/kDDS8C6fdlAvWyHShxtO3gx2pJSI3hk7J8fZu/kbojlLF16ayO+tgg -t3EoTZxN5zncygPaULstdKHhnMp8a4AO8lLrHtackFbbX7fuUJft0w457FpARvM8 -DONjWI8LHQKBgBBY5TyAxpv5jQL4weDf9hkoVk6mi69plieDyjyeb2VNTv+k9yki -FL7sSfF9WfBxd0/innvjuuAckKu3hJ7+VIG7xMse97eMYMYRWFEpnVju1WChdAa/ -EEC7yhEtKf8nupRve6JYA99N+U4heV3dpSmEaB3T8/OJ73IW9pl+7W59AoGADxM/ -OCDHZYF3sFtI4Jn8fy8dDmjjkiNUfJAInkDs0FeoQNsmZAwb7ET5Moz615z9+4kV -NyN3JwDBN0g3vexqtyI8Gyd/pW4CwXe+KX90gmustoolFSuQsueprOr7OpS2QwUx -Vtb9BH1V29IhXNFiJSZARwA4VJJE3U+Gs5sKd/UCgYEAoCPE3gVaa89nOqQtalhT -9SISOGQxxMknjNFrEuF3UaGuR0cxDRLX6lSEneAATEpho0QB2Fj4vO8PiyYOGvH+ -5ouJD97rcU77OOixlLFt4+TAWI9AvT0mN7y+SHJ22RkwWGQyF4TIfkg0tQvu36D+ -35W26Li1WteB2O4wV9qVReA= +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCu68//dEJZTfUb +g6lKo0AkcjWevKMtZVpO6YnBCQ+7J0d1U0p7OCN+bisCx0nXvzDO6VxDgWEcnG44 +IR03qYVihq+C1r/96I+6chKIqK0LI2WhXvJ/sXnzz1feFyBYoz/oSM6QndcjUV83 +R8nzp1+eefuTDjuhcCddAk8fU5fJ9OLd7B2sKit8ZLHdHwqlZSWU32sS12xEjP// +TjazNzP137KVa/KKVvRu2xYlRWHRmR1zY8trSy1795GIdv7198nF2i+0oS4k0PrF +LzIUYgr1fCZr3QYjLK7mErSpkXUk5FoEhApmWo9iGLOOWv3HUSC8yCgdcIcauK8N +zTqz2iORAgMBAAECggEAEeG3d1+U3M5Jt/tYq3GkQAA7l7OkYXf9UxiFZZTIj+hZ +t2vBWcwJDNwJoj9p6W1OebMveb3YhfU+lexaBp5aLWf5ZJW8NiJidxFBmx4rOnqZ +jB/0XbYbR8pdgC27DR9QjC134x7PpyOivo2kiTewtbcLTyLjA64/HT9RhAamphWA +aGNex/imFfrWObHg9BNTtfMDekfsOwHOIgbWS/TvdJaVbUzOphZZLmM3mOG/VROG +BIlDS7mfIO1/YHCE88vfRD3iuiGe3H86Tb6qZL+3xNNAzXIu/UqpLz+FGc9TMJRK +FZ/u0beD1U6Ij9/BZ6XO3UF7tN84UqhudZ2rnlG35QKBgQDeg4f6lNpTOKRgrVYx +sLZN5HANWe9I5n8z+TZcv2/pPtQY1A9ZDPM7s0b+Zys089k4f5qXNew0u/JTpin8 +h2MYNvNxXt/fCMxw7PBTkXB1JW+Qofz9k04NRXvMXEtGA3VR+vQcUwdEa9t9dWjD +rM1k5vp2tSIgqJujZmqtqQdpJwKBgQDJPr9qlVCbWGNXn70HPl5G2MVPvRT6aHVo +Hx9XUTU4spyCIfmsckh0S2BODJZAHlTZctOKPz7KfnPC6T8V9Vgwzwnv18X71+9w +4Z8D4OznWL3FNP5RaXSkR7JkpyE79drjVS5MCWC1k7Rr5T9dMPLu6GyjjH6nLfrr +MsKuNa7QhwKBgBoP1dFntdqhe79HDh1r0S52XxlxOzGSrbtsqQ1b7sOm9DikPdf0 +SFjpupr5gnoFRZ/0cirbyfqzOMLLZ4eIY/bmGMVik14QLcHcPpnLIxzVcafDEVqx +8iZjyQg6lyZwKUGc3xKiNuuwplifc9HXX4c99oAI3yJsHS6aRExqy89pAoGACbTe +FKz5A1UjDYHl4yiN8YrZEXyEO4O4TfpaT6LaF07+H4S1/yxP9FQCZCFVSehsnURd +kah1Rd0NhlQrt8pqo4gI6amVog0LPn2TZuN9abctCAsDTTfx6U6P+yzYfITiNt7P +6dj18iwaoq2e/cazoPRS8RyAq12bYabEHxT1xpcCgYAIEOqYHdawRk7nexDRiHcc +8kDIofYXJRXzdjfWH+j1j5/Dk3Ssuiz+/mIZU3PeLwC/p8PS0MmuPe10fC7bHM43 +kI6rdzMEyM586eIEQGJoZmHanK6Ox27qTXoOtX0mpc7DfRVainH70Jseaz7WddNU +wOWmTtGwe4WcO7Ky1RB/oQ== -----END PRIVATE KEY----- -----BEGIN CERTIFICATE----- -MIIEwDCCAqigAwIBAgIUay5Z8sVQUkSTFpacn6o4iq2ElGowDQYJKoZIhvcNAQEL +MIIEwDCCAqigAwIBAgIUedqTn+lWoKa2Ns1KDFXAG15/uYYwDQYJKoZIhvcNAQEL BQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg -Q0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTI0MDQxNDA4MTU0MVoXDTI1 -MDQxNDA4MTU0MVowgY4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh +Q0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTI1MDUwNDA4MDQwNFoXDTM1 +MDUwMjA4MDQwNFowgY4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh MRcwFQYDVQQHDA5TaWxpY29uIFZhbGxleTEPMA0GA1UECgwGUm9ja2V0MRswGQYD VQQDDBJSb2NrZXQgVExTIEV4YW1wbGUxIzAhBgkqhkiG9w0BCQEWFGV4YW1wbGVA -cm9ja2V0LmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo5Xt -d7v0f9Ps8HsnF4XRe2TWEH6l35DKcPRpXq26ka8UixHP2F1wbiDuQGSpF2Hj/IjP -Sm0gQ+KfBcGQ+yy+O+tNXOVsFqTXzq2rwmko2IL2mMoZ6Dc5hvDWGlWCgfZLqepT -skJnrDVxCjRjUqyqbKGkO4wZPpflVdYzQYzITVVrs+AHRTLFQ9PUMi9Rr0NDr0/w -W1CsqWhRcGHB67mLx7ihp65V5L8NOWmZirSokhOlEKAyrWVn1fMldjOkq++YvRim -hjMlGSJfPDMVSxnBsDuk6NsDRSny5ByzhiFqygO5vwW9p9ZNjk/uojpw81OtgaAM -xv4/HYTTy5memu3GXwIDAQABo1wwWjAYBgNVHREEETAPgg1ETlM6bG9jYWxob3N0 -MB0GA1UdDgQWBBSowDBXM26C7VogwXNB1F0vLpYO7DAfBgNVHSMEGDAWgBREAyUj -0lTwopZ2B1VmnvMPfUtCkzANBgkqhkiG9w0BAQsFAAOCAgEAbjF11+t8qVEF72ey -19p1sRkG9ygb0gE2UpLzVpPilucioIOwQuT4rvsVYZQxK+smQZURDI4uNXODIeoS -r3maL82VryLSYbkQADyShYjF0uCX8AfCI0YtOKOschNZDcZEJ5mUpHjJE0lEZnkO -x8ZVXwWf4pv1/8DZoCkMN3gDHwhQGPtrls4q7O38rI7zK9DNrzu7R1ZdGjQSDasL -6DqHee90O2ejpELUxO6lRl2EUosfklRvjV7hfrDHlpN9EuweXt0JiaKw3WZzHSLa -dKS8wtTMq5aWzOWrew1ZEhRr+B3KS6BSC5o9xSQMfcDyS0KJcIJI9bNh3nElWFhM -IBVtGxM/EYAwNJ++jLD10WHvaqW0epMV2cUu+dGJX+TPuI0c/wNehisS4ahvR64m -UpjAwNUBlYpR/Gb15/i2fVk2BbUyU3AcpZfWFDopQ8UqC8ALVcNjbNHq+yVkuTpj -gn5iiTTcTqb6qNfie4oDX4KR6ZgpNiTl/PWZo58qxSwdGiJwrINACkPJ6Qg6Qrpd -hp3CanTWjioHfvTSdiubqw5/XRnqa2Iav0Sttc6TPnTimodmtWkaYA8mvjS+jq8N -f9l2UYQz8yLabMkn98BM+gRJYwrVt6sCbVuEaHgPwq/qX9mQFhUrfw3iEPKlmezt -T3AhgPhybUpMFpu+4Tp8JE2JlKQ= +cm9ja2V0LmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAruvP +/3RCWU31G4OpSqNAJHI1nryjLWVaTumJwQkPuydHdVNKezgjfm4rAsdJ178wzulc +Q4FhHJxuOCEdN6mFYoavgta//eiPunISiKitCyNloV7yf7F5889X3hcgWKM/6EjO +kJ3XI1FfN0fJ86dfnnn7kw47oXAnXQJPH1OXyfTi3ewdrCorfGSx3R8KpWUllN9r +EtdsRIz//042szcz9d+ylWvyilb0btsWJUVh0Zkdc2PLa0ste/eRiHb+9ffJxdov +tKEuJND6xS8yFGIK9Xwma90GIyyu5hK0qZF1JORaBIQKZlqPYhizjlr9x1EgvMgo +HXCHGrivDc06s9ojkQIDAQABo1wwWjAYBgNVHREEETAPgg1ETlM6bG9jYWxob3N0 +MB0GA1UdDgQWBBRfHH7YEW3/jj2tvNsdcEU7hB3SlDAfBgNVHSMEGDAWgBREAyUj +0lTwopZ2B1VmnvMPfUtCkzANBgkqhkiG9w0BAQsFAAOCAgEAOTOF2u58WDp1kPKP +mTcjeVBunpu1qWmditSlu9+YNPmKwv22Lcwg9dMPh1o8bH80wdtmrGH0Yi857M9D +eosieaKHNN7WUU9DRqENJutknFxZ2hd1L3GOqADJujL43BDgOWL8b3ffmfP0f7b1 +5OsFmQALNWMlI5ThpK6naor7aWjXshCVVfjrDFfAouEyr6gLgKVpYyi4cQX7MCH2 +RfDgbksKy5OmqhI2374DEQgxlqadnnc+HTx2zKmLErUSvuE1K1CmKgwrZDyueTPh +aDKBNZrWh7t7okrcbyWFMmqaZtpMWMSvldvihIXv10v9LuRuHMd+QoNvfigrJofd +zEtk0+ZXx9DMSN5djhfyvxhapGGel68Kjt/XPamcx4pTzzxyKvoNLooEfV/WZnp7 +2n6MlNBcjmi0EBX8Xr7cbviBSXADAAGxnwFoLMUB/hK6oWdv5lkWPojzM7/E0cyW +cjIkF54wM/mXsxoHRqNFKo5pdjZYvoonguYADTU9+EsfM7Amp06Xqm/YR79L5yCa +GbRW0b4sUaYXGusTOuXpVqBfRxO7NG8J4r1OP9l3RP8tqwP+1JuDfyKyhD5yNmYl +OJFfHxS8udBM3ZbrzrfaT4/1T66prRC4QeufkjP6Zhj+l88rxgdg3KEN3VOjJ1IB +J3ig0HbpD/ETWVT21vrqhHXJXWg= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFbzCCA1egAwIBAgIURX345HUrWikAysSTFd8xoV5GSIYwDQYJKoZIhvcNAQEL diff --git a/examples/tls/private/gen_certs.sh b/examples/tls/private/gen_certs.sh index cb68ac5a1f..275de5bb60 100755 --- a/examples/tls/private/gen_certs.sh +++ b/examples/tls/private/gen_certs.sh @@ -138,13 +138,13 @@ function gen_ecdsa_nistp521_sha512() { } function gen_client_cert() { - openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr - openssl x509 -req -extfile <(printf "subjectAltName=DNS:${ALT}") -days 365 \ - -in client.csr -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \ - -out client.crt + openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj "/C=US/ST=California/L=Silicon Valley/O=Rocket/CN=Rocket TLS Example/emailAddress=example@rocket.local" + openssl x509 -req -extfile <(printf "subjectAltName=DNS:${ALT}") -days 3650 \ + -in client.csr -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial \ + -out client.crt - cat client.key client.crt ca_cert.pem > client.pem - rm client.key client.crt client.csr ca_cert.srl + cat client.key client.crt ca_cert.pem > client.pem + rm client.key client.crt client.csr ca_cert.srl } case $1 in @@ -160,5 +160,6 @@ case $1 in gen_ecdsa_nistp256_sha256 gen_ecdsa_nistp384_sha384 gen_ecdsa_nistp521_sha512 + gen_client_cert ;; esac diff --git a/testbench/src/servers/mtls.rs b/testbench/src/servers/mtls.rs index 1fdaea7ae0..9c85840c92 100644 --- a/testbench/src/servers/mtls.rs +++ b/testbench/src/servers/mtls.rs @@ -28,10 +28,10 @@ fn test_mtls(mandatory: bool) -> Result<()> { .identity(reqwest::Identity::from_pem(&pem)?) .try_into()?; - let response = client.get(&server, "/")?.send()?; - assert_eq!(response.text()?, - "611895682361338926795452113263857440769284805738:2\ - [C=US, ST=CA, O=Rocket CA, CN=Rocket Root CA] \ + let response = client.get(&server, "/")?.send()?.text()?; + let (_key_hash, subject) = response.split_once(":2").unwrap(); + assert_eq!(subject, + "[C=US, ST=CA, O=Rocket CA, CN=Rocket Root CA] \ C=US, ST=California, L=Silicon Valley, O=Rocket, \ CN=Rocket TLS Example, Email=example@rocket.local");