1#![forbid(unsafe_code)]
2#![deny(missing_docs)]
3
4pub mod client;
104
105pub mod server;
107
108pub mod codec;
110
111#[macro_use]
112pub mod error;
114pub mod middleware;
116pub mod redirect;
118pub mod request;
120pub mod response;
122
123#[cfg(feature = "actix-no-default")]
124#[doc(hidden)]
125pub use ::actix_web as actix_export;
126#[cfg(feature = "axum-no-default")]
127#[doc(hidden)]
128pub use ::axum as axum_export;
129#[cfg(feature = "generic")]
130#[doc(hidden)]
131pub use ::bytes as bytes_export;
132#[cfg(feature = "generic")]
133#[doc(hidden)]
134pub use ::http as http_export;
135use base64::{engine::general_purpose::STANDARD_NO_PAD, DecodeError, Engine};
136#[cfg(feature = "bitcode")]
137pub use bitcode;
138pub use bytes::Bytes;
141use bytes::{BufMut, BytesMut};
142use client::Client;
143use codec::{Encoding, FromReq, FromRes, IntoReq, IntoRes};
144#[doc(hidden)]
145pub use const_format;
146#[doc(hidden)]
147pub use const_str;
148use dashmap::DashMap;
149pub use error::ServerFnError;
150#[cfg(feature = "form-redirects")]
151use error::ServerFnUrlError;
152use error::{FromServerFnError, ServerFnErrorErr};
153use futures::{pin_mut, SinkExt, Stream, StreamExt};
154use http::Method;
155use middleware::{BoxedService, Layer, Service};
156use redirect::call_redirect_hook;
157use request::Req;
158use response::{ClientRes, Res, TryRes};
159#[cfg(feature = "rkyv")]
160pub use rkyv;
161#[doc(hidden)]
162pub use serde;
163#[doc(hidden)]
164#[cfg(feature = "serde-lite")]
165pub use serde_lite;
166use server::Server;
167use std::{
168    fmt::{Debug, Display},
169    future::Future,
170    marker::PhantomData,
171    ops::{Deref, DerefMut},
172    pin::Pin,
173    sync::{Arc, LazyLock},
174};
175#[doc(hidden)]
176pub use xxhash_rust;
177
178type ServerFnServerRequest<Fn> = <<Fn as ServerFn>::Server as crate::Server<
179    <Fn as ServerFn>::Error,
180    <Fn as ServerFn>::InputStreamError,
181    <Fn as ServerFn>::OutputStreamError,
182>>::Request;
183type ServerFnServerResponse<Fn> = <<Fn as ServerFn>::Server as crate::Server<
184    <Fn as ServerFn>::Error,
185    <Fn as ServerFn>::InputStreamError,
186    <Fn as ServerFn>::OutputStreamError,
187>>::Response;
188
189pub trait ServerFn: Send + Sized {
219    const PATH: &'static str;
221
222    type Client: Client<
226        Self::Error,
227        Self::InputStreamError,
228        Self::OutputStreamError,
229    >;
230
231    type Server: Server<
235        Self::Error,
236        Self::InputStreamError,
237        Self::OutputStreamError,
238    >;
239
240    type Protocol: Protocol<
242        Self,
243        Self::Output,
244        Self::Client,
245        Self::Server,
246        Self::Error,
247        Self::InputStreamError,
248        Self::OutputStreamError,
249    >;
250
251    type Output: Send;
256
257    type Error: FromServerFnError + Send + Sync;
260    type InputStreamError: FromServerFnError + Send + Sync;
263    type OutputStreamError: FromServerFnError + Send + Sync;
266
267    fn url() -> &'static str {
269        Self::PATH
270    }
271
272    fn middlewares() -> Vec<
274        Arc<
275            dyn Layer<
276                ServerFnServerRequest<Self>,
277                ServerFnServerResponse<Self>,
278            >,
279        >,
280    > {
281        Vec::new()
282    }
283
284    fn run_body(
286        self,
287    ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send;
288
289    #[doc(hidden)]
290    fn run_on_server(
291        req: ServerFnServerRequest<Self>,
292    ) -> impl Future<Output = ServerFnServerResponse<Self>> + Send {
293        #[cfg(feature = "form-redirects")]
297        let accepts_html = req
298            .accepts()
299            .map(|n| n.contains("text/html"))
300            .unwrap_or(false);
301        #[cfg(feature = "form-redirects")]
302        let mut referer = req.referer().as_deref().map(ToOwned::to_owned);
303
304        async move {
305            #[allow(unused_variables, unused_mut)]
306            let (mut res, err) =
308                Self::Protocol::run_server(req, Self::run_body)
309                    .await
310                    .map(|res| (res, None))
311                    .unwrap_or_else(|e| {
312                        let mut response =
313                            <<Self as ServerFn>::Server as crate::Server<
314                                Self::Error,
315                                Self::InputStreamError,
316                                Self::OutputStreamError,
317                            >>::Response::error_response(
318                                Self::PATH, e.ser()
319                            );
320                        let content_type =
321                    <Self::Error as FromServerFnError>::Encoder::CONTENT_TYPE;
322                        response.content_type(content_type);
323                        (response, Some(e))
324                    });
325
326            #[cfg(feature = "form-redirects")]
328            if accepts_html {
329                if let Some(err) = err {
331                    if let Ok(url) = ServerFnUrlError::new(Self::PATH, err)
332                        .to_url(referer.as_deref().unwrap_or("/"))
333                    {
334                        referer = Some(url.to_string());
335                    }
336                }
337                else if let Some(referer) = referer.as_mut() {
340                    ServerFnUrlError::<Self::Error>::strip_error_info(referer)
341                }
342
343                res.redirect(referer.as_deref().unwrap_or("/"));
345            }
346
347            res
348        }
349    }
350
351    #[doc(hidden)]
352    fn run_on_client(
353        self,
354    ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send {
355        async move { Self::Protocol::run_client(Self::PATH, self).await }
356    }
357}
358
359pub trait Protocol<
363    Input,
364    Output,
365    Client,
366    Server,
367    Error,
368    InputStreamError = Error,
369    OutputStreamError = Error,
370> where
371    Server: crate::Server<Error, InputStreamError, OutputStreamError>,
372    Client: crate::Client<Error, InputStreamError, OutputStreamError>,
373{
374    const METHOD: Method;
376
377    fn run_server<F, Fut>(
380        request: Server::Request,
381        server_fn: F,
382    ) -> impl Future<Output = Result<Server::Response, Error>> + Send
383    where
384        F: Fn(Input) -> Fut + Send,
385        Fut: Future<Output = Result<Output, Error>> + Send;
386
387    fn run_client(
390        path: &str,
391        input: Input,
392    ) -> impl Future<Output = Result<Output, Error>> + Send;
393}
394
395pub struct Http<InputProtocol, OutputProtocol>(
431    PhantomData<(InputProtocol, OutputProtocol)>,
432);
433
434impl<InputProtocol, OutputProtocol, Input, Output, Client, Server, E>
435    Protocol<Input, Output, Client, Server, E>
436    for Http<InputProtocol, OutputProtocol>
437where
438    Input: IntoReq<InputProtocol, Client::Request, E>
439        + FromReq<InputProtocol, Server::Request, E>
440        + Send,
441    Output: IntoRes<OutputProtocol, Server::Response, E>
442        + FromRes<OutputProtocol, Client::Response, E>
443        + Send,
444    E: FromServerFnError,
445    InputProtocol: Encoding,
446    OutputProtocol: Encoding,
447    Client: crate::Client<E>,
448    Server: crate::Server<E>,
449{
450    const METHOD: Method = InputProtocol::METHOD;
451
452    async fn run_server<F, Fut>(
453        request: Server::Request,
454        server_fn: F,
455    ) -> Result<Server::Response, E>
456    where
457        F: Fn(Input) -> Fut + Send,
458        Fut: Future<Output = Result<Output, E>> + Send,
459    {
460        let input = Input::from_req(request).await?;
461
462        let output = server_fn(input).await?;
463
464        let response = Output::into_res(output).await?;
465
466        Ok(response)
467    }
468
469    async fn run_client(path: &str, input: Input) -> Result<Output, E>
470    where
471        Client: crate::Client<E>,
472    {
473        let req = input.into_req(path, OutputProtocol::CONTENT_TYPE)?;
475        let res = Client::send(req).await?;
476
477        let status = res.status();
478        let location = res.location();
479        let has_redirect_header = res.has_redirect();
480
481        let res = if (400..=599).contains(&status) {
483            Err(E::de(res.try_into_bytes().await?))
484        } else {
485            let output = Output::from_res(res).await?;
487            Ok(output)
488        }?;
489
490        if (300..=399).contains(&status) || has_redirect_header {
492            call_redirect_hook(&location);
493        }
494        Ok(res)
495    }
496}
497
498pub struct Websocket<InputEncoding, OutputEncoding>(
531    PhantomData<(InputEncoding, OutputEncoding)>,
532);
533
534pub struct BoxedStream<T, E> {
549    stream: Pin<Box<dyn Stream<Item = Result<T, E>> + Send>>,
550}
551
552impl<T, E> From<BoxedStream<T, E>>
553    for Pin<Box<dyn Stream<Item = Result<T, E>> + Send>>
554{
555    fn from(val: BoxedStream<T, E>) -> Self {
556        val.stream
557    }
558}
559
560impl<T, E> Deref for BoxedStream<T, E> {
561    type Target = Pin<Box<dyn Stream<Item = Result<T, E>> + Send>>;
562    fn deref(&self) -> &Self::Target {
563        &self.stream
564    }
565}
566
567impl<T, E> DerefMut for BoxedStream<T, E> {
568    fn deref_mut(&mut self) -> &mut Self::Target {
569        &mut self.stream
570    }
571}
572
573impl<T, E> Debug for BoxedStream<T, E> {
574    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
575        f.debug_struct("BoxedStream").finish()
576    }
577}
578
579impl<T, E, S> From<S> for BoxedStream<T, E>
580where
581    S: Stream<Item = Result<T, E>> + Send + 'static,
582{
583    fn from(stream: S) -> Self {
584        BoxedStream {
585            stream: Box::pin(stream),
586        }
587    }
588}
589
590impl<
591        Input,
592        InputItem,
593        OutputItem,
594        InputEncoding,
595        OutputEncoding,
596        Client,
597        Server,
598        Error,
599        InputStreamError,
600        OutputStreamError,
601    >
602    Protocol<
603        Input,
604        BoxedStream<OutputItem, OutputStreamError>,
605        Client,
606        Server,
607        Error,
608        InputStreamError,
609        OutputStreamError,
610    > for Websocket<InputEncoding, OutputEncoding>
611where
612    Input: Deref<Target = BoxedStream<InputItem, InputStreamError>>
613        + Into<BoxedStream<InputItem, InputStreamError>>
614        + From<BoxedStream<InputItem, InputStreamError>>,
615    InputEncoding: Encodes<InputItem> + Decodes<InputItem>,
616    OutputEncoding: Encodes<OutputItem> + Decodes<OutputItem>,
617    InputStreamError: FromServerFnError + Send,
618    OutputStreamError: FromServerFnError + Send,
619    Error: FromServerFnError + Send,
620    Server: crate::Server<Error, InputStreamError, OutputStreamError>,
621    Client: crate::Client<Error, InputStreamError, OutputStreamError>,
622    OutputItem: Send + 'static,
623    InputItem: Send + 'static,
624{
625    const METHOD: Method = Method::GET;
626
627    async fn run_server<F, Fut>(
628        request: Server::Request,
629        server_fn: F,
630    ) -> Result<Server::Response, Error>
631    where
632        F: Fn(Input) -> Fut + Send,
633        Fut: Future<
634                Output = Result<
635                    BoxedStream<OutputItem, OutputStreamError>,
636                    Error,
637                >,
638            > + Send,
639    {
640        let (request_bytes, response_stream, response) =
641            request.try_into_websocket().await?;
642        let input = request_bytes.map(|request_bytes| {
643            let request_bytes = request_bytes
644                .map(|bytes| deserialize_result::<InputStreamError>(bytes))
645                .unwrap_or_else(Err);
646            match request_bytes {
647                Ok(request_bytes) => InputEncoding::decode(request_bytes)
648                    .map_err(|e| {
649                        InputStreamError::from_server_fn_error(
650                            ServerFnErrorErr::Deserialization(e.to_string()),
651                        )
652                    }),
653                Err(err) => Err(InputStreamError::de(err)),
654            }
655        });
656        let boxed = Box::pin(input)
657            as Pin<
658                Box<
659                    dyn Stream<Item = Result<InputItem, InputStreamError>>
660                        + Send,
661                >,
662            >;
663        let input = BoxedStream { stream: boxed };
664
665        let output = server_fn(input.into()).await?;
666
667        let output = output.stream.map(|output| {
668            let result = match output {
669                Ok(output) => OutputEncoding::encode(&output).map_err(|e| {
670                    OutputStreamError::from_server_fn_error(
671                        ServerFnErrorErr::Serialization(e.to_string()),
672                    )
673                    .ser()
674                }),
675                Err(err) => Err(err.ser()),
676            };
677            serialize_result(result)
678        });
679
680        Server::spawn(async move {
681            pin_mut!(response_stream);
682            pin_mut!(output);
683            while let Some(output) = output.next().await {
684                if response_stream.send(output).await.is_err() {
685                    break;
686                }
687            }
688        })?;
689
690        Ok(response)
691    }
692
693    fn run_client(
694        path: &str,
695        input: Input,
696    ) -> impl Future<
697        Output = Result<BoxedStream<OutputItem, OutputStreamError>, Error>,
698    > + Send {
699        let input = input.into();
700
701        async move {
702            let (stream, sink) = Client::open_websocket(path).await?;
703
704            Client::spawn(async move {
706                pin_mut!(input);
707                pin_mut!(sink);
708                while let Some(input) = input.stream.next().await {
709                    let result = match input {
710                        Ok(input) => {
711                            InputEncoding::encode(&input).map_err(|e| {
712                                InputStreamError::from_server_fn_error(
713                                    ServerFnErrorErr::Serialization(
714                                        e.to_string(),
715                                    ),
716                                )
717                                .ser()
718                            })
719                        }
720                        Err(err) => Err(err.ser()),
721                    };
722                    let result = serialize_result(result);
723                    if sink.send(result).await.is_err() {
724                        break;
725                    }
726                }
727            });
728
729            let stream = stream.map(|request_bytes| {
731                let request_bytes = request_bytes
732                    .map(|bytes| deserialize_result::<OutputStreamError>(bytes))
733                    .unwrap_or_else(Err);
734                match request_bytes {
735                    Ok(request_bytes) => OutputEncoding::decode(request_bytes)
736                        .map_err(|e| {
737                            OutputStreamError::from_server_fn_error(
738                                ServerFnErrorErr::Deserialization(
739                                    e.to_string(),
740                                ),
741                            )
742                        }),
743                    Err(err) => Err(OutputStreamError::de(err)),
744                }
745            });
746            let boxed = Box::pin(stream)
747                as Pin<
748                    Box<
749                        dyn Stream<Item = Result<OutputItem, OutputStreamError>>
750                            + Send,
751                    >,
752                >;
753            let output = BoxedStream { stream: boxed };
754            Ok(output)
755        }
756    }
757}
758
759fn serialize_result(result: Result<Bytes, Bytes>) -> Bytes {
764    match result {
765        Ok(bytes) => {
766            let mut buf = BytesMut::with_capacity(1 + bytes.len());
767            buf.put_u8(0); buf.extend_from_slice(&bytes);
769            buf.freeze()
770        }
771        Err(bytes) => {
772            let mut buf = BytesMut::with_capacity(1 + bytes.len());
773            buf.put_u8(1); buf.extend_from_slice(&bytes);
775            buf.freeze()
776        }
777    }
778}
779
780fn deserialize_result<E: FromServerFnError>(
782    bytes: Bytes,
783) -> Result<Bytes, Bytes> {
784    if bytes.is_empty() {
785        return Err(E::from_server_fn_error(
786            ServerFnErrorErr::Deserialization("Data is empty".into()),
787        )
788        .ser());
789    }
790
791    let tag = bytes[0];
792    let content = bytes.slice(1..);
793
794    match tag {
795        0 => Ok(content),
796        1 => Err(content),
797        _ => Err(E::from_server_fn_error(ServerFnErrorErr::Deserialization(
798            "Invalid data tag".into(),
799        ))
800        .ser()), }
802}
803
804pub enum Format {
806    Binary,
808    Text,
810}
811pub trait ContentType {
813    const CONTENT_TYPE: &'static str;
815}
816
817pub trait FormatType {
819    const FORMAT_TYPE: Format;
821
822    fn into_encoded_string(bytes: Bytes) -> String {
824        match Self::FORMAT_TYPE {
825            Format::Binary => STANDARD_NO_PAD.encode(bytes),
826            Format::Text => String::from_utf8(bytes.into())
827                .expect("Valid text format type with utf-8 comptabile string"),
828        }
829    }
830
831    fn from_encoded_string(data: &str) -> Result<Bytes, DecodeError> {
833        match Self::FORMAT_TYPE {
834            Format::Binary => {
835                STANDARD_NO_PAD.decode(data).map(|data| data.into())
836            }
837            Format::Text => Ok(Bytes::copy_from_slice(data.as_bytes())),
838        }
839    }
840}
841
842pub trait Encodes<T>: ContentType + FormatType {
844    type Error: Display + Debug;
846
847    fn encode(output: &T) -> Result<Bytes, Self::Error>;
849}
850
851pub trait Decodes<T> {
853    type Error: Display;
855
856    fn decode(bytes: Bytes) -> Result<T, Self::Error>;
858}
859
860#[cfg(feature = "ssr")]
861#[doc(hidden)]
862pub use inventory;
863
864#[macro_export]
866macro_rules! initialize_server_fn_map {
867    ($req:ty, $res:ty) => {
868        std::sync::LazyLock::new(|| {
869            $crate::inventory::iter::<ServerFnTraitObj<$req, $res>>
870                .into_iter()
871                .map(|obj| {
872                    ((obj.path().to_string(), obj.method()), obj.clone())
873                })
874                .collect()
875        })
876    };
877}
878
879pub type MiddlewareSet<Req, Res> = Vec<Arc<dyn Layer<Req, Res>>>;
881
882pub struct ServerFnTraitObj<Req, Res> {
886    path: &'static str,
887    method: Method,
888    handler: fn(Req) -> Pin<Box<dyn Future<Output = Res> + Send>>,
889    middleware: fn() -> MiddlewareSet<Req, Res>,
890    ser: fn(ServerFnErrorErr) -> Bytes,
891}
892
893impl<Req, Res> ServerFnTraitObj<Req, Res> {
894    pub const fn new<
896        S: ServerFn<
897            Server: crate::Server<
898                S::Error,
899                S::InputStreamError,
900                S::OutputStreamError,
901                Request = Req,
902                Response = Res,
903            >,
904        >,
905    >(
906        handler: fn(Req) -> Pin<Box<dyn Future<Output = Res> + Send>>,
907    ) -> Self
908    where
909        Req: crate::Req<
910                S::Error,
911                S::InputStreamError,
912                S::OutputStreamError,
913                WebsocketResponse = Res,
914            > + Send
915            + 'static,
916        Res: crate::TryRes<S::Error> + Send + 'static,
917    {
918        Self {
919            path: S::PATH,
920            method: S::Protocol::METHOD,
921            handler,
922            middleware: S::middlewares,
923            ser: |e| S::Error::from_server_fn_error(e).ser(),
924        }
925    }
926
927    pub fn path(&self) -> &'static str {
929        self.path
930    }
931
932    pub fn method(&self) -> Method {
934        self.method.clone()
935    }
936
937    pub fn handler(&self, req: Req) -> impl Future<Output = Res> + Send {
939        (self.handler)(req)
940    }
941
942    pub fn middleware(&self) -> MiddlewareSet<Req, Res> {
944        (self.middleware)()
945    }
946
947    pub fn boxed(self) -> BoxedService<Req, Res>
949    where
950        Self: Service<Req, Res>,
951        Req: 'static,
952        Res: 'static,
953    {
954        BoxedService::new(self.ser, self)
955    }
956}
957
958impl<Req, Res> Service<Req, Res> for ServerFnTraitObj<Req, Res>
959where
960    Req: Send + 'static,
961    Res: 'static,
962{
963    fn run(
964        &mut self,
965        req: Req,
966        _ser: fn(ServerFnErrorErr) -> Bytes,
967    ) -> Pin<Box<dyn Future<Output = Res> + Send>> {
968        let handler = self.handler;
969        Box::pin(async move { handler(req).await })
970    }
971}
972
973impl<Req, Res> Clone for ServerFnTraitObj<Req, Res> {
974    fn clone(&self) -> Self {
975        Self {
976            path: self.path,
977            method: self.method.clone(),
978            handler: self.handler,
979            middleware: self.middleware,
980            ser: self.ser,
981        }
982    }
983}
984
985#[allow(unused)] type LazyServerFnMap<Req, Res> =
987    LazyLock<DashMap<(String, Method), ServerFnTraitObj<Req, Res>>>;
988
989#[cfg(feature = "ssr")]
990impl<Req: 'static, Res: 'static> inventory::Collect
991    for ServerFnTraitObj<Req, Res>
992{
993    #[inline]
994    fn registry() -> &'static inventory::Registry {
995        static REGISTRY: inventory::Registry = inventory::Registry::new();
996        ®ISTRY
997    }
998}
999
1000#[cfg(feature = "axum-no-default")]
1002pub mod axum {
1003    use crate::{
1004        error::FromServerFnError, middleware::BoxedService, LazyServerFnMap,
1005        Protocol, Server, ServerFn, ServerFnTraitObj,
1006    };
1007    use axum::body::Body;
1008    use http::{Method, Request, Response, StatusCode};
1009    use std::future::Future;
1010
1011    static REGISTERED_SERVER_FUNCTIONS: LazyServerFnMap<
1012        Request<Body>,
1013        Response<Body>,
1014    > = initialize_server_fn_map!(Request<Body>, Response<Body>);
1015
1016    pub struct AxumServerFnBackend;
1018
1019    impl<Error, InputStreamError, OutputStreamError>
1020        Server<Error, InputStreamError, OutputStreamError>
1021        for AxumServerFnBackend
1022    where
1023        Error: FromServerFnError + Send + Sync,
1024        InputStreamError: FromServerFnError + Send + Sync,
1025        OutputStreamError: FromServerFnError + Send + Sync,
1026    {
1027        type Request = Request<Body>;
1028        type Response = Response<Body>;
1029
1030        #[allow(unused_variables)]
1031        fn spawn(
1032            future: impl Future<Output = ()> + Send + 'static,
1033        ) -> Result<(), Error> {
1034            #[cfg(feature = "axum")]
1035            {
1036                tokio::spawn(future);
1037                Ok(())
1038            }
1039            #[cfg(not(feature = "axum"))]
1040            {
1041                Err(Error::from_server_fn_error(
1042                    crate::error::ServerFnErrorErr::Request(
1043                        "No async runtime available. You need to either \
1044                         enable the full axum feature to pull in tokio, or \
1045                         implement the `Server` trait for your async runtime \
1046                         manually."
1047                            .into(),
1048                    ),
1049                ))
1050            }
1051        }
1052    }
1053
1054    pub fn register_explicit<T>()
1058    where
1059        T: ServerFn<
1060                Server: crate::Server<
1061                    T::Error,
1062                    T::InputStreamError,
1063                    T::OutputStreamError,
1064                    Request = Request<Body>,
1065                    Response = Response<Body>,
1066                >,
1067            > + 'static,
1068    {
1069        REGISTERED_SERVER_FUNCTIONS.insert(
1070            (T::PATH.into(), T::Protocol::METHOD),
1071            ServerFnTraitObj::new::<T>(|req| Box::pin(T::run_on_server(req))),
1072        );
1073    }
1074
1075    pub fn server_fn_paths() -> impl Iterator<Item = (&'static str, Method)> {
1077        REGISTERED_SERVER_FUNCTIONS
1078            .iter()
1079            .map(|item| (item.path(), item.method()))
1080    }
1081
1082    pub async fn handle_server_fn(req: Request<Body>) -> Response<Body> {
1084        let path = req.uri().path();
1085
1086        if let Some(mut service) =
1087            get_server_fn_service(path, req.method().clone())
1088        {
1089            service.run(req).await
1090        } else {
1091            Response::builder()
1092                .status(StatusCode::BAD_REQUEST)
1093                .body(Body::from(format!(
1094                    "Could not find a server function at the route {path}. \
1095                     \n\nIt's likely that either\n 1. The API prefix you \
1096                     specify in the `#[server]` macro doesn't match the \
1097                     prefix at which your server function handler is mounted, \
1098                     or \n2. You are on a platform that doesn't support \
1099                     automatic server function registration and you need to \
1100                     call ServerFn::register_explicit() on the server \
1101                     function type, somewhere in your `main` function.",
1102                )))
1103                .unwrap()
1104        }
1105    }
1106
1107    pub fn get_server_fn_service(
1109        path: &str,
1110        method: Method,
1111    ) -> Option<BoxedService<Request<Body>, Response<Body>>> {
1112        let key = (path.into(), method);
1113        REGISTERED_SERVER_FUNCTIONS.get(&key).map(|server_fn| {
1114            let middleware = (server_fn.middleware)();
1115            let mut service = server_fn.clone().boxed();
1116            for middleware in middleware {
1117                service = middleware.layer(service);
1118            }
1119            service
1120        })
1121    }
1122}
1123
1124#[cfg(feature = "actix-no-default")]
1126pub mod actix {
1127    use crate::{
1128        error::FromServerFnError, middleware::BoxedService,
1129        request::actix::ActixRequest, response::actix::ActixResponse,
1130        server::Server, LazyServerFnMap, Protocol, ServerFn, ServerFnTraitObj,
1131    };
1132    use actix_web::{web::Payload, HttpRequest, HttpResponse};
1133    use http::Method;
1134    #[doc(hidden)]
1135    pub use send_wrapper::SendWrapper;
1136    use std::future::Future;
1137
1138    static REGISTERED_SERVER_FUNCTIONS: LazyServerFnMap<
1139        ActixRequest,
1140        ActixResponse,
1141    > = initialize_server_fn_map!(ActixRequest, ActixResponse);
1142
1143    pub struct ActixServerFnBackend;
1145
1146    impl<Error, InputStreamError, OutputStreamError>
1147        Server<Error, InputStreamError, OutputStreamError>
1148        for ActixServerFnBackend
1149    where
1150        Error: FromServerFnError + Send + Sync,
1151        InputStreamError: FromServerFnError + Send + Sync,
1152        OutputStreamError: FromServerFnError + Send + Sync,
1153    {
1154        type Request = ActixRequest;
1155        type Response = ActixResponse;
1156
1157        fn spawn(
1158            future: impl Future<Output = ()> + Send + 'static,
1159        ) -> Result<(), Error> {
1160            actix_web::rt::spawn(future);
1161            Ok(())
1162        }
1163    }
1164
1165    pub fn register_explicit<T>()
1169    where
1170        T: ServerFn<
1171                Server: crate::Server<
1172                    T::Error,
1173                    T::InputStreamError,
1174                    T::OutputStreamError,
1175                    Request = ActixRequest,
1176                    Response = ActixResponse,
1177                >,
1178            > + 'static,
1179    {
1180        REGISTERED_SERVER_FUNCTIONS.insert(
1181            (T::PATH.into(), T::Protocol::METHOD),
1182            ServerFnTraitObj::new::<T>(|req| Box::pin(T::run_on_server(req))),
1183        );
1184    }
1185
1186    pub fn server_fn_paths() -> impl Iterator<Item = (&'static str, Method)> {
1188        REGISTERED_SERVER_FUNCTIONS
1189            .iter()
1190            .map(|item| (item.path(), item.method()))
1191    }
1192
1193    pub async fn handle_server_fn(
1195        req: HttpRequest,
1196        payload: Payload,
1197    ) -> HttpResponse {
1198        let path = req.uri().path();
1199        let method = req.method();
1200        if let Some(mut service) = get_server_fn_service(path, method) {
1201            service
1202                .run(ActixRequest::from((req, payload)))
1203                .await
1204                .0
1205                .take()
1206        } else {
1207            HttpResponse::BadRequest().body(format!(
1208                "Could not find a server function at the route {path}. \
1209                 \n\nIt's likely that either\n 1. The API prefix you specify \
1210                 in the `#[server]` macro doesn't match the prefix at which \
1211                 your server function handler is mounted, or \n2. You are on \
1212                 a platform that doesn't support automatic server function \
1213                 registration and you need to call \
1214                 ServerFn::register_explicit() on the server function type, \
1215                 somewhere in your `main` function.",
1216            ))
1217        }
1218    }
1219
1220    pub fn get_server_fn_service(
1222        path: &str,
1223        method: &actix_web::http::Method,
1224    ) -> Option<BoxedService<ActixRequest, ActixResponse>> {
1225        use actix_web::http::Method as ActixMethod;
1226
1227        let method = match *method {
1228            ActixMethod::GET => Method::GET,
1229            ActixMethod::POST => Method::POST,
1230            ActixMethod::PUT => Method::PUT,
1231            ActixMethod::PATCH => Method::PATCH,
1232            ActixMethod::DELETE => Method::DELETE,
1233            ActixMethod::HEAD => Method::HEAD,
1234            ActixMethod::TRACE => Method::TRACE,
1235            ActixMethod::OPTIONS => Method::OPTIONS,
1236            ActixMethod::CONNECT => Method::CONNECT,
1237            _ => unreachable!(),
1238        };
1239        REGISTERED_SERVER_FUNCTIONS.get(&(path.into(), method)).map(
1240            |server_fn| {
1241                let middleware = (server_fn.middleware)();
1242                let mut service = server_fn.clone().boxed();
1243                for middleware in middleware {
1244                    service = middleware.layer(service);
1245                }
1246                service
1247            },
1248        )
1249    }
1250}
1251
1252pub mod mock {
1254    use std::future::Future;
1255
1256    pub struct BrowserMockServer;
1263
1264    impl<Error, InputStreamError, OutputStreamError>
1265        crate::server::Server<Error, InputStreamError, OutputStreamError>
1266        for BrowserMockServer
1267    where
1268        Error: Send + 'static,
1269        InputStreamError: Send + 'static,
1270        OutputStreamError: Send + 'static,
1271    {
1272        type Request = crate::request::BrowserMockReq;
1273        type Response = crate::response::BrowserMockRes;
1274
1275        fn spawn(
1276            _: impl Future<Output = ()> + Send + 'static,
1277        ) -> Result<(), Error> {
1278            unreachable!()
1279        }
1280    }
1281}
1282
1283#[cfg(test)]
1284mod tests {
1285
1286    use super::*;
1287    use crate::codec::JsonEncoding;
1288    use serde::{Deserialize, Serialize};
1289
1290    #[derive(Debug, Serialize, Deserialize)]
1291    enum TestError {
1292        ServerFnError(ServerFnErrorErr),
1293    }
1294
1295    impl FromServerFnError for TestError {
1296        type Encoder = JsonEncoding;
1297
1298        fn from_server_fn_error(value: ServerFnErrorErr) -> Self {
1299            Self::ServerFnError(value)
1300        }
1301    }
1302    #[test]
1303    fn test_result_serialization() {
1304        let ok_result: Result<Bytes, Bytes> =
1306            Ok(Bytes::from_static(b"success data"));
1307        let serialized = serialize_result(ok_result);
1308        let deserialized = deserialize_result::<TestError>(serialized);
1309        assert!(deserialized.is_ok());
1310        assert_eq!(deserialized.unwrap(), Bytes::from_static(b"success data"));
1311
1312        let err_result: Result<Bytes, Bytes> =
1314            Err(Bytes::from_static(b"error details"));
1315        let serialized = serialize_result(err_result);
1316        let deserialized = deserialize_result::<TestError>(serialized);
1317        assert!(deserialized.is_err());
1318        assert_eq!(
1319            deserialized.unwrap_err(),
1320            Bytes::from_static(b"error details")
1321        );
1322    }
1323}