server_fn/
lib.rs

1#![forbid(unsafe_code)]
2#![deny(missing_docs)]
3
4//! # Server Functions
5//!
6//! This package is based on a simple idea: sometimes it’s useful to write functions
7//! that will only run on the server, and call them from the client.
8//!
9//! If you’re creating anything beyond a toy app, you’ll need to do this all the time:
10//! reading from or writing to a database that only runs on the server, running expensive
11//! computations using libraries you don’t want to ship down to the client, accessing
12//! APIs that need to be called from the server rather than the client for CORS reasons
13//! or because you need a secret API key that’s stored on the server and definitely
14//! shouldn’t be shipped down to a user’s browser.
15//!
16//! Traditionally, this is done by separating your server and client code, and by setting
17//! up something like a REST API or GraphQL API to allow your client to fetch and mutate
18//! data on the server. This is fine, but it requires you to write and maintain your code
19//! in multiple separate places (client-side code for fetching, server-side functions to run),
20//! as well as creating a third thing to manage, which is the API contract between the two.
21//!
22//! This package provides two simple primitives that allow you instead to write co-located,
23//! isomorphic server functions. (*Co-located* means you can write them in your app code so
24//! that they are “located alongside” the client code that calls them, rather than separating
25//! the client and server sides. *Isomorphic* means you can call them from the client as if
26//! you were simply calling a function; the function call has the “same shape” on the client
27//! as it does on the server.)
28//!
29//! ### `#[server]`
30//!
31//! The [`#[server]`](../leptos/attr.server.html) macro allows you to annotate a function to
32//! indicate that it should only run on the server (i.e., when you have an `ssr` feature in your
33//! crate that is enabled).
34//!
35//! **Important**: Before calling a server function on a non-web platform, you must set the server URL by calling
36//! [`set_server_url`](crate::client::set_server_url).
37//!
38//! ```rust,ignore
39//! #[server]
40//! async fn read_posts(how_many: usize, query: String) -> Result<Vec<Posts>, ServerFnError> {
41//!   // do some server-only work here to access the database
42//!   let posts = ...;
43//!   Ok(posts)
44//! }
45//!
46//! // call the function
47//! # #[tokio::main]
48//! # async fn main() {
49//! async {
50//!   let posts = read_posts(3, "my search".to_string()).await;
51//!   log::debug!("posts = {posts:#?}");
52//! }
53//! # }
54//! ```
55//!
56//! If you call this function from the client, it will serialize the function arguments and `POST`
57//! them to the server as if they were the URL-encoded inputs in `<form method="post">`.
58//!
59//! Here’s what you need to remember:
60//! - **Server functions must be `async`.** Even if the work being done inside the function body
61//!   can run synchronously on the server, from the client’s perspective it involves an asynchronous
62//!   function call.
63//! - **Server functions must return `Result<T, ServerFnError>`.** Even if the work being done
64//!   inside the function body can’t fail, the processes of serialization/deserialization and the
65//!   network call are fallible. [`ServerFnError`] can receive generic errors.
66//! - **Server functions are part of the public API of your application.** A server function is an
67//!   ad hoc HTTP API endpoint, not a magic formula. Any server function can be accessed by any HTTP
68//!   client. You should take care to sanitize any data being returned from the function to ensure it
69//!   does not leak data that should exist only on the server.
70//! - **Server functions can’t be generic.** Because each server function creates a separate API endpoint,
71//!   it is difficult to monomorphize. As a result, server functions cannot be generic (for now?) If you need to use
72//!   a generic function, you can define a generic inner function called by multiple concrete server functions.
73//! - **Arguments and return types must be serializable.** We support a variety of different encodings,
74//!   but one way or another arguments need to be serialized to be sent to the server and deserialized
75//!   on the server, and the return type must be serialized on the server and deserialized on the client.
76//!   This means that the set of valid server function argument and return types is a subset of all
77//!   possible Rust argument and return types. (i.e., server functions are strictly more limited than
78//!   ordinary functions.)
79//!
80//! ## Server Function Encodings
81//!
82//! Server functions are designed to allow a flexible combination of input and output encodings, the set
83//! of which can be found in the [`codec`] module.
84//!
85//! Calling and handling server functions is done through the [`Protocol`] trait, which is implemented
86//! for the [`Http`] and [`Websocket`] protocols. Most server functions will use the [`Http`] protocol.
87//!
88//! When using the [`Http`] protocol, the serialization/deserialization process for server functions
89//! consists of a series of steps, each of which is represented by a different trait:
90//! 1. [`IntoReq`]: The client serializes the [`ServerFn`] argument type into an HTTP request.
91//! 2. The [`Client`] sends the request to the server.
92//! 3. [`FromReq`]: The server deserializes the HTTP request back into the [`ServerFn`] type.
93//! 4. The server calls calls [`ServerFn::run_body`] on the data.
94//! 5. [`IntoRes`]: The server serializes the [`ServerFn::Output`] type into an HTTP response.
95//! 6. The server integration applies any middleware from [`ServerFn::middlewares`] and responds to the request.
96//! 7. [`FromRes`]: The client deserializes the response back into the [`ServerFn::Output`] type.
97//!
98//! [server]: ../leptos/attr.server.html
99//! [`serde_qs`]: <https://docs.rs/serde_qs/latest/serde_qs/>
100//! [`cbor`]: <https://docs.rs/cbor/latest/cbor/>
101
102/// Implementations of the client side of the server function call.
103pub mod client;
104
105/// Implementations of the server side of the server function call.
106pub mod server;
107
108/// Encodings for arguments and results.
109pub mod codec;
110
111#[macro_use]
112/// Error types and utilities.
113pub mod error;
114/// Types to add server middleware to a server function.
115pub mod middleware;
116/// Utilities to allow client-side redirects.
117pub mod redirect;
118/// Types and traits for  for HTTP requests.
119pub mod request;
120/// Types and traits for HTTP responses.
121pub mod response;
122
123#[cfg(feature = "actix")]
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// re-exported to make it possible to implement a custom Client without adding a separate
137// dependency on `bytes`
138pub use bytes::Bytes;
139use bytes::{BufMut, BytesMut};
140use client::Client;
141use codec::{Encoding, FromReq, FromRes, IntoReq, IntoRes};
142#[doc(hidden)]
143pub use const_format;
144#[doc(hidden)]
145pub use const_str;
146use dashmap::DashMap;
147pub use error::ServerFnError;
148#[cfg(feature = "form-redirects")]
149use error::ServerFnUrlError;
150use error::{FromServerFnError, ServerFnErrorErr};
151use futures::{pin_mut, SinkExt, Stream, StreamExt};
152use http::Method;
153use middleware::{BoxedService, Layer, Service};
154use once_cell::sync::Lazy;
155use redirect::call_redirect_hook;
156use request::Req;
157use response::{ClientRes, Res, TryRes};
158#[cfg(feature = "rkyv")]
159pub use rkyv;
160#[doc(hidden)]
161pub use serde;
162#[doc(hidden)]
163#[cfg(feature = "serde-lite")]
164pub use serde_lite;
165use server::Server;
166use std::{
167    fmt::{Debug, Display},
168    future::Future,
169    marker::PhantomData,
170    ops::{Deref, DerefMut},
171    pin::Pin,
172    sync::Arc,
173};
174#[doc(hidden)]
175pub use xxhash_rust;
176
177type ServerFnServerRequest<Fn> = <<Fn as ServerFn>::Server as crate::Server<
178    <Fn as ServerFn>::Error,
179    <Fn as ServerFn>::InputStreamError,
180    <Fn as ServerFn>::OutputStreamError,
181>>::Request;
182type ServerFnServerResponse<Fn> = <<Fn as ServerFn>::Server as crate::Server<
183    <Fn as ServerFn>::Error,
184    <Fn as ServerFn>::InputStreamError,
185    <Fn as ServerFn>::OutputStreamError,
186>>::Response;
187
188/// Defines a function that runs only on the server, but can be called from the server or the client.
189///
190/// The type for which `ServerFn` is implemented is actually the type of the arguments to the function,
191/// while the function body itself is implemented in [`run_body`](ServerFn::run_body).
192///
193/// This means that `Self` here is usually a struct, in which each field is an argument to the function.
194/// In other words,
195/// ```rust,ignore
196/// #[server]
197/// pub async fn my_function(foo: String, bar: usize) -> Result<usize, ServerFnError> {
198///     Ok(foo.len() + bar)
199/// }
200/// ```
201/// should expand to
202/// ```rust,ignore
203/// #[derive(Serialize, Deserialize)]
204/// pub struct MyFunction {
205///     foo: String,
206///     bar: usize
207/// }
208///
209/// impl ServerFn for MyFunction {
210///     async fn run_body() -> Result<usize, ServerFnError> {
211///         Ok(foo.len() + bar)
212///     }
213///
214///     // etc.
215/// }
216/// ```
217pub trait ServerFn: Send + Sized {
218    /// A unique path for the server function’s API endpoint, relative to the host, including its prefix.
219    const PATH: &'static str;
220
221    /// The type of the HTTP client that will send the request from the client side.
222    ///
223    /// For example, this might be `gloo-net` in the browser, or `reqwest` for a desktop app.
224    type Client: Client<
225        Self::Error,
226        Self::InputStreamError,
227        Self::OutputStreamError,
228    >;
229
230    /// The type of the HTTP server that will send the response from the server side.
231    ///
232    /// For example, this might be `axum` or `actix-web`.
233    type Server: Server<
234        Self::Error,
235        Self::InputStreamError,
236        Self::OutputStreamError,
237    >;
238
239    /// The protocol the server function uses to communicate with the client.
240    type Protocol: Protocol<
241        Self,
242        Self::Output,
243        Self::Client,
244        Self::Server,
245        Self::Error,
246        Self::InputStreamError,
247        Self::OutputStreamError,
248    >;
249
250    /// The return type of the server function.
251    ///
252    /// This needs to be converted into `ServerResponse` on the server side, and converted
253    /// *from* `ClientResponse` when received by the client.
254    type Output: Send;
255
256    /// The type of error in the server function return.
257    /// Typically [`ServerFnError`], but allowed to be any type that implements [`FromServerFnError`].
258    type Error: FromServerFnError + Send + Sync;
259    /// The type of error in the server function for stream items sent from the client to the server.
260    /// Typically [`ServerFnError`], but allowed to be any type that implements [`FromServerFnError`].
261    type InputStreamError: FromServerFnError + Send + Sync;
262    /// The type of error in the server function for stream items sent from the server to the client.
263    /// Typically [`ServerFnError`], but allowed to be any type that implements [`FromServerFnError`].
264    type OutputStreamError: FromServerFnError + Send + Sync;
265
266    /// Returns [`Self::PATH`].
267    fn url() -> &'static str {
268        Self::PATH
269    }
270
271    /// Middleware that should be applied to this server function.
272    fn middlewares() -> Vec<
273        Arc<
274            dyn Layer<
275                ServerFnServerRequest<Self>,
276                ServerFnServerResponse<Self>,
277            >,
278        >,
279    > {
280        Vec::new()
281    }
282
283    /// The body of the server function. This will only run on the server.
284    fn run_body(
285        self,
286    ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send;
287
288    #[doc(hidden)]
289    fn run_on_server(
290        req: ServerFnServerRequest<Self>,
291    ) -> impl Future<Output = ServerFnServerResponse<Self>> + Send {
292        // Server functions can either be called by a real Client,
293        // or directly by an HTML <form>. If they're accessed by a <form>, default to
294        // redirecting back to the Referer.
295        #[cfg(feature = "form-redirects")]
296        let accepts_html = req
297            .accepts()
298            .map(|n| n.contains("text/html"))
299            .unwrap_or(false);
300        #[cfg(feature = "form-redirects")]
301        let mut referer = req.referer().as_deref().map(ToOwned::to_owned);
302
303        async move {
304            #[allow(unused_variables, unused_mut)]
305            // used in form redirects feature
306            let (mut res, err) =
307                Self::Protocol::run_server(req, Self::run_body)
308                    .await
309                    .map(|res| (res, None))
310                    .unwrap_or_else(|e| {
311                        (
312                            <<Self as ServerFn>::Server as crate::Server<
313                                Self::Error,
314                                Self::InputStreamError,
315                                Self::OutputStreamError,
316                            >>::Response::error_response(
317                                Self::PATH, e.ser()
318                            ),
319                            Some(e),
320                        )
321                    });
322
323            // if it accepts HTML, we'll redirect to the Referer
324            #[cfg(feature = "form-redirects")]
325            if accepts_html {
326                // if it had an error, encode that error in the URL
327                if let Some(err) = err {
328                    if let Ok(url) = ServerFnUrlError::new(Self::PATH, err)
329                        .to_url(referer.as_deref().unwrap_or("/"))
330                    {
331                        referer = Some(url.to_string());
332                    }
333                }
334                // otherwise, strip error info from referer URL, as that means it's from a previous
335                // call
336                else if let Some(referer) = referer.as_mut() {
337                    ServerFnUrlError::<Self::Error>::strip_error_info(referer)
338                }
339
340                // set the status code and Location header
341                res.redirect(referer.as_deref().unwrap_or("/"));
342            }
343
344            res
345        }
346    }
347
348    #[doc(hidden)]
349    fn run_on_client(
350        self,
351    ) -> impl Future<Output = Result<Self::Output, Self::Error>> + Send {
352        async move { Self::Protocol::run_client(Self::PATH, self).await }
353    }
354}
355
356/// The protocol that a server function uses to communicate with the client. This trait handles
357/// the server and client side of running a server function. It is implemented for the [`Http`] and
358/// [`Websocket`] protocols and can be used to implement custom protocols.
359pub trait Protocol<
360    Input,
361    Output,
362    Client,
363    Server,
364    Error,
365    InputStreamError = Error,
366    OutputStreamError = Error,
367> where
368    Server: crate::Server<Error, InputStreamError, OutputStreamError>,
369    Client: crate::Client<Error, InputStreamError, OutputStreamError>,
370{
371    /// The HTTP method used for requests.
372    const METHOD: Method;
373
374    /// Run the server function on the server. The implementation should handle deserializing the
375    /// input, running the server function, and serializing the output.
376    fn run_server<F, Fut>(
377        request: Server::Request,
378        server_fn: F,
379    ) -> impl Future<Output = Result<Server::Response, Error>> + Send
380    where
381        F: Fn(Input) -> Fut + Send,
382        Fut: Future<Output = Result<Output, Error>> + Send;
383
384    /// Run the server function on the client. The implementation should handle serializing the
385    /// input, sending the request, and deserializing the output.
386    fn run_client(
387        path: &str,
388        input: Input,
389    ) -> impl Future<Output = Result<Output, Error>> + Send;
390}
391
392/// The http protocol with specific input and output encodings for the request and response. This is
393/// the default protocol server functions use if no override is set in the server function macro
394///
395/// The http protocol accepts two generic argument that define how the input and output for a server
396/// function are turned into HTTP requests and responses. For example, [`Http<GetUrl, Json>`] will
397/// accept a Url encoded Get request and return a JSON post response.
398///
399/// # Example
400///
401/// ```rust, no_run
402/// # use server_fn_macro_default::server;
403/// use serde::{Serialize, Deserialize};
404/// use server_fn::{Http, ServerFnError, codec::{Json, GetUrl}};
405///
406/// #[derive(Debug, Clone, Serialize, Deserialize)]
407/// pub struct Message {
408///     user: String,
409///     message: String,
410/// }
411///
412/// // The http protocol can be used on any server function that accepts and returns arguments that implement
413/// // the [`IntoReq`] and [`FromRes`] traits.
414/// //
415/// // In this case, the input and output encodings are [`GetUrl`] and [`Json`], respectively which requires
416/// // the items to implement [`IntoReq<GetUrl, ...>`] and [`FromRes<Json, ...>`]. Both of those implementations
417/// // require the items to implement [`Serialize`] and [`Deserialize`].
418/// # #[cfg(feature = "browser")] {
419/// #[server(protocol = Http<GetUrl, Json>)]
420/// async fn echo_http(
421///     input: Message,
422/// ) -> Result<Message, ServerFnError> {
423///     Ok(input)
424/// }
425/// # }
426/// ```
427pub struct Http<InputProtocol, OutputProtocol>(
428    PhantomData<(InputProtocol, OutputProtocol)>,
429);
430
431impl<InputProtocol, OutputProtocol, Input, Output, Client, Server, E>
432    Protocol<Input, Output, Client, Server, E>
433    for Http<InputProtocol, OutputProtocol>
434where
435    Input: IntoReq<InputProtocol, Client::Request, E>
436        + FromReq<InputProtocol, Server::Request, E>
437        + Send,
438    Output: IntoRes<OutputProtocol, Server::Response, E>
439        + FromRes<OutputProtocol, Client::Response, E>
440        + Send,
441    E: FromServerFnError,
442    InputProtocol: Encoding,
443    OutputProtocol: Encoding,
444    Client: crate::Client<E>,
445    Server: crate::Server<E>,
446{
447    const METHOD: Method = InputProtocol::METHOD;
448
449    async fn run_server<F, Fut>(
450        request: Server::Request,
451        server_fn: F,
452    ) -> Result<Server::Response, E>
453    where
454        F: Fn(Input) -> Fut + Send,
455        Fut: Future<Output = Result<Output, E>> + Send,
456    {
457        let input = Input::from_req(request).await?;
458
459        let output = server_fn(input).await?;
460
461        let response = Output::into_res(output).await?;
462
463        Ok(response)
464    }
465
466    async fn run_client(path: &str, input: Input) -> Result<Output, E>
467    where
468        Client: crate::Client<E>,
469    {
470        // create and send request on client
471        let req = input.into_req(path, OutputProtocol::CONTENT_TYPE)?;
472        let res = Client::send(req).await?;
473
474        let status = res.status();
475        let location = res.location();
476        let has_redirect_header = res.has_redirect();
477
478        // if it returns an error status, deserialize the error using the error's decoder.
479        let res = if (400..=599).contains(&status) {
480            Err(E::de(res.try_into_bytes().await?))
481        } else {
482            // otherwise, deserialize the body as is
483            let output = Output::from_res(res).await?;
484            Ok(output)
485        }?;
486
487        // if redirected, call the redirect hook (if that's been set)
488        if (300..=399).contains(&status) || has_redirect_header {
489            call_redirect_hook(&location);
490        }
491        Ok(res)
492    }
493}
494
495/// The websocket protocol that encodes the input and output streams using a websocket connection.
496///
497/// The websocket protocol accepts two generic argument that define the input and output serialization
498/// formats. For example, [`Websocket<CborEncoding, JsonEncoding>`] would accept a stream of Cbor-encoded messages
499/// and return a stream of JSON-encoded messages.
500///
501/// # Example
502///
503/// ```rust, no_run
504/// # use server_fn_macro_default::server;
505/// # #[cfg(feature = "browser")] {
506/// use server_fn::{ServerFnError, BoxedStream, Websocket, codec::JsonEncoding};
507/// use serde::{Serialize, Deserialize};
508///
509/// #[derive(Clone, Serialize, Deserialize)]
510/// pub struct Message {
511///     user: String,
512///     message: String,
513/// }
514/// // The websocket protocol can be used on any server function that accepts and returns a [`BoxedStream`]
515/// // with items that can be encoded by the input and output encoding generics.
516/// //
517/// // In this case, the input and output encodings are [`Json`] and [`Json`], respectively which requires
518/// // the items to implement [`Serialize`] and [`Deserialize`].
519/// #[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
520/// async fn echo_websocket(
521///     input: BoxedStream<Message, ServerFnError>,
522/// ) -> Result<BoxedStream<Message, ServerFnError>, ServerFnError> {
523///     Ok(input.into())
524/// }
525/// # }
526/// ```
527pub struct Websocket<InputEncoding, OutputEncoding>(
528    PhantomData<(InputEncoding, OutputEncoding)>,
529);
530
531/// A boxed stream type that can be used with the websocket protocol.
532///
533/// You can easily convert any static type that implement [`futures::Stream`] into a [`BoxedStream`]
534/// with the [`From`] trait.
535///
536/// # Example
537///
538/// ```rust, no_run
539/// use futures::StreamExt;
540/// use server_fn::{BoxedStream, ServerFnError};
541///
542/// let stream: BoxedStream<_, ServerFnError> =
543///     futures::stream::iter(0..10).map(Result::Ok).into();
544/// ```
545pub struct BoxedStream<T, E> {
546    stream: Pin<Box<dyn Stream<Item = Result<T, E>> + Send>>,
547}
548
549impl<T, E> From<BoxedStream<T, E>>
550    for Pin<Box<dyn Stream<Item = Result<T, E>> + Send>>
551{
552    fn from(val: BoxedStream<T, E>) -> Self {
553        val.stream
554    }
555}
556
557impl<T, E> Deref for BoxedStream<T, E> {
558    type Target = Pin<Box<dyn Stream<Item = Result<T, E>> + Send>>;
559    fn deref(&self) -> &Self::Target {
560        &self.stream
561    }
562}
563
564impl<T, E> DerefMut for BoxedStream<T, E> {
565    fn deref_mut(&mut self) -> &mut Self::Target {
566        &mut self.stream
567    }
568}
569
570impl<T, E> Debug for BoxedStream<T, E> {
571    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
572        f.debug_struct("BoxedStream").finish()
573    }
574}
575
576impl<T, E, S> From<S> for BoxedStream<T, E>
577where
578    S: Stream<Item = Result<T, E>> + Send + 'static,
579{
580    fn from(stream: S) -> Self {
581        BoxedStream {
582            stream: Box::pin(stream),
583        }
584    }
585}
586
587impl<
588        Input,
589        InputItem,
590        OutputItem,
591        InputEncoding,
592        OutputEncoding,
593        Client,
594        Server,
595        Error,
596        InputStreamError,
597        OutputStreamError,
598    >
599    Protocol<
600        Input,
601        BoxedStream<OutputItem, OutputStreamError>,
602        Client,
603        Server,
604        Error,
605        InputStreamError,
606        OutputStreamError,
607    > for Websocket<InputEncoding, OutputEncoding>
608where
609    Input: Deref<Target = BoxedStream<InputItem, InputStreamError>>
610        + Into<BoxedStream<InputItem, InputStreamError>>
611        + From<BoxedStream<InputItem, InputStreamError>>,
612    InputEncoding: Encodes<InputItem> + Decodes<InputItem>,
613    OutputEncoding: Encodes<OutputItem> + Decodes<OutputItem>,
614    InputStreamError: FromServerFnError + Send,
615    OutputStreamError: FromServerFnError + Send,
616    Error: FromServerFnError + Send,
617    Server: crate::Server<Error, InputStreamError, OutputStreamError>,
618    Client: crate::Client<Error, InputStreamError, OutputStreamError>,
619    OutputItem: Send + 'static,
620    InputItem: Send + 'static,
621{
622    const METHOD: Method = Method::GET;
623
624    async fn run_server<F, Fut>(
625        request: Server::Request,
626        server_fn: F,
627    ) -> Result<Server::Response, Error>
628    where
629        F: Fn(Input) -> Fut + Send,
630        Fut: Future<
631                Output = Result<
632                    BoxedStream<OutputItem, OutputStreamError>,
633                    Error,
634                >,
635            > + Send,
636    {
637        let (request_bytes, response_stream, response) =
638            request.try_into_websocket().await?;
639        let input = request_bytes.map(|request_bytes| {
640            let request_bytes = request_bytes
641                .map(|bytes| deserialize_result::<InputStreamError>(bytes))
642                .unwrap_or_else(Err);
643            match request_bytes {
644                Ok(request_bytes) => InputEncoding::decode(request_bytes)
645                    .map_err(|e| {
646                        InputStreamError::from_server_fn_error(
647                            ServerFnErrorErr::Deserialization(e.to_string()),
648                        )
649                    }),
650                Err(err) => Err(InputStreamError::de(err)),
651            }
652        });
653        let boxed = Box::pin(input)
654            as Pin<
655                Box<
656                    dyn Stream<Item = Result<InputItem, InputStreamError>>
657                        + Send,
658                >,
659            >;
660        let input = BoxedStream { stream: boxed };
661
662        let output = server_fn(input.into()).await?;
663
664        let output = output.stream.map(|output| {
665            let result = match output {
666                Ok(output) => OutputEncoding::encode(&output).map_err(|e| {
667                    OutputStreamError::from_server_fn_error(
668                        ServerFnErrorErr::Serialization(e.to_string()),
669                    )
670                    .ser()
671                }),
672                Err(err) => Err(err.ser()),
673            };
674            serialize_result(result)
675        });
676
677        Server::spawn(async move {
678            pin_mut!(response_stream);
679            pin_mut!(output);
680            while let Some(output) = output.next().await {
681                if response_stream.send(output).await.is_err() {
682                    break;
683                }
684            }
685        })?;
686
687        Ok(response)
688    }
689
690    fn run_client(
691        path: &str,
692        input: Input,
693    ) -> impl Future<
694        Output = Result<BoxedStream<OutputItem, OutputStreamError>, Error>,
695    > + Send {
696        let input = input.into();
697
698        async move {
699            let (stream, sink) = Client::open_websocket(path).await?;
700
701            // Forward the input stream to the websocket
702            Client::spawn(async move {
703                pin_mut!(input);
704                pin_mut!(sink);
705                while let Some(input) = input.stream.next().await {
706                    let result = match input {
707                        Ok(input) => {
708                            InputEncoding::encode(&input).map_err(|e| {
709                                InputStreamError::from_server_fn_error(
710                                    ServerFnErrorErr::Serialization(
711                                        e.to_string(),
712                                    ),
713                                )
714                                .ser()
715                            })
716                        }
717                        Err(err) => Err(err.ser()),
718                    };
719                    let result = serialize_result(result);
720                    if sink.send(result).await.is_err() {
721                        break;
722                    }
723                }
724            });
725
726            // Return the output stream
727            let stream = stream.map(|request_bytes| {
728                let request_bytes = request_bytes
729                    .map(|bytes| deserialize_result::<OutputStreamError>(bytes))
730                    .unwrap_or_else(Err);
731                match request_bytes {
732                    Ok(request_bytes) => OutputEncoding::decode(request_bytes)
733                        .map_err(|e| {
734                            OutputStreamError::from_server_fn_error(
735                                ServerFnErrorErr::Deserialization(
736                                    e.to_string(),
737                                ),
738                            )
739                        }),
740                    Err(err) => Err(OutputStreamError::de(err)),
741                }
742            });
743            let boxed = Box::pin(stream)
744                as Pin<
745                    Box<
746                        dyn Stream<Item = Result<OutputItem, OutputStreamError>>
747                            + Send,
748                    >,
749                >;
750            let output = BoxedStream { stream: boxed };
751            Ok(output)
752        }
753    }
754}
755
756// Serializes a Result<Bytes, Bytes> into a single Bytes instance.
757// Format: [tag: u8][content: Bytes]
758// - Tag 0: Ok variant
759// - Tag 1: Err variant
760fn serialize_result(result: Result<Bytes, Bytes>) -> Bytes {
761    match result {
762        Ok(bytes) => {
763            let mut buf = BytesMut::with_capacity(1 + bytes.len());
764            buf.put_u8(0); // Tag for Ok variant
765            buf.extend_from_slice(&bytes);
766            buf.freeze()
767        }
768        Err(bytes) => {
769            let mut buf = BytesMut::with_capacity(1 + bytes.len());
770            buf.put_u8(1); // Tag for Err variant
771            buf.extend_from_slice(&bytes);
772            buf.freeze()
773        }
774    }
775}
776
777// Deserializes a Bytes instance back into a Result<Bytes, Bytes>.
778fn deserialize_result<E: FromServerFnError>(
779    bytes: Bytes,
780) -> Result<Bytes, Bytes> {
781    if bytes.is_empty() {
782        return Err(E::from_server_fn_error(
783            ServerFnErrorErr::Deserialization("Data is empty".into()),
784        )
785        .ser());
786    }
787
788    let tag = bytes[0];
789    let content = bytes.slice(1..);
790
791    match tag {
792        0 => Ok(content),
793        1 => Err(content),
794        _ => Err(E::from_server_fn_error(ServerFnErrorErr::Deserialization(
795            "Invalid data tag".into(),
796        ))
797        .ser()), // Invalid tag
798    }
799}
800
801/// Encode format type
802pub enum Format {
803    /// Binary representation
804    Binary,
805    /// utf-8 compatible text representation
806    Text,
807}
808/// A trait for types with an associated content type.
809pub trait ContentType {
810    /// The MIME type of the data.
811    const CONTENT_TYPE: &'static str;
812}
813
814/// Data format representation
815pub trait FormatType {
816    /// The representation type
817    const FORMAT_TYPE: Format;
818
819    /// Encodes data into a string.
820    fn into_encoded_string(bytes: Bytes) -> String {
821        match Self::FORMAT_TYPE {
822            Format::Binary => STANDARD_NO_PAD.encode(bytes),
823            Format::Text => String::from_utf8(bytes.into())
824                .expect("Valid text format type with utf-8 comptabile string"),
825        }
826    }
827
828    /// Decodes string to bytes
829    fn from_encoded_string(data: &str) -> Result<Bytes, DecodeError> {
830        match Self::FORMAT_TYPE {
831            Format::Binary => {
832                STANDARD_NO_PAD.decode(data).map(|data| data.into())
833            }
834            Format::Text => Ok(Bytes::copy_from_slice(data.as_bytes())),
835        }
836    }
837}
838
839/// A trait for types that can be encoded into a bytes for a request body.
840pub trait Encodes<T>: ContentType + FormatType {
841    /// The error type that can be returned if the encoding fails.
842    type Error: Display + Debug;
843
844    /// Encodes the given value into a bytes.
845    fn encode(output: &T) -> Result<Bytes, Self::Error>;
846}
847
848/// A trait for types that can be decoded from a bytes for a response body.
849pub trait Decodes<T> {
850    /// The error type that can be returned if the decoding fails.
851    type Error: Display;
852
853    /// Decodes the given bytes into a value.
854    fn decode(bytes: Bytes) -> Result<T, Self::Error>;
855}
856
857#[cfg(feature = "ssr")]
858#[doc(hidden)]
859pub use inventory;
860
861/// Uses the `inventory` crate to initialize a map between paths and server functions.
862#[macro_export]
863macro_rules! initialize_server_fn_map {
864    ($req:ty, $res:ty) => {
865        once_cell::sync::Lazy::new(|| {
866            $crate::inventory::iter::<ServerFnTraitObj<$req, $res>>
867                .into_iter()
868                .map(|obj| {
869                    ((obj.path().to_string(), obj.method()), obj.clone())
870                })
871                .collect()
872        })
873    };
874}
875
876/// A list of middlewares that can be applied to a server function.
877pub type MiddlewareSet<Req, Res> = Vec<Arc<dyn Layer<Req, Res>>>;
878
879/// A trait object that allows multiple server functions that take the same
880/// request type and return the same response type to be gathered into a single
881/// collection.
882pub struct ServerFnTraitObj<Req, Res> {
883    path: &'static str,
884    method: Method,
885    handler: fn(Req) -> Pin<Box<dyn Future<Output = Res> + Send>>,
886    middleware: fn() -> MiddlewareSet<Req, Res>,
887    ser: fn(ServerFnErrorErr) -> Bytes,
888}
889
890impl<Req, Res> ServerFnTraitObj<Req, Res> {
891    /// Converts the relevant parts of a server function into a trait object.
892    pub const fn new<
893        S: ServerFn<
894            Server: crate::Server<
895                S::Error,
896                S::InputStreamError,
897                S::OutputStreamError,
898                Request = Req,
899                Response = Res,
900            >,
901        >,
902    >(
903        handler: fn(Req) -> Pin<Box<dyn Future<Output = Res> + Send>>,
904    ) -> Self
905    where
906        Req: crate::Req<
907                S::Error,
908                S::InputStreamError,
909                S::OutputStreamError,
910                WebsocketResponse = Res,
911            > + Send
912            + 'static,
913        Res: crate::TryRes<S::Error> + Send + 'static,
914    {
915        Self {
916            path: S::PATH,
917            method: S::Protocol::METHOD,
918            handler,
919            middleware: S::middlewares,
920            ser: |e| S::Error::from_server_fn_error(e).ser(),
921        }
922    }
923
924    /// The path of the server function.
925    pub fn path(&self) -> &'static str {
926        self.path
927    }
928
929    /// The HTTP method the server function expects.
930    pub fn method(&self) -> Method {
931        self.method.clone()
932    }
933
934    /// The handler for this server function.
935    pub fn handler(&self, req: Req) -> impl Future<Output = Res> + Send {
936        (self.handler)(req)
937    }
938
939    /// The set of middleware that should be applied to this function.
940    pub fn middleware(&self) -> MiddlewareSet<Req, Res> {
941        (self.middleware)()
942    }
943
944    /// Converts the server function into a boxed service.
945    pub fn boxed(self) -> BoxedService<Req, Res>
946    where
947        Self: Service<Req, Res>,
948        Req: 'static,
949        Res: 'static,
950    {
951        BoxedService::new(self.ser, self)
952    }
953}
954
955impl<Req, Res> Service<Req, Res> for ServerFnTraitObj<Req, Res>
956where
957    Req: Send + 'static,
958    Res: 'static,
959{
960    fn run(
961        &mut self,
962        req: Req,
963        _ser: fn(ServerFnErrorErr) -> Bytes,
964    ) -> Pin<Box<dyn Future<Output = Res> + Send>> {
965        let handler = self.handler;
966        Box::pin(async move { handler(req).await })
967    }
968}
969
970impl<Req, Res> Clone for ServerFnTraitObj<Req, Res> {
971    fn clone(&self) -> Self {
972        Self {
973            path: self.path,
974            method: self.method.clone(),
975            handler: self.handler,
976            middleware: self.middleware,
977            ser: self.ser,
978        }
979    }
980}
981
982#[allow(unused)] // used by server integrations
983type LazyServerFnMap<Req, Res> =
984    Lazy<DashMap<(String, Method), ServerFnTraitObj<Req, Res>>>;
985
986#[cfg(feature = "ssr")]
987impl<Req: 'static, Res: 'static> inventory::Collect
988    for ServerFnTraitObj<Req, Res>
989{
990    #[inline]
991    fn registry() -> &'static inventory::Registry {
992        static REGISTRY: inventory::Registry = inventory::Registry::new();
993        &REGISTRY
994    }
995}
996
997/// Axum integration.
998#[cfg(feature = "axum-no-default")]
999pub mod axum {
1000    use crate::{
1001        error::FromServerFnError, middleware::BoxedService, LazyServerFnMap,
1002        Protocol, Server, ServerFn, ServerFnTraitObj,
1003    };
1004    use axum::body::Body;
1005    use http::{Method, Request, Response, StatusCode};
1006    use std::future::Future;
1007
1008    static REGISTERED_SERVER_FUNCTIONS: LazyServerFnMap<
1009        Request<Body>,
1010        Response<Body>,
1011    > = initialize_server_fn_map!(Request<Body>, Response<Body>);
1012
1013    /// The axum server function backend
1014    pub struct AxumServerFnBackend;
1015
1016    impl<Error, InputStreamError, OutputStreamError>
1017        Server<Error, InputStreamError, OutputStreamError>
1018        for AxumServerFnBackend
1019    where
1020        Error: FromServerFnError + Send + Sync,
1021        InputStreamError: FromServerFnError + Send + Sync,
1022        OutputStreamError: FromServerFnError + Send + Sync,
1023    {
1024        type Request = Request<Body>;
1025        type Response = Response<Body>;
1026
1027        #[allow(unused_variables)]
1028        fn spawn(
1029            future: impl Future<Output = ()> + Send + 'static,
1030        ) -> Result<(), Error> {
1031            #[cfg(feature = "axum")]
1032            {
1033                tokio::spawn(future);
1034                Ok(())
1035            }
1036            #[cfg(not(feature = "axum"))]
1037            {
1038                Err(Error::from_server_fn_error(
1039                    crate::error::ServerFnErrorErr::Request(
1040                        "No async runtime available. You need to either \
1041                         enable the full axum feature to pull in tokio, or \
1042                         implement the `Server` trait for your async runtime \
1043                         manually."
1044                            .into(),
1045                    ),
1046                ))
1047            }
1048        }
1049    }
1050
1051    /// Explicitly register a server function. This is only necessary if you are
1052    /// running the server in a WASM environment (or a rare environment that the
1053    /// `inventory` crate won't work in.).
1054    pub fn register_explicit<T>()
1055    where
1056        T: ServerFn<
1057                Server: crate::Server<
1058                    T::Error,
1059                    T::InputStreamError,
1060                    T::OutputStreamError,
1061                    Request = Request<Body>,
1062                    Response = Response<Body>,
1063                >,
1064            > + 'static,
1065    {
1066        REGISTERED_SERVER_FUNCTIONS.insert(
1067            (T::PATH.into(), T::Protocol::METHOD),
1068            ServerFnTraitObj::new::<T>(|req| Box::pin(T::run_on_server(req))),
1069        );
1070    }
1071
1072    /// The set of all registered server function paths.
1073    pub fn server_fn_paths() -> impl Iterator<Item = (&'static str, Method)> {
1074        REGISTERED_SERVER_FUNCTIONS
1075            .iter()
1076            .map(|item| (item.path(), item.method()))
1077    }
1078
1079    /// An Axum handler that responds to a server function request.
1080    pub async fn handle_server_fn(req: Request<Body>) -> Response<Body> {
1081        let path = req.uri().path();
1082
1083        if let Some(mut service) =
1084            get_server_fn_service(path, req.method().clone())
1085        {
1086            service.run(req).await
1087        } else {
1088            Response::builder()
1089                .status(StatusCode::BAD_REQUEST)
1090                .body(Body::from(format!(
1091                    "Could not find a server function at the route {path}. \
1092                     \n\nIt's likely that either\n 1. The API prefix you \
1093                     specify in the `#[server]` macro doesn't match the \
1094                     prefix at which your server function handler is mounted, \
1095                     or \n2. You are on a platform that doesn't support \
1096                     automatic server function registration and you need to \
1097                     call ServerFn::register_explicit() on the server \
1098                     function type, somewhere in your `main` function.",
1099                )))
1100                .unwrap()
1101        }
1102    }
1103
1104    /// Returns the server function at the given path as a service that can be modified.
1105    pub fn get_server_fn_service(
1106        path: &str,
1107        method: Method,
1108    ) -> Option<BoxedService<Request<Body>, Response<Body>>> {
1109        let key = (path.into(), method);
1110        REGISTERED_SERVER_FUNCTIONS.get(&key).map(|server_fn| {
1111            let middleware = (server_fn.middleware)();
1112            let mut service = server_fn.clone().boxed();
1113            for middleware in middleware {
1114                service = middleware.layer(service);
1115            }
1116            service
1117        })
1118    }
1119}
1120
1121/// Actix integration.
1122#[cfg(feature = "actix")]
1123pub mod actix {
1124    use crate::{
1125        error::FromServerFnError, middleware::BoxedService,
1126        request::actix::ActixRequest, response::actix::ActixResponse,
1127        server::Server, LazyServerFnMap, Protocol, ServerFn, ServerFnTraitObj,
1128    };
1129    use actix_web::{web::Payload, HttpRequest, HttpResponse};
1130    use http::Method;
1131    #[doc(hidden)]
1132    pub use send_wrapper::SendWrapper;
1133    use std::future::Future;
1134
1135    static REGISTERED_SERVER_FUNCTIONS: LazyServerFnMap<
1136        ActixRequest,
1137        ActixResponse,
1138    > = initialize_server_fn_map!(ActixRequest, ActixResponse);
1139
1140    /// The actix server function backend
1141    pub struct ActixServerFnBackend;
1142
1143    impl<Error, InputStreamError, OutputStreamError>
1144        Server<Error, InputStreamError, OutputStreamError>
1145        for ActixServerFnBackend
1146    where
1147        Error: FromServerFnError + Send + Sync,
1148        InputStreamError: FromServerFnError + Send + Sync,
1149        OutputStreamError: FromServerFnError + Send + Sync,
1150    {
1151        type Request = ActixRequest;
1152        type Response = ActixResponse;
1153
1154        fn spawn(
1155            future: impl Future<Output = ()> + Send + 'static,
1156        ) -> Result<(), Error> {
1157            actix_web::rt::spawn(future);
1158            Ok(())
1159        }
1160    }
1161
1162    /// Explicitly register a server function. This is only necessary if you are
1163    /// running the server in a WASM environment (or a rare environment that the
1164    /// `inventory` crate won't work in.).
1165    pub fn register_explicit<T>()
1166    where
1167        T: ServerFn<
1168                Server: crate::Server<
1169                    T::Error,
1170                    T::InputStreamError,
1171                    T::OutputStreamError,
1172                    Request = ActixRequest,
1173                    Response = ActixResponse,
1174                >,
1175            > + 'static,
1176    {
1177        REGISTERED_SERVER_FUNCTIONS.insert(
1178            (T::PATH.into(), T::Protocol::METHOD),
1179            ServerFnTraitObj::new::<T>(|req| Box::pin(T::run_on_server(req))),
1180        );
1181    }
1182
1183    /// The set of all registered server function paths.
1184    pub fn server_fn_paths() -> impl Iterator<Item = (&'static str, Method)> {
1185        REGISTERED_SERVER_FUNCTIONS
1186            .iter()
1187            .map(|item| (item.path(), item.method()))
1188    }
1189
1190    /// An Actix handler that responds to a server function request.
1191    pub async fn handle_server_fn(
1192        req: HttpRequest,
1193        payload: Payload,
1194    ) -> HttpResponse {
1195        let path = req.uri().path();
1196        let method = req.method();
1197        if let Some(mut service) = get_server_fn_service(path, method) {
1198            service
1199                .run(ActixRequest::from((req, payload)))
1200                .await
1201                .0
1202                .take()
1203        } else {
1204            HttpResponse::BadRequest().body(format!(
1205                "Could not find a server function at the route {path}. \
1206                 \n\nIt's likely that either\n 1. The API prefix you specify \
1207                 in the `#[server]` macro doesn't match the prefix at which \
1208                 your server function handler is mounted, or \n2. You are on \
1209                 a platform that doesn't support automatic server function \
1210                 registration and you need to call \
1211                 ServerFn::register_explicit() on the server function type, \
1212                 somewhere in your `main` function.",
1213            ))
1214        }
1215    }
1216
1217    /// Returns the server function at the given path as a service that can be modified.
1218    pub fn get_server_fn_service(
1219        path: &str,
1220        method: &actix_web::http::Method,
1221    ) -> Option<BoxedService<ActixRequest, ActixResponse>> {
1222        use actix_web::http::Method as ActixMethod;
1223
1224        let method = match *method {
1225            ActixMethod::GET => Method::GET,
1226            ActixMethod::POST => Method::POST,
1227            ActixMethod::PUT => Method::PUT,
1228            ActixMethod::PATCH => Method::PATCH,
1229            ActixMethod::DELETE => Method::DELETE,
1230            ActixMethod::HEAD => Method::HEAD,
1231            ActixMethod::TRACE => Method::TRACE,
1232            ActixMethod::OPTIONS => Method::OPTIONS,
1233            ActixMethod::CONNECT => Method::CONNECT,
1234            _ => unreachable!(),
1235        };
1236        REGISTERED_SERVER_FUNCTIONS.get(&(path.into(), method)).map(
1237            |server_fn| {
1238                let middleware = (server_fn.middleware)();
1239                let mut service = server_fn.clone().boxed();
1240                for middleware in middleware {
1241                    service = middleware.layer(service);
1242                }
1243                service
1244            },
1245        )
1246    }
1247}
1248
1249/// Mocks for the server function backend types when compiling for the client.
1250pub mod mock {
1251    use std::future::Future;
1252
1253    /// A mocked server type that can be used in place of the actual server,
1254    /// when compiling for the browser.
1255    ///
1256    /// ## Panics
1257    /// This always panics if its methods are called. It is used solely to stub out the
1258    /// server type when compiling for the client.
1259    pub struct BrowserMockServer;
1260
1261    impl<Error, InputStreamError, OutputStreamError>
1262        crate::server::Server<Error, InputStreamError, OutputStreamError>
1263        for BrowserMockServer
1264    where
1265        Error: Send + 'static,
1266        InputStreamError: Send + 'static,
1267        OutputStreamError: Send + 'static,
1268    {
1269        type Request = crate::request::BrowserMockReq;
1270        type Response = crate::response::BrowserMockRes;
1271
1272        fn spawn(
1273            _: impl Future<Output = ()> + Send + 'static,
1274        ) -> Result<(), Error> {
1275            unreachable!()
1276        }
1277    }
1278}
1279
1280#[cfg(test)]
1281mod tests {
1282
1283    use super::*;
1284    use crate::codec::JsonEncoding;
1285    use serde::{Deserialize, Serialize};
1286
1287    #[derive(Debug, Serialize, Deserialize)]
1288    enum TestError {
1289        ServerFnError(ServerFnErrorErr),
1290    }
1291
1292    impl FromServerFnError for TestError {
1293        type Encoder = JsonEncoding;
1294
1295        fn from_server_fn_error(value: ServerFnErrorErr) -> Self {
1296            Self::ServerFnError(value)
1297        }
1298    }
1299    #[test]
1300    fn test_result_serialization() {
1301        // Test Ok variant
1302        let ok_result: Result<Bytes, Bytes> =
1303            Ok(Bytes::from_static(b"success data"));
1304        let serialized = serialize_result(ok_result);
1305        let deserialized = deserialize_result::<TestError>(serialized);
1306        assert!(deserialized.is_ok());
1307        assert_eq!(deserialized.unwrap(), Bytes::from_static(b"success data"));
1308
1309        // Test Err variant
1310        let err_result: Result<Bytes, Bytes> =
1311            Err(Bytes::from_static(b"error details"));
1312        let serialized = serialize_result(err_result);
1313        let deserialized = deserialize_result::<TestError>(serialized);
1314        assert!(deserialized.is_err());
1315        assert_eq!(
1316            deserialized.unwrap_err(),
1317            Bytes::from_static(b"error details")
1318        );
1319    }
1320}