tower_sec_fetch/
authorizer.rs

1use std::{ops::Deref, sync::Arc};
2
3/// Custom request authorization logic
4pub trait SecFetchAuthorizer {
5    /// Authorizes the current request
6    fn authorize<B>(&self, request: &http::Request<B>) -> AuthorizationDecision;
7}
8
9#[doc(hidden)]
10pub struct NoopAuthorizer;
11
12impl SecFetchAuthorizer for NoopAuthorizer {
13    fn authorize<B>(&self, _: &http::Request<B>) -> AuthorizationDecision {
14        AuthorizationDecision::Continue
15    }
16}
17
18/// The decision made by a [SecFetchAuthorizer]
19pub enum AuthorizationDecision {
20    /// The request can be passed to the server
21    /// Short-circuits the evaluation policy
22    Allowed,
23    /// The request is denied
24    /// Short-circuits the evaluation policy
25    Denied,
26    /// The request is neither denied nor allowed, deferring
27    /// to the evaluation policy
28    Continue,
29}
30
31impl<T, A> SecFetchAuthorizer for T
32where
33    T: Deref<Target = A>,
34    A: SecFetchAuthorizer,
35{
36    fn authorize<B>(&self, request: &http::Request<B>) -> AuthorizationDecision {
37        self.deref().authorize(request)
38    }
39}
40
41/// A [SecFetchAuthorizer] that allows requests based on their path
42pub struct PathAuthorizer(Arc<[&'static str]>);
43
44impl PathAuthorizer {
45    pub fn new(allowed_paths: impl Into<Arc<[&'static str]>>) -> Self {
46        Self(allowed_paths.into())
47    }
48}
49
50impl SecFetchAuthorizer for PathAuthorizer {
51    fn authorize<B>(&self, request: &http::Request<B>) -> AuthorizationDecision {
52        if self.0.contains(&request.uri().path()) {
53            return AuthorizationDecision::Allowed;
54        }
55
56        AuthorizationDecision::Continue
57    }
58}