diff --git a/examples/server_fns_axum/src/app.rs b/examples/server_fns_axum/src/app.rs
index a6ec1fe8a4..07eb960925 100644
--- a/examples/server_fns_axum/src/app.rs
+++ b/examples/server_fns_axum/src/app.rs
@@ -5,13 +5,15 @@ use leptos_meta::{provide_meta_context, Link, Meta, Stylesheet};
use leptos_router::{ActionForm, Route, Router, Routes};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use server_fn::{
+ client::{browser::BrowserClient, Client},
codec::{
Encoding, FromReq, FromRes, GetUrl, IntoReq, IntoRes, MultipartData,
MultipartFormData, Rkyv, SerdeLite, StreamingText, TextStream,
},
- request::{ClientReq, Req},
- response::{ClientRes, Res},
+ request::{browser::BrowserRequest, ClientReq, Req},
+ response::{browser::BrowserResponse, ClientRes, Res},
};
+use std::future::Future;
#[cfg(feature = "ssr")]
use std::sync::{
atomic::{AtomicU8, Ordering},
@@ -58,6 +60,7 @@ pub fn HomePage() -> impl IntoView {
+
}
}
@@ -795,3 +798,55 @@ pub fn CustomEncoding() -> impl IntoView {
{result}
}
}
+
+/// Middleware lets you modify the request/response on the server.
+///
+/// On the client, you might also want to modify the request. For example, you may need to add a
+/// custom header for authentication on every request. You can do this by creating a "custom
+/// client."
+#[component]
+pub fn CustomClientExample() -> impl IntoView {
+ // Define a type for our client.
+ pub struct CustomClient;
+
+ // Implement the `Client` trait for it.
+ impl Client for CustomClient {
+ // BrowserRequest and BrowserResponse are the defaults used by other server functions.
+ // They are wrappers for the underlying Web Fetch API types.
+ type Request = BrowserRequest;
+ type Response = BrowserResponse;
+
+ // Our custom `send()` implementation does all the work.
+ fn send(
+ req: Self::Request,
+ ) -> impl Future>>
+ + Send {
+ // BrowserRequest derefs to the underlying Request type from gloo-net,
+ // so we can get access to the headers here
+ let headers = req.headers();
+ // modify the headers by appending one
+ headers.append("X-Custom-Header", "foobar");
+ // delegate back out to BrowserClient to send the modified request
+ BrowserClient::send(req)
+ }
+ }
+
+ // Specify our custom client with `client = `
+ #[server(client = CustomClient)]
+ pub async fn fn_with_custom_client() -> Result<(), ServerFnError> {
+ use http::header::HeaderMap;
+ use leptos_axum::extract;
+
+ let headers: HeaderMap = extract().await?;
+ let custom_header = headers.get("X-Custom-Header");
+ println!("X-Custom-Header = {custom_header:?}");
+ Ok(())
+ }
+
+ view! {
+ Custom clients
+ You can define a custom server function client to do something like adding a header to every request.
+ Check the network request in your browser devtools to see how this client adds a custom header.
+ Click me
+ }
+}
diff --git a/server_fn/src/request/browser.rs b/server_fn/src/request/browser.rs
index 820ea77ffb..41978cc8dc 100644
--- a/server_fn/src/request/browser.rs
+++ b/server_fn/src/request/browser.rs
@@ -5,6 +5,7 @@ use futures::{Stream, StreamExt};
pub use gloo_net::http::Request;
use js_sys::{Reflect, Uint8Array};
use send_wrapper::SendWrapper;
+use std::ops::{Deref, DerefMut};
use wasm_bindgen::JsValue;
use wasm_streams::ReadableStream;
use web_sys::{FormData, Headers, RequestInit, UrlSearchParams};
@@ -19,6 +20,32 @@ impl From for BrowserRequest {
}
}
+impl From for Request {
+ fn from(value: BrowserRequest) -> Self {
+ value.0.take()
+ }
+}
+
+impl From for web_sys::Request {
+ fn from(value: BrowserRequest) -> Self {
+ value.0.take().into()
+ }
+}
+
+impl Deref for BrowserRequest {
+ type Target = Request;
+
+ fn deref(&self) -> &Self::Target {
+ self.0.deref()
+ }
+}
+
+impl DerefMut for BrowserRequest {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.0.deref_mut()
+ }
+}
+
/// The `FormData` type available in the browser.
#[derive(Debug)]
pub struct BrowserFormData(pub(crate) SendWrapper);