use super::*;
impl Default for Server {
#[inline(always)]
fn default() -> Self {
Self {
server_config: ServerConfig::default(),
request_config: RequestConfig::default(),
task_panic: Vec::new(),
request_error: Vec::new(),
route_matcher: RouteMatcher::new(),
request_middleware: Vec::new(),
response_middleware: Vec::new(),
}
}
}
impl PartialEq for Server {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.get_server_config() == other.get_server_config()
&& self.get_request_config() == other.get_request_config()
&& self.get_route_matcher() == other.get_route_matcher()
&& self.get_task_panic().len() == other.get_task_panic().len()
&& self.get_request_error().len() == other.get_request_error().len()
&& self.get_request_middleware().len() == other.get_request_middleware().len()
&& self.get_response_middleware().len() == other.get_response_middleware().len()
&& self
.get_task_panic()
.iter()
.zip(other.get_task_panic().iter())
.all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
&& self
.get_request_error()
.iter()
.zip(other.get_request_error().iter())
.all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
&& self
.get_request_middleware()
.iter()
.zip(other.get_request_middleware().iter())
.all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
&& self
.get_response_middleware()
.iter()
.zip(other.get_response_middleware().iter())
.all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
}
}
impl Eq for Server {}
impl From<usize> for Server {
#[inline(always)]
fn from(address: usize) -> Self {
let server: &Server = address.into();
server.clone()
}
}
impl From<usize> for &'static Server {
#[inline(always)]
fn from(address: usize) -> &'static Server {
unsafe { &*(address as *const Server) }
}
}
impl From<usize> for &'static mut Server {
#[inline(always)]
fn from(address: usize) -> &'static mut Server {
unsafe { &mut *(address as *mut Server) }
}
}
impl From<&Server> for usize {
#[inline(always)]
fn from(server: &Server) -> Self {
server as *const Server as usize
}
}
impl From<&mut Server> for usize {
#[inline(always)]
fn from(server: &mut Server) -> Self {
server as *mut Server as usize
}
}
impl AsRef<Server> for Server {
#[inline(always)]
fn as_ref(&self) -> &Self {
let address: usize = self.into();
address.into()
}
}
impl AsMut<Server> for Server {
#[inline(always)]
fn as_mut(&mut self) -> &mut Self {
let address: usize = self.into();
address.into()
}
}
impl From<ServerConfig> for Server {
#[inline(always)]
fn from(server_config: ServerConfig) -> Self {
Self {
server_config,
..Default::default()
}
}
}
impl From<RequestConfig> for Server {
#[inline(always)]
fn from(request_config: RequestConfig) -> Self {
Self {
request_config,
..Default::default()
}
}
}
impl Lifetime for Server {
#[inline(always)]
unsafe fn leak(&self) -> &'static Self {
let address: usize = self.into();
address.into()
}
#[inline(always)]
unsafe fn leak_mut(&self) -> &'static mut Self {
let address: usize = self.into();
address.into()
}
}
impl Server {
#[inline]
pub fn handle_hook(&mut self, hook: HookType) {
match hook {
HookType::TaskPanic(_, hook) => {
self.get_mut_task_panic().push(hook());
}
HookType::RequestError(_, hook) => {
self.get_mut_request_error().push(hook());
}
HookType::RequestMiddleware(_, hook) => {
self.get_mut_request_middleware().push(hook());
}
HookType::Route(path, hook) => {
self.get_mut_route_matcher().add(path, hook()).unwrap();
}
HookType::ResponseMiddleware(_, hook) => {
self.get_mut_response_middleware().push(hook());
}
};
}
#[inline]
pub fn config_from_json<C>(&mut self, json: C) -> &mut Self
where
C: AsRef<str>,
{
let config: ServerConfig = serde_json::from_str(json.as_ref()).unwrap();
self.set_server_config(config);
self
}
#[inline(always)]
pub fn server_config(&mut self, config: ServerConfig) -> &mut Self {
self.set_server_config(config);
self
}
#[inline(always)]
pub fn request_config(&mut self, config: RequestConfig) -> &mut Self {
self.set_request_config(config);
self
}
#[inline(always)]
pub fn task_panic<S>(&mut self) -> &mut Self
where
S: ServerHook,
{
self.get_mut_task_panic().push(Hook::factory::<S>());
self
}
#[inline(always)]
pub fn request_error<S>(&mut self) -> &mut Self
where
S: ServerHook,
{
self.get_mut_request_error().push(Hook::factory::<S>());
self
}
#[inline(always)]
pub fn route<S>(&mut self, path: impl AsRef<str>) -> &mut Self
where
S: ServerHook,
{
self.get_mut_route_matcher()
.add(path.as_ref(), Hook::factory::<S>())
.unwrap();
self
}
#[inline(always)]
pub fn request_middleware<S>(&mut self) -> &mut Self
where
S: ServerHook,
{
self.get_mut_request_middleware().push(Hook::factory::<S>());
self
}
#[inline(always)]
pub fn response_middleware<S>(&mut self) -> &mut Self
where
S: ServerHook,
{
self.get_mut_response_middleware()
.push(Hook::factory::<S>());
self
}
#[inline(always)]
pub fn format_bind_address<H>(host: H, port: u16) -> String
where
H: AsRef<str>,
{
format!("{}{COLON}{port}", host.as_ref())
}
#[inline(always)]
pub fn try_flush_stdout() -> io::Result<()> {
stdout().flush()
}
#[inline(always)]
pub fn flush_stdout() {
stdout().flush().unwrap();
}
#[inline(always)]
pub fn try_flush_stderr() -> io::Result<()> {
stderr().flush()
}
#[inline(always)]
pub fn flush_stderr() {
stderr().flush().unwrap();
}
#[inline(always)]
pub fn try_flush_stdout_and_stderr() -> io::Result<()> {
Self::try_flush_stdout()?;
Self::try_flush_stderr()
}
#[inline(always)]
pub fn flush_stdout_and_stderr() {
Self::flush_stdout();
Self::flush_stderr();
}
pub(super) async fn handle_request_middleware(
&self,
stream: &mut Stream,
ctx: &mut Context,
) -> bool {
for hook in self.get_request_middleware().iter() {
if hook(stream, ctx).await.is_reject() {
return true;
}
}
false
}
pub(super) async fn handle_route_matcher(
&self,
stream: &mut Stream,
ctx: &mut Context,
path: &str,
) -> bool {
if let Some(hook) = self.get_route_matcher().try_resolve_route(ctx, path)
&& hook(stream, ctx).await.is_reject()
{
return true;
}
false
}
pub(super) async fn handle_response_middleware(
&self,
stream: &mut Stream,
ctx: &mut Context,
) -> bool {
for hook in self.get_response_middleware().iter() {
if hook(stream, ctx).await.is_reject() {
return true;
}
}
false
}
pub async fn handle_request_error(
&self,
stream: &mut Stream,
ctx: &mut Context,
error: &RequestError,
) {
ctx.set_request_error_data(error.clone());
stream.set_closed(false);
for hook in self.get_request_error().iter() {
if hook(stream, ctx).await.is_reject() {
return;
}
}
}
pub(crate) async fn request_hook(
&self,
stream: &mut Stream,
ctx: &mut Context,
request: Request,
) -> bool {
let keep_alive: bool = request.is_enable_keep_alive();
let version: RequestVersion = request.get_version().clone();
ctx.set_request(request);
ctx.get_mut_response().reset().set_version(version);
ctx.clear_route_params();
ctx.clear_attribute();
stream.set_closed(false);
if self.handle_request_middleware(stream, ctx).await {
return stream.is_keep_alive(keep_alive);
}
let static_hook: Option<&ServerHookHandler> = {
let path: &str = ctx.get_request().get_path().as_str();
self.get_route_matcher().try_resolve_static_route(path)
};
if let Some(hook) = static_hook {
if hook(stream, ctx).await.is_reject() {
return stream.is_keep_alive(keep_alive);
}
} else {
let route: RequestPath = ctx.get_request().get_path().clone();
if self.handle_route_matcher(stream, ctx, &route).await {
return stream.is_keep_alive(keep_alive);
}
}
if self.handle_response_middleware(stream, ctx).await {
return stream.is_keep_alive(keep_alive);
}
stream.is_keep_alive(keep_alive)
}
async fn handle_http_requests(&self, stream: &mut Stream, ctx: &mut Context, request: Request) {
if !self.request_hook(stream, ctx, request).await {
return;
}
loop {
let mut reused_request: Request = mem::take(ctx.get_mut_request());
match stream.try_fill_http_request(&mut reused_request).await {
Ok(()) => {
if !self.request_hook(stream, ctx, reused_request).await {
return;
}
}
Err(error) => {
ctx.set_request(reused_request);
self.handle_request_error(stream, ctx, &error).await;
return;
}
}
}
}
async fn handle_connection(&self, stream: &mut Stream, ctx: &mut Context) {
match stream.try_get_http_request().await {
Ok(request) => {
self.handle_http_requests(stream, ctx, request).await;
}
Err(error) => {
self.handle_request_error(stream, ctx, &error).await;
}
}
}
pub(crate) async fn serve_h1_connection_stream(&self, stream: &mut Stream) {
let mut ctx: Context = Context::default();
let panicked: Option<PanicData> =
catch_connection_panic(self.handle_connection(stream, &mut ctx)).await;
let Some(panic) = panicked else {
return;
};
ctx.set_task_panic(panic)
.get_mut_response()
.set_status_code(HttpStatus::InternalServerError.code());
stream.set_closed(false);
for hook in self.get_task_panic().iter() {
if hook(stream, &mut ctx).await.is_reject() {
break;
}
}
}
pub(crate) async fn run_protocol_lifecycle(
&self,
stream: &mut Stream,
ctx: &mut Context,
request: Request,
) {
let panicked: Option<PanicData> = catch_connection_panic(async {
let _keep_alive: bool = self.request_hook(stream, ctx, request).await;
})
.await;
let Some(panic) = panicked else {
return;
};
ctx.set_task_panic(panic)
.get_mut_response()
.set_status_code(HttpStatus::InternalServerError.code());
stream.set_closed(false);
for hook in self.get_task_panic().iter() {
if hook(stream, ctx).await.is_reject() {
break;
}
}
}
pub async fn run(&self) -> Result<ServerControlHook, Box<ServerError>> {
let server_config: &ServerConfig = self.get_server_config();
let protocol: ServerProtocol = server_config.get_protocol();
let tls_config: Option<TlsConfig> = server_config.get_tls().clone();
if protocol == ServerProtocol::Http3 && tls_config.is_none() {
return Err(Box::new(ServerError::MissingTlsForHttp3));
}
let stream_tls: Option<Arc<rustls::ServerConfig>> = match tls_config.clone() {
Some(_) if protocol == ServerProtocol::Http3 => None,
Some(config) => Some(build_stream_tls_config(&config, &protocol)?),
None => None,
};
let bind_address: &String = server_config.get_address();
let server: Arc<Server> = Arc::new(Self::clone(self));
let request_config: RequestConfig = *self.get_request_config();
let (shutdown_sender, shutdown_receiver) = channel(());
let (running_sender, running_receiver) = channel(SERVER_RUNNING);
let _: JoinHandle<()> = match protocol {
ServerProtocol::Http3 => {
let Some(config) = tls_config.clone() else {
return Err(Box::new(ServerError::MissingTlsForHttp3));
};
let quic_config: Arc<quinn::crypto::rustls::QuicServerConfig> = Arc::new(
quinn::crypto::rustls::QuicServerConfig::try_from(build_quic_tls_config(
&config,
)?)
.map_err(
|error: quinn::crypto::rustls::NoInitialCipherSuite| {
Box::new(ServerError::Tls(format!(
"no compatible cipher suite for quic: {}",
error
)))
},
)?,
);
let bind_addr: SocketAddr =
bind_address
.parse::<SocketAddr>()
.map_err(|error: AddrParseError| {
Box::new(ServerError::Tls(format!(
"invalid bind address {}: {}",
bind_address, error
)))
})?;
let endpoint: Endpoint =
Endpoint::server(quinn::ServerConfig::with_crypto(quic_config), bind_addr)
.map_err(|error: io::Error| Box::new(ServerError::from(error)))?;
let env: ConnectionEnv = ConnectionEnv {
server,
request_config,
protocol,
};
spawn(async move {
let _: Result<(), Box<ServerError>> =
quic_accept(env, endpoint, shutdown_receiver, running_sender).await;
})
}
_ => {
let tcp_listener: TcpListener = TcpListener::bind(&bind_address)
.await
.map_err(|error: io::Error| Box::new(ServerError::from(error)))?;
let env: ConnectionEnv = ConnectionEnv {
server,
request_config,
protocol,
};
spawn(async move {
tcp_accept(
env,
stream_tls,
AcceptSignal {
listener: tcp_listener,
shutdown_receiver,
running_sender,
},
)
.await;
})
}
};
let wait_hook: ServerControlHookHandler<()> = Arc::new(move || {
let mut running_receiver_clone: Receiver<bool> = running_receiver.clone();
Box::pin(async move {
while !*running_receiver_clone.borrow_and_update() {
let _: Result<(), tokio::sync::watch::error::RecvError> =
running_receiver_clone.changed().await;
}
})
});
let shutdown_hook: ServerControlHookHandler<()> = Arc::new(move || {
let shutdown_sender_clone: Sender<()> = shutdown_sender.clone();
Box::pin(async move {
let _: Result<(), tokio::sync::watch::error::SendError<()>> =
shutdown_sender_clone.send(());
})
});
let mut server_control_hook: ServerControlHook = ServerControlHook::default();
server_control_hook.set_shutdown_hook(shutdown_hook);
server_control_hook.set_wait_hook(wait_hook);
Ok(server_control_hook)
}
}