| Crates.io | flytrap |
| lib.rs | flytrap |
| version | 0.2.1 |
| created_at | 2023-11-18 05:23:00.835677+00 |
| updated_at | 2024-05-29 00:40:20.524273+00 |
| description | Query the Fly.io runtime environment |
| homepage | https://flytrap.fly.dev/ |
| repository | https://github.com/silverlyra/flytrap |
| max_upload_size | |
| id | 1040285 |
| size | 142,615 |
Flytrap is a Rust crate for reading the Fly.io runtime environment.
$FLY_PUBLIC_IP into a structtop3.nearest.of.<app>.internalFly-Client-IP (into an IpAddr)ord into names like ”Chicago” and lat/long coordinatesA demo app is available at flytrap.fly.dev which shows this crate’s capabilities.
Flytrap can be added to your project with cargo:
cargo add flytrap
Most of the crate’s features are enabled by default, but at your
option, you can enable only what you need by setting default-features = false.
cargo add flytrap --no-default-features --features 'dns environment http serde'
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(())
}
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:
#[test]
fn longitude_latitude() {
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]);
}
If Flytrap receives a region code it doesn’t recognize (i.e., a region which
didn’t exist when your version of Flytrap was built), the raw code like ord
will be stored as a RegionCode.
(If you build Flytrap without the regions feature,
flytrap::Region simply becomes an alias for String.)
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);
}
}
Create an api::Client to send requests to the machines API.
[!NOTE]
Theapimodule is not built by default; theapifeature must be enabled first.
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(())
}
The http module contains typed Header implementations of
the HTTP request headers added by Fly.io edge proxies, like
Fly-Client-IP.
use axum::response::Html;
use axum_extra::TypedHeader;
use flytrap::http::{FlyClientIp, FlyRegion};
async fn ip(
TypedHeader(ip): TypedHeader<FlyClientIp>,
TypedHeader(edge): TypedHeader<FlyRegion>,
) -> Html<String> {
Html(format!("Your IP: <code>{ip}</code> (via {edge})"))
}
Flytrap’s compilation can be controlled through a number of Cargo features.
api: Enable the api::Client for the Fly.io machines APIdns: 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 toolchainsregions: Enable the Region type and RegionDetails structures ⭐️serde: Enable Serde #[derive(Deserialize, Serialize)] on this crate’s typessystem-resolver: Enable the Resolver::system() constructor, which reads /etc/resolv.conf(Features marked with a ⭐️ are enabled by default.)