| Crates.io | farp |
| lib.rs | farp |
| version | 1.0.2 |
| created_at | 2025-11-05 22:55:59.26402+00 |
| updated_at | 2025-12-08 14:54:17.116681+00 |
| description | Forge API Gateway Registration Protocol (FARP) - Schema-aware service discovery and gateway integration |
| homepage | |
| repository | https://github.com/xraph/farp |
| max_upload_size | |
| id | 1918770 |
| size | 333,883 |
FARP is a Rust implementation of the Forge API Gateway Registration Protocol - a standardized mechanism for service instances to register their API schemas, health information, and capabilities with API gateways and service discovery systems.
Add FARP to your Cargo.toml:
[dependencies]
farp = "1.0.0"
# With all features
farp = { version = "1.0.0", features = ["full"] }
# With specific providers
farp = { version = "1.0.0", features = ["providers-openapi", "providers-asyncapi", "gateway"] }
use farp::prelude::*;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<()> {
// 1. Create a schema manifest
let mut manifest = new_manifest("user-service", "v1.0.0", "instance-123");
manifest.add_capability("rest");
manifest.endpoints.health = "/health".to_string();
// 2. Add an OpenAPI schema
let schema = serde_json::json!({
"openapi": "3.1.0",
"info": {"title": "User API", "version": "1.0.0"},
"paths": {"/users": {"get": {}}}
});
let hash = calculate_schema_checksum(&schema)?;
manifest.add_schema(SchemaDescriptor {
schema_type: SchemaType::OpenAPI,
spec_version: "3.1.0".to_string(),
location: SchemaLocation {
location_type: LocationType::Inline,
inline_schema: Some(schema),
..Default::default()
},
hash,
content_type: "application/json".to_string(),
size: 1024,
..Default::default()
});
manifest.update_checksum()?;
manifest.validate()?;
// 3. Register with an in-memory registry
use farp::registry::memory::MemoryRegistry;
let registry = Arc::new(MemoryRegistry::new());
registry.register_manifest(&manifest).await?;
println!("โ
Manifest registered successfully!");
Ok(())
}
FARP uses feature flags to minimize dependencies:
default: Core types + memory registrymemory-registry: In-memory registry implementationproviders-openapi: OpenAPI schema providerproviders-asyncapi: AsyncAPI schema providerproviders-grpc: gRPC/Protocol Buffer providerproviders-graphql: GraphQL schema providerproviders-orpc: oRPC providerproviders-avro: Apache Avro providerproviders-thrift: Apache Thrift providerproviders-all: All schema providersgateway: Gateway client for route conversionfull: Everything enabledA Schema Manifest describes all API contracts exposed by a service instance:
pub struct SchemaManifest {
pub version: String, // Protocol version
pub service_name: String, // Service name
pub service_version: String, // Service version
pub instance_id: String, // Instance ID
pub schemas: Vec<SchemaDescriptor>, // API schemas
pub capabilities: Vec<String>, // Protocols supported
pub endpoints: SchemaEndpoints, // Health/metrics endpoints
pub updated_at: i64, // Unix timestamp
pub checksum: String, // SHA256 of schemas
}
A Schema Descriptor describes a single API schema:
pub struct SchemaDescriptor {
pub schema_type: SchemaType, // OpenAPI, AsyncAPI, etc.
pub spec_version: String, // Spec version
pub location: SchemaLocation, // Where to fetch schema
pub content_type: String, // MIME type
pub hash: String, // SHA256 hash
pub size: i64, // Size in bytes
}
Schemas can be retrieved via three strategies:
use farp::prelude::*;
let mut manifest = new_manifest("api-service", "v1.0.0", "instance-1");
manifest.add_capability("rest");
manifest.endpoints.health = "/health".to_string();
manifest.update_checksum()?;
// Register with registry
registry.register_manifest(&manifest).await?;
use farp::prelude::*;
registry.watch_manifests("api-service", Box::new(|event| {
match event.event_type {
EventType::Added => println!("Service added: {}", event.manifest.instance_id),
EventType::Updated => println!("Service updated: {}", event.manifest.instance_id),
EventType::Removed => println!("Service removed: {}", event.manifest.instance_id),
}
})).await?;
use farp::gateway::Client;
let client = Client::new(registry);
client.watch_services("api-service", |routes| {
for route in routes {
println!("Configure route: {} {} -> {}",
route.methods.join(","),
route.path,
route.target_url
);
}
}).await?;
use farp::providers::openapi::OpenAPIProvider;
use farp::provider::{SchemaProvider, Application};
struct MyApp;
impl Application for MyApp {
fn name(&self) -> &str { "my-app" }
fn version(&self) -> &str { "1.0.0" }
fn routes(&self) -> Box<dyn std::any::Any + Send + Sync> {
Box::new(()) // Your route info
}
}
let provider = OpenAPIProvider::default();
let schema = provider.generate(&MyApp).await?;
Run the test suite:
# Run all tests
cargo test
# Run tests with all features
cargo test --all-features
# Run specific test
cargo test test_manifest_creation
# Run with output
cargo test -- --nocapture
Run the example:
cargo run --example basic --all-features
Generate and view documentation:
cargo doc --all-features --open
FARP follows a layered architecture:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Applications & Gateways โ
โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FARP Protocol Core โ
โ - Types & Manifests โ
โ - Provider & Registry Traits โ
โ - Validation & Checksums โ
โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโดโโโโโโโ
โ โ
โโโโโโโโโผโโโโโโโ โโโผโโโโโโโโโโโโโโโโโ
โ Providers โ โ Registries โ
โ - OpenAPI โ โ - Memory โ
โ - AsyncAPI โ โ - (Future: etcd,โ
โ - gRPC โ โ Consul, K8s) โ
โ - GraphQL โ โ โ
โ - ... โ โ โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Licensed under either of:
at your option.
For questions or feedback, please open an issue.
Built with โค๏ธ using Rust