diff --git a/client/src/builder.rs b/client/src/builder.rs index 6aa8eef5..2e485406 100644 --- a/client/src/builder.rs +++ b/client/src/builder.rs @@ -120,14 +120,14 @@ impl ClientBuilder { #[cfg(feature = "openssl")] /// enable openssl as tls connector. pub fn openssl(mut self) -> Self { - self.connector = connector::openssl(self.alpn_from_version()); + self.connector = connector::openssl::connect(self.alpn_from_version()); self } #[cfg(feature = "rustls")] /// enable rustls as tls connector. pub fn rustls(mut self) -> Self { - self.connector = connector::rustls(self.alpn_from_version()); + self.connector = connector::rustls::connect(self.alpn_from_version()); self } diff --git a/client/src/tls/connector.rs b/client/src/tls/connector.rs index c0b55a67..320549a1 100644 --- a/client/src/tls/connector.rs +++ b/client/src/tls/connector.rs @@ -40,13 +40,15 @@ pub(crate) fn nop() -> Connector { } #[cfg(feature = "openssl")] -pub(crate) fn openssl(protocols: &[&[u8]]) -> Connector { +pub(crate) mod openssl { use core::pin::Pin; use openssl_crate::ssl::{SslConnector, SslMethod}; use tokio_openssl::SslStream; use xitca_http::bytes::BufMut; + use super::*; + impl<'n> Service<(&'n str, Box)> for SslConnector { type Response = (Box, Version); type Error = Error; @@ -72,22 +74,24 @@ pub(crate) fn openssl(protocols: &[&[u8]]) -> Connector { } } - let mut alpn = Vec::with_capacity(20); - for proto in protocols { - alpn.put_u8(proto.len() as u8); - alpn.put(*proto); - } + pub(crate) fn connect(protocols: &[&[u8]]) -> Connector { + let mut alpn = Vec::with_capacity(20); + for proto in protocols { + alpn.put_u8(proto.len() as u8); + alpn.put(*proto); + } - let mut ssl = SslConnector::builder(SslMethod::tls()).unwrap(); + let mut ssl = SslConnector::builder(SslMethod::tls()).unwrap(); - ssl.set_alpn_protos(&alpn) - .unwrap_or_else(|e| panic!("Can not set ALPN protocol: {e:?}")); + ssl.set_alpn_protos(&alpn) + .unwrap_or_else(|e| panic!("Can not set ALPN protocol: {e:?}")); - Box::new(ssl.build()) + Box::new(ssl.build()) + } } #[cfg(feature = "rustls")] -pub(crate) fn rustls(protocols: &[&[u8]]) -> Connector { +pub(crate) mod rustls { use std::sync::Arc; use rustls_pki_types::ServerName; @@ -97,6 +101,8 @@ pub(crate) fn rustls(protocols: &[&[u8]]) -> Connector { }; use webpki_roots::TLS_SERVER_ROOTS; + use super::*; + impl<'n> Service<(&'n str, Box)> for TlsConnector { type Response = (Box, Version); type Error = Error; @@ -119,15 +125,17 @@ pub(crate) fn rustls(protocols: &[&[u8]]) -> Connector { } } - let mut root_certs = RootCertStore::empty(); + pub(crate) fn connect(protocols: &[&[u8]]) -> Connector { + let mut root_certs = RootCertStore::empty(); - root_certs.extend(TLS_SERVER_ROOTS.iter().cloned()); + root_certs.extend(TLS_SERVER_ROOTS.iter().cloned()); - let mut config = ClientConfig::builder() - .with_root_certificates(root_certs) - .with_no_client_auth(); + let mut config = ClientConfig::builder() + .with_root_certificates(root_certs) + .with_no_client_auth(); - config.alpn_protocols = protocols.iter().map(|p| p.to_vec()).collect(); + config.alpn_protocols = protocols.iter().map(|p| p.to_vec()).collect(); - Box::new(TlsConnector::from(Arc::new(config))) + Box::new(TlsConnector::from(Arc::new(config))) + } } diff --git a/http-ws/CHANGES.md b/http-ws/CHANGES.md index 343e5aa1..751981e7 100644 --- a/http-ws/CHANGES.md +++ b/http-ws/CHANGES.md @@ -2,6 +2,7 @@ ## Add - add `RequestStream::inner_mut` method for accessing inner stream type. - add `RequestStream::codec_mut` method for accessing `Codec` type. +- add `ResponseSender::close` method for sending close message. ## Change - reduce `stream::RequestStream`'s generic type params. diff --git a/http-ws/src/stream.rs b/http-ws/src/stream.rs index c20a3675..0c8d105c 100644 --- a/http-ws/src/stream.rs +++ b/http-ws/src/stream.rs @@ -17,6 +17,7 @@ use tokio::sync::mpsc::{channel, Receiver, Sender}; use super::{ codec::{Codec, Message}, error::ProtocolError, + proto::CloseReason, }; pin_project! { @@ -239,6 +240,12 @@ impl ResponseSender { pub fn binary(&self, bin: impl Into) -> impl Future> + '_ { self.send(Message::Binary(bin.into())) } + + /// encode [Message::Close] variant and add to [ResponseStream]. + /// take ownership of Self as after close message no more message can be sent to client. + pub async fn close(self, reason: Option>) -> Result<(), ProtocolError> { + self.send(Message::Close(reason.map(Into::into))).await + } } /// [Weak] version of [ResponseSender]. diff --git a/http/src/util/service/route.rs b/http/src/util/service/route.rs index 27761860..b22df89e 100644 --- a/http/src/util/service/route.rs +++ b/http/src/util/service/route.rs @@ -176,7 +176,7 @@ impl ReadyService for RouteService { } /// Error type of Method not allow for route. -pub struct MethodNotAllowed(pub Vec); +pub struct MethodNotAllowed(pub Box>); impl MethodNotAllowed { /// slice of allowed methods of current route. @@ -229,7 +229,7 @@ where type Error = RouterError; async fn call(&self, _: Req) -> Result { - Err(RouterError::NotAllowed(MethodNotAllowed(Vec::new()))) + Err(RouterError::NotAllowed(MethodNotAllowed(Box::default()))) } } diff --git a/web/src/service/file.rs b/web/src/service/file.rs index 30e83f77..d60d87bb 100644 --- a/web/src/service/file.rs +++ b/web/src/service/file.rs @@ -95,7 +95,7 @@ mod service { Err(e) => Err(match e { ServeError::NotFound => RouterError::Match(MatchError), ServeError::MethodNotAllowed => { - RouterError::NotAllowed(MethodNotAllowed(vec![Method::GET, Method::HEAD])) + RouterError::NotAllowed(MethodNotAllowed(Box::new(vec![Method::GET, Method::HEAD]))) } ServeError::Io(io) => RouterError::Service(Error::from(io)), _ => RouterError::Service(Error::from(ErrorStatus::bad_request())),