Initial commit: OpenFUT Bridge

FIFA 23 reverse-engineering proxy and integration scaffold.

- Catch-all HTTP proxy that captures all incoming FIFA 23 traffic
- Known-route mapper (speculative FUT paths → Core API calls)
- Placeholder JSON responses for unmapped endpoints
- Admin endpoints: GET /_bridge/captures, GET /_bridge/unknown
- Capture persistence to captures/*.json for RE analysis
- 4 unit tests passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-25 15:09:47 -07:00
commit a826e5f7d3
19 changed files with 2897 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
use anyhow::Result;
use axum::{
routing::{any, get},
Router,
};
use openfut_bridge::{config::Config, proxy::ProxyState, routes};
use tower_http::{cors::CorsLayer, trace::TraceLayer};
use tracing::info;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
#[tokio::main]
async fn main() -> Result<()> {
dotenvy::dotenv().ok();
tracing_subscriber::registry()
.with(
EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "openfut_bridge=debug,tower_http=info".into()),
)
.with(tracing_subscriber::fmt::layer())
.init();
let cfg = Config::from_env()?;
let listen_addr = cfg.listen_addr.clone();
info!("OpenFUT Bridge starting on {listen_addr}");
info!("Core URL: {}", cfg.core_url);
info!("Placeholder mode: {}", cfg.placeholder_mode);
info!("Captures dir: {}", cfg.captures_dir);
std::fs::create_dir_all(&cfg.captures_dir)?;
let state = ProxyState::new(cfg);
let app = Router::new()
.route("/_bridge/health", get(routes::health::get_health))
.route("/_bridge/captures", get(routes::admin::get_captures))
.route(
"/_bridge/unknown",
get(routes::admin::get_unknown_endpoints),
)
.fallback(any(openfut_bridge::proxy::catch_all_handler))
.layer(TraceLayer::new_for_http())
.layer(CorsLayer::permissive())
.with_state(state);
let listener = tokio::net::TcpListener::bind(&listen_addr).await?;
info!("Bridge listening on http://{listen_addr}");
axum::serve(listener, app).await?;
Ok(())
}