fastly 0.12.0

Fastly Compute API
Documentation
//! Compute ACLs.
//!
//! # Management
//!
//! Management of ACLs is done via api.fastly.com.
//! See [ACLs in Compute](https://www.fastly.com/documentation/reference/api/acls/acls/).
//!
//! One or more ACLs can be
//! [linked](https://www.fastly.com/documentation/reference/api/services/resource/#create-resource) to a
//! Compute service. Once linked, an ACL can be accessed from within a Compute application via its
//! linked name.
//!
//! # Usage
//!
//! The following example opens an ACL by its linked name and then performs a lookup
//! within the ACL of the client's IP. Different responses are returned depending on
//! the result of the lookup (allow or block):
//!
//! ```no_run
//! use fastly::{Error, Request, Response};
//!
//! #[fastly::main]
//! fn main(req: Request) -> Result<Response, Error> {
//!     let acl = fastly::Acl::open("my_acl").expect("can open acl");
//!
//!     let ip = req.get_client_ip_addr().expect("request has an ip");
//!
//!     let lookup = acl.try_lookup(ip)?;
//!     match lookup {
//!         Some(lookup_match) if lookup_match.is_allow() => {
//!             // IP is allowed.
//!             Ok(Response::from_body("allowed!"))
//!         }
//!         Some(_) => {
//!             // IP is not allowed.
//!             Ok(Response::from_status(403).with_body("blocked!"))
//!         }
//!         None => {
//!             // No prefixes matched the IP.
//!             Ok(Response::from_body("no match"))
//!         }
//!     }
//! }
//! ```

use std::net::IpAddr;

mod handle;
mod response;

pub use handle::{LookupError, OpenError};
pub use response::{LookupMatch, MatchAction};

/// A Compute ACL.
pub struct Acl {
    handle: handle::AclHandle,
}

impl Acl {
    /// Open an ACL linked to the current service with the given link name.
    pub fn open(name: &str) -> Result<Self, OpenError> {
        handle::AclHandle::open(name).map(|handle| Self { handle })
    }

    /// Perform a lookup of the given IP address in the ACL.
    /// If no matches are found, then `Ok(None)` is returned.
    pub fn try_lookup(&self, ip: IpAddr) -> Result<Option<LookupMatch>, LookupError> {
        match self.handle.lookup(ip)? {
            Some(body_handle) => LookupMatch::from_body_handle(body_handle)
                .map(|lookup_match| Ok(Some(lookup_match)))
                .map_err(|_| LookupError::InvalidResponseBody)?,

            // No prefix match found.
            None => Ok(None),
        }
    }
}