Skip to content
This repository has been archived by the owner on Feb 27, 2024. It is now read-only.

Wrap doesn't work within scope #24

Open
Mondei1 opened this issue Aug 29, 2022 · 2 comments
Open

Wrap doesn't work within scope #24

Mondei1 opened this issue Aug 29, 2022 · 2 comments

Comments

@Mondei1
Copy link

Mondei1 commented Aug 29, 2022

Hey @TerminalWitchcraft,

my use-case currently is that I only want to apply a rate limiter to my /auth path. In issue #10 you wrote the following:

Hey, yes you can using scopes. Each scope can register independent middlewares and it's also a nice utility to group related resources/endpoints! More information here: https://docs.rs/actix-web/3.3.2/actix_web/struct.Scope.html

I haven't personally tried it, but it should work if I understand the documentation correctly. Let me know if you run into any trouble using this.

Scopes would actually work perfectly for me. I just never worked with them before.

Well, I tried them and my code looks like this:

let cors = Cors::default();
let store = MemoryStore::new();

App::new()
    .wrap(Compress::default())
    .service(
      web::scope("/auth")
        .wrap(cors)    // This .wrap actually works with actix-cors
        .wrap(
          RateLimiter::new(
              MemoryStoreActor::from(store.clone()).start()
          )
          .with_interval(Duration::from_secs(60 * 10))
          .with_max_requests(20)
        )
        .service(web::resource("/").to(auth::get_auth))
    )
    /* Some more routes down here */
)

As it seems actix-ratelimit doesn't work properly as scoped middleware because the Rust compiler complains:

error[E0277]: the trait bound `RateLimiter<MemoryStoreActor>: Transform<actix_web::scope::ScopeService, ServiceRequest>` is not satisfied
   --> src/main.rs:69:25
    |
68  |                       .wrap(
    |                        ---- required by a bound introduced by this call
69  | /                         RateLimiter::new(
70  | |                             MemoryStoreActor::from(store.clone()).start()
71  | |                         )
72  | |                         .with_interval(Duration::from_secs(60 * 10))
73  | |                         .with_max_requests(20)
    | |______________________________________________^ the trait `Transform<actix_web::scope::ScopeService, ServiceRequest>` is not implemented for `RateLimiter<MemoryStoreActor>`
    |

The problem may lay in this implementation of RateLimiter<T>: https://github.com/TerminalWitchcraft/actix-ratelimit/blob/master/src/middleware.rs#L100

Their implementation (from actix-cors) looks like this:

impl<S, B> Transform<S, ServiceRequest> for Cors
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,

    B: MessageBody + 'static,
{
    type Response = ServiceResponse<EitherBody<B>>;
    type Error = Error;
    type InitError = ();
    type Transform = CorsMiddleware<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        // ...
    }
}

Source: https://github.com/actix/actix-extras/blob/master/actix-cors/src/builder.rs#L486

I'm not a Rust expert, I've just started using it seriously for ~3 months, but I'd bet that the S generic is incorrectly defined. Do you know how to fix this?

Thanks in advance,
Nicolas

@TommyLike
Copy link

Having this issue now @Mondei1

@tkr-sh
Copy link

tkr-sh commented Jul 21, 2023

Same

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants