Crate flytrap

source ·
Expand description

Flytrap is a crate for reading the Fly.io runtime environment.

A demo app is available at flytrap.fly.dev which shows this crate’s capabilities.

§Usage

§Placement

The Placement type gives access to Fly.io runtime environment variables like $FLY_PUBLIC_IP and $FLY_REGION.

use flytrap::{Placement, Machine};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let runtime = Placement::current()?;

    println!("Fly.io app: {}", runtime.app);
    println!("    region: {}", runtime.location);

    if let Some(Machine{ id, memory: Some(memory), image: Some(image), .. }) = runtime.machine {
        println!("   machine: {id} ({memory} MB) running {image}");
    }

    if let Some(public_ip) = runtime.public_ip {
        println!(" public IP: {}", public_ip);
    }
    println!("private IP: {}", runtime.private_ip);

    Ok(())
}
§Regions

Flytrap models Fly.io regions as an enum:

use flytrap::{City, Placement, Region};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let runtime = Placement::current()?;
    let region = runtime.region().unwrap_or(Region::Guadalajara);

    show(region);
    Ok(())
}

fn show(region: Region) {
    let City { name, country, geo } = region.city;
    println!("Running in {name} ({country}) @ {}, {}", geo.x(), geo.y());
}

Regions implement Ord, and sort geographically:

use flytrap::Region::*;

let mut regions = [Bucharest, Chicago, HongKong, Johannesburg,
                   LosAngeles, Madrid, Santiago, Tokyo];
regions.sort();

assert_eq!(regions, [LosAngeles, Chicago, Santiago, Madrid,
                     Bucharest, Johannesburg, HongKong, Tokyo]);

§DNS queries

Create a Resolver in order to query the Fly.io .internal DNS zone.

use flytrap::Resolver;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resolver = Resolver::new()?;

    // Discover all instances of the currently-running app
    let peers = resolver.current()?.peers().await?;

    for peer in peers {
        println!("peer {} in {} @ {}", peer.id, peer.location, peer.private_ip);
    }

    Ok(())
}

§Machines API requests

Create an api::Client to send requests to the machines API

use std::env;
use flytrap::api::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = env::var("FLY_API_TOKEN")?;
    let client = Client::new(token);

    // Discover other instances of the currently-running app
    let peers = client.peers().await?;

    for peer in peers {
        println!("peer {} in {} is {:?}", peer.name, peer.location, peer.state);
    }

    Ok(())
}

§HTTP headers

The http module contains typed Header implementations of the HTTP request headers added by Fly.io edge proxies, like Fly-Client-IP.

§Features

Flytrap’s compilation can be controlled through a number of Cargo features.

  • api: Enable the client for the Fly.io machines API
  • dns: Enable Resolver for querying Fly.io internal DNS, via hickory-dns
  • detect: Enable automatic Resolver setup for Wireguard VPN clients, via if-addrs ⭐️
  • environment: Enable code which reads Fly.io environment variables like $FLY_PUBLIC_IP ⭐️
  • http: Enable types for HTTP headers like Fly-Client-IP ⭐️
  • nightly: Enable code which is only accepted by nightly Rust toolchains
  • regions: Enable the Region type and RegionDetails structures ⭐️
  • serde: Enable Serde #[derive(Deserialize, Serialize)] on this crate’s types
  • system-resolver: Enable the Resolver::system() constructor, which reads /etc/resolv.conf

(Features marked with a ⭐️ are enabled by default.)

Modules§

Structs§

Enums§

Functions§