3

My API routes are collected into a scope like so:

.scope("/api", |s| s
        .nested("/doorlock", routes::doorlock)
        .resource("/config{path:.*}", |r| {
            r.get().with(routes::config::read);
            r.put().with(routes::config::write);
            r.delete().with(routes::config::delete);
        })
)

I am thinking about adding a route-level protection, something that would either pass-through or return a 401 Unauthorizated response like so:

.scope("/api", |s| s
        .filter(is_authenticated_and_authorized)
        .nested("/doorlock", routes::doorlock)
        .resource("/config{path:.*}", |r| {
            r.get().with(routes::config::read);
            r.put().with(routes::config::write);
            r.delete().with(routes::config::delete);
        })
)

Unfortunately, this will forward requests to the default handler rather than returning an error response in case it does not match.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Ákos Vandra-Meyer
  • 1,890
  • 1
  • 23
  • 40

1 Answers1

2

What you are looking for is middleware.

You can then add your middleware to the scope:

// Create middleware
struct AuthMiddleware;

impl Middleware<AppState> for AuthMiddleware {
    fn start(&self, req: &mut HttpRequest<AppState>) -> Result<Started> {
        unimplemented!() // implement your auth logic here
    }
}

// later:

App::with_state(my_state)
    .scope("/api", |s| s
        .middleware(AuthMiddleware) // add your middleware to the scope
        .nested("/doorlock", routes::doorlock)
        .resource("/config{path:.*}", |r| {
            r.get().with(routes::config::read);
            r.put().with(routes::config::write);
            r.delete().with(routes::config::delete);
        })
);
belst
  • 2,285
  • 2
  • 20
  • 22