example of middleware that can run before and/or after server fn

This commit is contained in:
Greg Johnston 2024-01-17 10:29:45 -05:00
parent 22b4537f27
commit 5065bed594
3 changed files with 38 additions and 4 deletions

View file

@ -30,6 +30,7 @@ toml = "0.8.8"
web-sys = { version = "0.3.67", features = ["FileList", "File"] }
strum = { version = "0.25.0", features = ["strum_macros", "derive"] }
notify = { version = "6.1.1", optional = true }
pin-project-lite = "0.2.13"
[features]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]

View file

@ -242,6 +242,7 @@ pub fn WithActionForm() -> impl IntoView {
// In this case, any `tower::Layer` that takes services of `Request<Body>` will work
#[middleware(crate::middleware::LoggingLayer)]
pub async fn length_of_input(input: String) -> Result<usize, ServerFnError> {
println!("2. Running server function.");
// insert a simulated wait
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
Ok(input.len())

View file

@ -1,6 +1,11 @@
use axum::body::Body;
use http::Request;
use std::task::{Context, Poll};
use pin_project_lite::pin_project;
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use tower::{Layer, Service};
pub struct LoggingLayer;
@ -23,7 +28,7 @@ where
{
type Response = T::Response;
type Error = T::Error;
type Future = T::Future;
type Future = LoggingServiceFuture<T::Future>;
fn poll_ready(
&mut self,
@ -33,8 +38,35 @@ where
}
fn call(&mut self, req: Request<Body>) -> Self::Future {
println!("Running my middleware!");
println!("1. Running my middleware!");
self.inner.call(req)
LoggingServiceFuture {
inner: self.inner.call(req),
}
}
}
pin_project! {
pub struct LoggingServiceFuture<T> {
#[pin]
inner: T,
}
}
impl<T> Future for LoggingServiceFuture<T>
where
T: Future,
{
type Output = T::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
match this.inner.poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(output) => {
println!("3. Running my middleware!");
Poll::Ready(output)
}
}
}
}