Skip to content

Commit d0b5fb1

Browse files
committed
update migration guide on middleware
1 parent 12fb341 commit d0b5fb1

File tree

1 file changed

+89
-3
lines changed

1 file changed

+89
-3
lines changed

actix-web/MIGRATION-4.0.md

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,97 @@ The following is a migration for an error handler that creates a new response in
239239

240240
## Middleware Trait APIs
241241

242-
This section builds upon guidance from the [response body types](#response-body-types) section.
242+
The underlying traits that are used for creating middleware, `Service`, `ServiceFactory`, and `Transform`, have changed in design.
243243

244-
TODO
244+
- The associated `Request` type has moved to the type parameter position in order to allow multiple request implementations in other areas of the service stack.
245+
- The `self` arguments in `Service` have changed from exclusive (mutable) borrows to shared (immutable) borrows. Since most service layers, such as middleware, do not host mutable state, it reduces the runtime overhead in places where a `RefCell` used to be required for wrapping an inner service.
246+
- We've also introduced some macros that reduce boilerplate when implementing `poll_ready`.
247+
- Further to the guidance on [response body types](#response-body-types), any use of the old methods on `ServiceResponse` designed to match up body types (e.g., the old `into_body` method), should be replaced with an explicit response body type utilizing `EitherBody<B>`.
245248

246-
TODO: Also write the Middleware author's guide.
249+
A typical migration would look like this:
250+
251+
```diff
252+
use std::{
253+
- cell::RefCell,
254+
future::Future,
255+
pin::Pin,
256+
rc::Rc,
257+
- task::{Context, Poll},
258+
};
259+
260+
use actix_web::{
261+
dev::{Service, ServiceRequest, ServiceResponse, Transform},
262+
Error,
263+
};
264+
use futures_util::future::{ok, LocalBoxFuture, Ready};
265+
266+
pub struct SayHi;
267+
268+
- impl<S, B> Transform<S> for SayHi
269+
+ impl<S, B> Transform<S, ServiceRequest> for SayHi
270+
where
271+
- S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
272+
+ S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
273+
S::Future: 'static,
274+
B: 'static,
275+
{
276+
- type Request = ServiceRequest;
277+
type Response = ServiceResponse<B>;
278+
type Error = Error;
279+
type InitError = ();
280+
type Transform = SayHiMiddleware<S>;
281+
type Future = Ready<Result<Self::Transform, Self::InitError>>;
282+
283+
fn new_transform(&self, service: S) -> Self::Future {
284+
ok(SayHiMiddleware {
285+
- service: Rc::new(RefCell::new(service)),
286+
+ service: Rc::new(service),
287+
})
288+
}
289+
}
290+
291+
pub struct SayHiMiddleware<S> {
292+
- service: Rc<RefCell<S>>,
293+
+ service: Rc<S>,
294+
}
295+
296+
- impl<S, B> Service for SayHiMiddleware<S>
297+
+ impl<S, B> Service<ServiceRequest> for SayHiMiddleware<S>
298+
where
299+
- S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
300+
+ S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
301+
S::Future: 'static,
302+
B: 'static,
303+
{
304+
- type Request = ServiceRequest;
305+
type Response = ServiceResponse<B>;
306+
type Error = Error;
307+
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
308+
309+
- fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
310+
- self.service.poll_ready(cx)
311+
- }
312+
+ actix_web::dev::forward_ready!(service);
313+
314+
- fn call(&mut self, req: ServiceRequest) -> Self::Future {
315+
+ fn call(&self, req: ServiceRequest) -> Self::Future {
316+
println!("Hi from start. You requested: {}", req.path());
317+
318+
let fut = self.service.call(req);
319+
320+
Box::pin(async move {
321+
let res = fut.await?;
322+
323+
println!("Hi from response");
324+
Ok(res)
325+
})
326+
}
327+
}
328+
```
329+
330+
This new design is forward-looking and should ease transition to traits that support the upcoming Generic Associated Type (GAT) feature in Rust while also trimming down the boilerplate required to implement middleware.
331+
332+
We understand that creating middleware is still a pain point for Actix Web and we hope to provide [an even more ergonomic solution](https://docs.rs/actix-web-lab/0.11.0/actix_web_lab/middleware/fn.from_fn.html) in a v4.x release.
247333

248334
## `Responder` Trait
249335

0 commit comments

Comments
 (0)