hyperlane_core/server/impl.rs
1use super::*;
2
3/// Provides a default implementation for Server.
4impl Default for Server {
5 /// Creates a new Server instance with default values.
6 ///
7 /// # Returns
8 ///
9 /// - `Self` - A new instance with default configuration.
10 #[inline(always)]
11 fn default() -> Self {
12 Self {
13 server_config: ServerConfig::default(),
14 request_config: RequestConfig::default(),
15 task_panic: Vec::new(),
16 request_error: Vec::new(),
17 route_matcher: RouteMatcher::new(),
18 request_middleware: Vec::new(),
19 response_middleware: Vec::new(),
20 }
21 }
22}
23
24/// Implements the `PartialEq` trait for `Server`.
25///
26/// This allows for comparing two `Server` instances for equality.
27impl PartialEq for Server {
28 /// Checks if two `Server` instances are equal.
29 ///
30 /// # Arguments
31 ///
32 /// - `&Self` - The other `Server` instance to compare against.
33 ///
34 /// # Returns
35 ///
36 /// - `bool` - `true` if the instances are equal, `false` otherwise.
37 #[inline]
38 fn eq(&self, other: &Self) -> bool {
39 self.get_server_config() == other.get_server_config()
40 && self.get_request_config() == other.get_request_config()
41 && self.get_route_matcher() == other.get_route_matcher()
42 && self.get_task_panic().len() == other.get_task_panic().len()
43 && self.get_request_error().len() == other.get_request_error().len()
44 && self.get_request_middleware().len() == other.get_request_middleware().len()
45 && self.get_response_middleware().len() == other.get_response_middleware().len()
46 && self
47 .get_task_panic()
48 .iter()
49 .zip(other.get_task_panic().iter())
50 .all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
51 && self
52 .get_request_error()
53 .iter()
54 .zip(other.get_request_error().iter())
55 .all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
56 && self
57 .get_request_middleware()
58 .iter()
59 .zip(other.get_request_middleware().iter())
60 .all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
61 && self
62 .get_response_middleware()
63 .iter()
64 .zip(other.get_response_middleware().iter())
65 .all(|pair: (&ServerHookHandler, &ServerHookHandler)| Arc::ptr_eq(pair.0, pair.1))
66 }
67}
68
69/// Implements the `Eq` trait for `Server`.
70///
71/// This indicates that `Server` has a total equality relation.
72impl Eq for Server {}
73
74/// Implementation of `From` trait for converting `usize` address into `Server`.
75impl From<usize> for Server {
76 /// Converts a memory address into an owned `Server` by cloning from the reference.
77 ///
78 /// # Arguments
79 ///
80 /// - `usize` - The memory address of the `Server` instance.
81 ///
82 /// # Returns
83 ///
84 /// - `Server` - A cloned `Server` instance from the given address.
85 #[inline(always)]
86 fn from(address: usize) -> Self {
87 let server: &Server = address.into();
88 server.clone()
89 }
90}
91
92/// Implementation of `From` trait for converting `usize` address into `&Server`.
93impl From<usize> for &'static Server {
94 /// Converts a memory address into a reference to `Server`.
95 ///
96 /// # Arguments
97 ///
98 /// - `usize` - The memory address of the `Server` instance.
99 ///
100 /// # Returns
101 ///
102 /// - `&'static Server` - A reference to the `Server` at the given address.
103 ///
104 /// # Safety
105 ///
106 /// - The address is guaranteed to be a valid `Server` instance
107 /// that was previously converted from a reference and is managed by the runtime.
108 #[inline(always)]
109 fn from(address: usize) -> &'static Server {
110 unsafe { &*(address as *const Server) }
111 }
112}
113
114/// Implementation of `From` trait for converting `usize` address into `&mut Server`.
115impl From<usize> for &'static mut Server {
116 /// Converts a memory address into a mutable reference to `Server`.
117 ///
118 /// # Arguments
119 ///
120 /// - `usize` - The memory address of the `Server` instance.
121 ///
122 /// # Returns
123 ///
124 /// - `&'static mut Server` - A mutable reference to the `Server` at the given address.
125 ///
126 /// # Safety
127 ///
128 /// - The address is guaranteed to be a valid `Server` instance
129 /// that was previously converted from a reference and is managed by the runtime.
130 #[inline(always)]
131 fn from(address: usize) -> &'static mut Server {
132 unsafe { &mut *(address as *mut Server) }
133 }
134}
135
136/// Implementation of `From` trait for converting `&Server` into `usize` address.
137impl From<&Server> for usize {
138 /// Converts a reference to `Server` into its memory address.
139 ///
140 /// # Arguments
141 ///
142 /// - `&Server` - The reference to the `Server` instance.
143 ///
144 /// # Returns
145 ///
146 /// - `usize` - The memory address of the `Server` instance.
147 #[inline(always)]
148 fn from(server: &Server) -> Self {
149 server as *const Server as usize
150 }
151}
152
153/// Implementation of `From` trait for converting `&mut Server` into `usize` address.
154impl From<&mut Server> for usize {
155 /// Converts a mutable reference to `Server` into its memory address.
156 ///
157 /// # Arguments
158 ///
159 /// - `&mut Server` - The mutable reference to the `Server` instance.
160 ///
161 /// # Returns
162 ///
163 /// - `usize` - The memory address of the `Server` instance.
164 #[inline(always)]
165 fn from(server: &mut Server) -> Self {
166 server as *mut Server as usize
167 }
168}
169
170/// Implementation of `AsRef` trait for `Server`.
171impl AsRef<Server> for Server {
172 /// Converts `&Server` to `&Server` via memory address conversion.
173 ///
174 /// # Returns
175 ///
176 /// - `&Self` - A reference to the `Server` instance.
177 #[inline(always)]
178 fn as_ref(&self) -> &Self {
179 let address: usize = self.into();
180 address.into()
181 }
182}
183
184/// Implementation of `AsMut` trait for `Server`.
185impl AsMut<Server> for Server {
186 /// Converts `&mut Server` to `&mut Server` via memory address conversion.
187 ///
188 /// # Returns
189 ///
190 /// - `&mut Self` - A mutable reference to the `Server` instance.
191 #[inline(always)]
192 fn as_mut(&mut self) -> &mut Self {
193 let address: usize = self.into();
194 address.into()
195 }
196}
197
198/// Converts a `ServerConfig` into a `Server` instance.
199///
200/// This allows creating a `Server` directly from its configuration,
201/// using default values for other fields.
202impl From<ServerConfig> for Server {
203 /// Creates a new `Server` instance from the given `ServerConfig`.
204 ///
205 /// # Arguments
206 ///
207 /// - `ServerConfig` - The server configuration to use.
208 ///
209 /// # Returns
210 ///
211 /// - `Self` - A new `Server` instance with the provided configuration.
212 #[inline(always)]
213 fn from(server_config: ServerConfig) -> Self {
214 Self {
215 server_config,
216 ..Default::default()
217 }
218 }
219}
220
221/// Converts a `RequestConfig` into a `Server` instance.
222///
223/// This allows creating a `Server` directly from its request configuration,
224/// using default values for other fields.
225impl From<RequestConfig> for Server {
226 /// Creates a new `Server` instance from the given `RequestConfig`.
227 ///
228 /// # Arguments
229 ///
230 /// - `RequestConfig` - The request configuration to use.
231 ///
232 /// # Returns
233 ///
234 /// - `Self` - A new `Server` instance with the provided request configuration.
235 #[inline(always)]
236 fn from(request_config: RequestConfig) -> Self {
237 Self {
238 request_config,
239 ..Default::default()
240 }
241 }
242}
243
244/// Implementation of `Lifetime` trait for `Server`.
245impl Lifetime for Server {
246 /// Converts a reference to the server into a `'static` reference.
247 ///
248 /// # Returns
249 ///
250 /// - `&'static Self` - A reference to the server with a `'static` lifetime.
251 ///
252 /// # Safety
253 ///
254 /// - The address is guaranteed to be a valid `Server` instance
255 /// that was previously converted from a reference and is managed by the runtime.
256 #[inline(always)]
257 unsafe fn leak(&self) -> &'static Self {
258 let address: usize = self.into();
259 address.into()
260 }
261
262 /// Converts a reference to the server into a `'static` mutable reference.
263 ///
264 /// # Returns
265 ///
266 /// - `&'static mut Self` - A mutable reference to the server with a `'static` lifetime.
267 ///
268 /// # Safety
269 ///
270 /// - The address is guaranteed to be a valid `Server` instance
271 /// that was previously converted from a reference and is managed by the runtime.
272 #[inline(always)]
273 unsafe fn leak_mut(&self) -> &'static mut Self {
274 let address: usize = self.into();
275 address.into()
276 }
277}
278
279/// Represents the server, providing methods to configure and run it.
280///
281/// This struct wraps the `Server` configuration and routing logic,
282/// offering a high-level API for setting up the HTTP and WebSocket server.
283impl Server {
284 /// Registers a hook into the server's processing pipeline.
285 ///
286 /// This function dispatches the provided `HookType` to the appropriate
287 /// internal hook collection based on its variant. The hook will be executed
288 /// at the corresponding stage of request processing according to its type:
289 /// - `Panic` - Added to panic handlers for error recovery
290 /// - `RequestError` - Added to request error handlers
291 /// - `RequestMiddleware` - Added to pre-route middleware chain
292 /// - `Route` - Registered as a route handler for the specified path
293 /// - `ResponseMiddleware` - Added to post-route middleware chain
294 ///
295 /// # Arguments
296 ///
297 /// - `HookType` - The `HookType` instance containing the hook configuration and factory.
298 #[inline]
299 pub fn handle_hook(&mut self, hook: HookType) {
300 match hook {
301 HookType::TaskPanic(_, hook) => {
302 self.get_mut_task_panic().push(hook());
303 }
304 HookType::RequestError(_, hook) => {
305 self.get_mut_request_error().push(hook());
306 }
307 HookType::RequestMiddleware(_, hook) => {
308 self.get_mut_request_middleware().push(hook());
309 }
310 HookType::Route(path, hook) => {
311 self.get_mut_route_matcher().add(path, hook()).unwrap();
312 }
313 HookType::ResponseMiddleware(_, hook) => {
314 self.get_mut_response_middleware().push(hook());
315 }
316 };
317 }
318
319 /// Sets the server configuration from a JSON string.
320 ///
321 /// # Arguments
322 ///
323 /// - `C` - The configuration.
324 ///
325 /// # Returns
326 ///
327 /// - `&mut Self` - Reference to self for method chaining.
328 #[inline]
329 pub fn config_from_json<C>(&mut self, json: C) -> &mut Self
330 where
331 C: AsRef<str>,
332 {
333 let config: ServerConfig = serde_json::from_str(json.as_ref()).unwrap();
334 self.set_server_config(config);
335 self
336 }
337
338 /// Sets the server configuration.
339 ///
340 /// # Arguments
341 ///
342 /// - `ServerConfig` - The server configuration.
343 ///
344 /// # Returns
345 ///
346 /// - `&mut Self` - Reference to self for method chaining.
347 #[inline(always)]
348 pub fn server_config(&mut self, config: ServerConfig) -> &mut Self {
349 self.set_server_config(config);
350 self
351 }
352
353 /// Sets the HTTP request config.
354 ///
355 /// # Arguments
356 ///
357 /// - `RequestConfig` - The HTTP request config to set.
358 ///
359 /// # Returns
360 ///
361 /// - `&mut Self` - Reference to self for method chaining.
362 #[inline(always)]
363 pub fn request_config(&mut self, config: RequestConfig) -> &mut Self {
364 self.set_request_config(config);
365 self
366 }
367
368 /// Registers a task panic handler to the processing pipeline.
369 ///
370 /// This method allows registering task panic handlers that implement the `ServerHook` trait,
371 /// which will be executed when a panic occurs during request processing.
372 ///
373 /// # Returns
374 ///
375 /// - `&mut Self` - Reference to self for method chaining.
376 #[inline(always)]
377 pub fn task_panic<S>(&mut self) -> &mut Self
378 where
379 S: ServerHook,
380 {
381 self.get_mut_task_panic().push(Hook::factory::<S>());
382 self
383 }
384
385 /// Registers a request error handler to the processing pipeline.
386 ///
387 /// This method allows registering request error handlers that implement the `ServerHook` trait,
388 /// which will be executed when a request error occurs during HTTP request processing.
389 ///
390 /// # Returns
391 ///
392 /// - `&mut Self` - Reference to self for method chaining.
393 #[inline(always)]
394 pub fn request_error<S>(&mut self) -> &mut Self
395 where
396 S: ServerHook,
397 {
398 self.get_mut_request_error().push(Hook::factory::<S>());
399 self
400 }
401
402 /// Registers a route hook for a specific path.
403 ///
404 /// This method allows registering route handlers that implement the `ServerHook` trait,
405 /// providing type safety and better code organization.
406 ///
407 /// # Arguments
408 ///
409 /// - `impl AsRef<str>` - The route path pattern.
410 ///
411 /// # Returns
412 ///
413 /// - `&mut Self` - Reference to self for method chaining.
414 #[inline(always)]
415 pub fn route<S>(&mut self, path: impl AsRef<str>) -> &mut Self
416 where
417 S: ServerHook,
418 {
419 self.get_mut_route_matcher()
420 .add(path.as_ref(), Hook::factory::<S>())
421 .unwrap();
422 self
423 }
424
425 /// Registers request middleware to the processing pipeline.
426 ///
427 /// This method allows registering middleware that implements the `ServerHook` trait,
428 /// which will be executed before route handlers for every incoming request.
429 ///
430 /// # Returns
431 ///
432 /// - `&mut Self` - Reference to self for method chaining.
433 #[inline(always)]
434 pub fn request_middleware<S>(&mut self) -> &mut Self
435 where
436 S: ServerHook,
437 {
438 self.get_mut_request_middleware().push(Hook::factory::<S>());
439 self
440 }
441
442 /// Registers response middleware to the processing pipeline.
443 ///
444 /// This method allows registering middleware that implements the `ServerHook` trait,
445 /// which will be executed after route handlers for every outgoing response.
446 ///
447 /// # Returns
448 ///
449 /// - `&mut Self` - Reference to self for method chaining.
450 #[inline(always)]
451 pub fn response_middleware<S>(&mut self) -> &mut Self
452 where
453 S: ServerHook,
454 {
455 self.get_mut_response_middleware()
456 .push(Hook::factory::<S>());
457 self
458 }
459
460 /// Format the host and port into a bindable address string.
461 ///
462 /// # Arguments
463 ///
464 /// - `H` - The host address.
465 /// - `u16` - The port number.
466 ///
467 /// # Returns
468 ///
469 /// - `String` - The formatted address string in the form "host:port".
470 #[inline(always)]
471 pub fn format_bind_address<H>(host: H, port: u16) -> String
472 where
473 H: AsRef<str>,
474 {
475 format!("{}{COLON}{port}", host.as_ref())
476 }
477
478 /// Flushes the standard output stream.
479 ///
480 /// # Returns
481 ///
482 /// - `io::Result<()>` - The result of the flush operation.
483 #[inline(always)]
484 pub fn try_flush_stdout() -> io::Result<()> {
485 stdout().flush()
486 }
487
488 /// Flushes the standard output stream.
489 ///
490 /// # Panics
491 ///
492 /// This function will panic if the flush operation fails.
493 #[inline(always)]
494 pub fn flush_stdout() {
495 stdout().flush().unwrap();
496 }
497
498 /// Flushes the standard error stream.
499 ///
500 /// # Returns
501 ///
502 /// - `io::Result<()>` - The result of the flush operation.
503 #[inline(always)]
504 pub fn try_flush_stderr() -> io::Result<()> {
505 stderr().flush()
506 }
507
508 /// Flushes the standard error stream.
509 ///
510 /// # Panics
511 ///
512 /// This function will panic if the flush operation fails.
513 #[inline(always)]
514 pub fn flush_stderr() {
515 stderr().flush().unwrap();
516 }
517
518 /// Flushes both the standard output and error streams.
519 ///
520 /// # Returns
521 ///
522 /// - `io::Result<()>` - The result of the flush operation.
523 #[inline(always)]
524 pub fn try_flush_stdout_and_stderr() -> io::Result<()> {
525 Self::try_flush_stdout()?;
526 Self::try_flush_stderr()
527 }
528
529 /// Flushes both the standard output and error streams.
530 ///
531 /// # Panics
532 ///
533 /// This function will panic if either flush operation fails.
534 #[inline(always)]
535 pub fn flush_stdout_and_stderr() {
536 Self::flush_stdout();
537 Self::flush_stderr();
538 }
539
540 /// Executes trait-based request middleware in sequence.
541 ///
542 /// # Arguments
543 ///
544 /// - `&mut Stream` - The `Stream` for the current request.
545 /// - `&mut Context` - The `Context` for the current request.
546 ///
547 /// # Returns
548 ///
549 /// - `bool` - `true` if the lifecycle was aborted, `false` otherwise.
550 pub(super) async fn handle_request_middleware(
551 &self,
552 stream: &mut Stream,
553 ctx: &mut Context,
554 ) -> bool {
555 for hook in self.get_request_middleware().iter() {
556 if hook(stream, ctx).await.is_reject() {
557 return true;
558 }
559 }
560 false
561 }
562
563 /// Executes a trait-based route hook if one matches.
564 ///
565 /// # Arguments
566 ///
567 /// - `&mut Stream` - The `Stream` for the current request.
568 /// - `&mut Context` - The `Context` for the current request.
569 /// - `&str` - The request path to match.
570 ///
571 /// # Returns
572 ///
573 /// - `bool` - `true` if the lifecycle was aborted, `false` otherwise.
574 pub(super) async fn handle_route_matcher(
575 &self,
576 stream: &mut Stream,
577 ctx: &mut Context,
578 path: &str,
579 ) -> bool {
580 if let Some(hook) = self.get_route_matcher().try_resolve_route(ctx, path)
581 && hook(stream, ctx).await.is_reject()
582 {
583 return true;
584 }
585 false
586 }
587
588 /// Executes trait-based response middleware in sequence.
589 ///
590 /// # Arguments
591 ///
592 /// - `&mut Stream` - The `Stream` for the current request.
593 /// - `&mut Context` - The `Context` for the current request.
594 ///
595 /// # Returns
596 ///
597 /// - `bool` - `true` if the lifecycle was aborted, `false` otherwise.
598 pub(super) async fn handle_response_middleware(
599 &self,
600 stream: &mut Stream,
601 ctx: &mut Context,
602 ) -> bool {
603 for hook in self.get_response_middleware().iter() {
604 if hook(stream, ctx).await.is_reject() {
605 return true;
606 }
607 }
608 false
609 }
610
611 /// Handles errors that occur while processing HTTP requests.
612 ///
613 /// # Arguments
614 ///
615 /// - `&mut Stream` - The `Stream` for the current request.
616 /// - `&mut Context` - The `Context` for the current request.
617 /// - `&RequestError` - The error that occurred.
618 pub async fn handle_request_error(
619 &self,
620 stream: &mut Stream,
621 ctx: &mut Context,
622 error: &RequestError,
623 ) {
624 ctx.set_request_error_data(error.clone());
625 stream.set_closed(false);
626 for hook in self.get_request_error().iter() {
627 if hook(stream, ctx).await.is_reject() {
628 return;
629 }
630 }
631 }
632
633 /// The core request handling pipeline.
634 ///
635 /// This function orchestrates the execution of request middleware, the route hook,
636 /// and response middleware. It supports both function-based and trait-based handlers.
637 ///
638 /// # Arguments
639 ///
640 /// - `&mut Stream` - The `Stream` for the current request.
641 /// - `&mut Context` - The `Context` for the current request.
642 /// - `Request` - The incoming request to be processed.
643 ///
644 /// # Returns
645 ///
646 /// - `bool` - A boolean indicating whether the connection should be kept alive.
647 pub(crate) async fn request_hook(
648 &self,
649 stream: &mut Stream,
650 ctx: &mut Context,
651 request: Request,
652 ) -> bool {
653 let keep_alive: bool = request.is_enable_keep_alive();
654 let version: RequestVersion = request.get_version().clone();
655 ctx.set_request(request);
656 ctx.get_mut_response().reset().set_version(version);
657 ctx.clear_route_params();
658 ctx.clear_attribute();
659 stream.set_closed(false);
660 if self.handle_request_middleware(stream, ctx).await {
661 return stream.is_keep_alive(keep_alive);
662 }
663 // A static route is the common case and needs nothing but the path,
664 // so the path is borrowed from the request instead of being copied
665 // out of it. Only a pattern route, which is the rarer case, pays for
666 // the copy.
667 let static_hook: Option<&ServerHookHandler> = {
668 let path: &str = ctx.get_request().get_path().as_str();
669 self.get_route_matcher().try_resolve_static_route(path)
670 };
671 if let Some(hook) = static_hook {
672 if hook(stream, ctx).await.is_reject() {
673 return stream.is_keep_alive(keep_alive);
674 }
675 } else {
676 let route: RequestPath = ctx.get_request().get_path().clone();
677 if self.handle_route_matcher(stream, ctx, &route).await {
678 return stream.is_keep_alive(keep_alive);
679 }
680 }
681 if self.handle_response_middleware(stream, ctx).await {
682 return stream.is_keep_alive(keep_alive);
683 }
684 stream.is_keep_alive(keep_alive)
685 }
686
687 /// Handles subsequent HTTP requests on a persistent (keep-alive) connection.
688 ///
689 /// # Arguments
690 ///
691 /// - `&mut Stream` - The `Stream` for the current request.
692 /// - `&mut Context` - The `Context` for the current request.
693 /// - `Request` - The initial request that established the keep-alive connection.
694 async fn handle_http_requests(&self, stream: &mut Stream, ctx: &mut Context, request: Request) {
695 if !self.request_hook(stream, ctx, request).await {
696 return;
697 }
698 loop {
699 let mut reused_request: Request = mem::take(ctx.get_mut_request());
700 match stream.try_fill_http_request(&mut reused_request).await {
701 Ok(()) => {
702 if !self.request_hook(stream, ctx, reused_request).await {
703 return;
704 }
705 }
706 Err(error) => {
707 ctx.set_request(reused_request);
708 self.handle_request_error(stream, ctx, &error).await;
709 return;
710 }
711 }
712 }
713 }
714
715 /// Handles a single client connection, determining whether it's an HTTP or WebSocket request.
716 ///
717 /// It reads the initial request from the stream and dispatches it to the appropriate hook.
718 /// Both arguments are borrowed: the stream and the context belong to the
719 /// caller, so this leaves them alive for whatever runs next — the panic
720 /// hooks after an unwind, or the next request on a keep alive connection.
721 ///
722 /// # Arguments
723 ///
724 /// - `&mut Stream` - The `Stream` for the current request.
725 /// - `&mut Context` - The `Context` for the current request.
726 async fn handle_connection(&self, stream: &mut Stream, ctx: &mut Context) {
727 match stream.try_get_http_request().await {
728 Ok(request) => {
729 self.handle_http_requests(stream, ctx, request).await;
730 }
731 Err(error) => {
732 self.handle_request_error(stream, ctx, &error).await;
733 }
734 }
735 }
736
737 /// Serves one HTTP/1.1 connection through the existing keep alive pipeline.
738 ///
739 /// This is the same pipeline a plaintext connection has always used: the
740 /// request parser runs in a loop, so keep alive, upgrades and raw writes
741 /// behave exactly as they did before TLS and the multiplexed protocols
742 /// existed. A handler that panics is caught here and reported through the
743 /// existing task panic hooks, so the accept loop survives it and the hooks
744 /// see the panic while the stream and context are still alive.
745 ///
746 /// # Arguments
747 ///
748 /// - `&mut Stream` - The stream carrying the connection.
749 ///
750 /// # Returns
751 ///
752 /// - `()` - Resolves once the connection is finished.
753 pub(crate) async fn serve_h1_connection_stream(&self, stream: &mut Stream) {
754 let mut ctx: Context = Context::default();
755 let panicked: Option<PanicData> =
756 catch_connection_panic(self.handle_connection(stream, &mut ctx)).await;
757 let Some(panic) = panicked else {
758 return;
759 };
760 ctx.set_task_panic(panic)
761 .get_mut_response()
762 .set_status_code(HttpStatus::InternalServerError.code());
763 stream.set_closed(false);
764 for hook in self.get_task_panic().iter() {
765 if hook(stream, &mut ctx).await.is_reject() {
766 break;
767 }
768 }
769 }
770
771 /// Serves one request that arrived on a multiplexed protocol stream.
772 ///
773 /// The lifecycle is the one an HTTP/1.1 request runs: the request
774 /// middleware, the matched route and the response middleware, in that
775 /// order, against the same context and the same error hook. A panic inside
776 /// it is caught the same way a connection panic is.
777 ///
778 /// # Arguments
779 ///
780 /// - `&mut Stream` - The stream the pipeline writes its response onto.
781 /// - `&mut Context` - The context for the current request.
782 /// - `Request` - The request converted from the protocol head and body.
783 ///
784 /// # Returns
785 ///
786 /// - `()` - Resolves once the pipeline has finished writing.
787 pub(crate) async fn run_protocol_lifecycle(
788 &self,
789 stream: &mut Stream,
790 ctx: &mut Context,
791 request: Request,
792 ) {
793 let panicked: Option<PanicData> = catch_connection_panic(async {
794 let _keep_alive: bool = self.request_hook(stream, ctx, request).await;
795 })
796 .await;
797 let Some(panic) = panicked else {
798 return;
799 };
800 ctx.set_task_panic(panic)
801 .get_mut_response()
802 .set_status_code(HttpStatus::InternalServerError.code());
803 stream.set_closed(false);
804 for hook in self.get_task_panic().iter() {
805 if hook(stream, ctx).await.is_reject() {
806 break;
807 }
808 }
809 }
810
811 /// Starts the server, binds to the configured address, and begins listening.
812 ///
813 /// The configured protocol selects the listener. HTTP/1.1 and HTTP/2 share
814 /// the TCP listener, the latter speaking its own preface and optionally
815 /// wrapping the connection in TLS, while HTTP/3 binds a QUIC UDP endpoint.
816 /// Invalid TLS material and an HTTP/3 configuration without TLS are both
817 /// rejected before the socket is bound, so a misconfigured server fails to
818 /// start rather than accepting connections it cannot serve.
819 ///
820 /// The accept loop owns a clone of the server instead of borrowing it, so
821 /// running a short lived `Server` stays safe and dropping it leaves no
822 /// leaked allocation behind.
823 ///
824 /// # Returns
825 ///
826 /// - `Result<ServerControlHook, Box<ServerError>>` - The shutdown hook on
827 /// success, or the failure that prevented the server from binding.
828 pub async fn run(&self) -> Result<ServerControlHook, Box<ServerError>> {
829 let server_config: &ServerConfig = self.get_server_config();
830 let protocol: ServerProtocol = server_config.get_protocol();
831 let tls_config: Option<TlsConfig> = server_config.get_tls().clone();
832 if protocol == ServerProtocol::Http3 && tls_config.is_none() {
833 return Err(Box::new(ServerError::MissingTlsForHttp3));
834 }
835 let stream_tls: Option<Arc<rustls::ServerConfig>> = match tls_config.clone() {
836 Some(_) if protocol == ServerProtocol::Http3 => None,
837 Some(config) => Some(build_stream_tls_config(&config, &protocol)?),
838 None => None,
839 };
840 let bind_address: &String = server_config.get_address();
841 let server: Arc<Server> = Arc::new(Self::clone(self));
842 let request_config: RequestConfig = *self.get_request_config();
843 let (shutdown_sender, shutdown_receiver) = channel(());
844 let (running_sender, running_receiver) = channel(SERVER_RUNNING);
845 let _: JoinHandle<()> = match protocol {
846 ServerProtocol::Http3 => {
847 let Some(config) = tls_config.clone() else {
848 return Err(Box::new(ServerError::MissingTlsForHttp3));
849 };
850 let quic_config: Arc<quinn::crypto::rustls::QuicServerConfig> = Arc::new(
851 quinn::crypto::rustls::QuicServerConfig::try_from(build_quic_tls_config(
852 &config,
853 )?)
854 .map_err(
855 |error: quinn::crypto::rustls::NoInitialCipherSuite| {
856 Box::new(ServerError::Tls(format!(
857 "no compatible cipher suite for quic: {}",
858 error
859 )))
860 },
861 )?,
862 );
863 let bind_addr: SocketAddr =
864 bind_address
865 .parse::<SocketAddr>()
866 .map_err(|error: AddrParseError| {
867 Box::new(ServerError::Tls(format!(
868 "invalid bind address {}: {}",
869 bind_address, error
870 )))
871 })?;
872 let endpoint: Endpoint =
873 Endpoint::server(quinn::ServerConfig::with_crypto(quic_config), bind_addr)
874 .map_err(|error: io::Error| Box::new(ServerError::from(error)))?;
875 let env: ConnectionEnv = ConnectionEnv {
876 server,
877 request_config,
878 protocol,
879 };
880 spawn(async move {
881 let _: Result<(), Box<ServerError>> =
882 quic_accept(env, endpoint, shutdown_receiver, running_sender).await;
883 })
884 }
885 _ => {
886 let tcp_listener: TcpListener = TcpListener::bind(&bind_address)
887 .await
888 .map_err(|error: io::Error| Box::new(ServerError::from(error)))?;
889 let env: ConnectionEnv = ConnectionEnv {
890 server,
891 request_config,
892 protocol,
893 };
894 spawn(async move {
895 tcp_accept(
896 env,
897 stream_tls,
898 AcceptSignal {
899 listener: tcp_listener,
900 shutdown_receiver,
901 running_sender,
902 },
903 )
904 .await;
905 })
906 }
907 };
908 let wait_hook: ServerControlHookHandler<()> = Arc::new(move || {
909 let mut running_receiver_clone: Receiver<bool> = running_receiver.clone();
910 Box::pin(async move {
911 while !*running_receiver_clone.borrow_and_update() {
912 let _: Result<(), tokio::sync::watch::error::RecvError> =
913 running_receiver_clone.changed().await;
914 }
915 })
916 });
917 let shutdown_hook: ServerControlHookHandler<()> = Arc::new(move || {
918 let shutdown_sender_clone: Sender<()> = shutdown_sender.clone();
919 Box::pin(async move {
920 let _: Result<(), tokio::sync::watch::error::SendError<()>> =
921 shutdown_sender_clone.send(());
922 })
923 });
924 let mut server_control_hook: ServerControlHook = ServerControlHook::default();
925 server_control_hook.set_shutdown_hook(shutdown_hook);
926 server_control_hook.set_wait_hook(wait_hook);
927 Ok(server_control_hook)
928 }
929}