forge-runtime 0.9.0

Runtime executors and gateway for the Forge framework
mod auth;
pub mod jwks;
mod mcp;
mod multipart;
pub mod oauth;
mod request;
mod response;
mod rpc;
mod server;
mod sse;
mod tracing;

pub use auth::{AuthConfig, AuthMiddleware, HmacTokenIssuer, build_auth_context_from_claims};
pub use jwks::{JwksClient, JwksError};
pub use mcp::{McpState, mcp_get_handler, mcp_post_handler};
pub use multipart::rpc_multipart_handler;
pub use oauth::OAuthState;
pub use request::{BatchRpcRequest, BatchRpcResponse, RpcRequest};
pub use response::{RpcError, RpcResponse};
pub use rpc::RpcHandler;
pub use server::{GatewayConfig, GatewayServer};
pub use sse::{
    SseConfig, SsePayload, SseQuery, SseState, sse_handler, sse_job_subscribe_handler,
    sse_subscribe_handler, sse_unsubscribe_handler, sse_workflow_subscribe_handler,
};
pub use tracing::TracingMiddleware;

pub(crate) fn extract_client_ip(headers: &axum::http::HeaderMap) -> Option<String> {
    headers
        .get("x-forwarded-for")
        .and_then(|v| v.to_str().ok())
        .and_then(|s| s.split(',').next())
        .map(|s| s.trim().to_string())
        .filter(|s| !s.is_empty())
        .or_else(|| {
            headers
                .get("x-real-ip")
                .and_then(|v| v.to_str().ok())
                .map(|s| s.trim().to_string())
                .filter(|s| !s.is_empty())
        })
}

pub(crate) fn extract_header(headers: &axum::http::HeaderMap, name: &str) -> Option<String> {
    headers
        .get(name)
        .and_then(|v| v.to_str().ok())
        .filter(|v| !v.is_empty())
        .map(String::from)
}