sdforge 0.5.0-rc.4

Multi-protocol SDK framework with unified macro configuration
// Copyright (c) 2026 Kirky.X
// SPDX-License-Identifier: MIT
//! HTTP server implementation

use crate::core::ApiMetadata;
#[cfg(test)]
use crate::core::Registration;
use crate::define_registration;
use axum::routing::MethodRouter;

// Type imports re-exported to test modules via `use super::super::*`.
#[cfg(test)]
use axum::Router;
#[cfg(test)]
use axum::body::Body;

pub mod response;
pub mod security_headers;
pub mod version_routing;

pub use response::{build_fallback_response, build_json_response};
pub use security_headers::SecurityHeaders;
pub use version_routing::{
    VersionRedirectLayer, VersionRedirectService, VersionRouterConfig, VersionedRoute,
    build_version_router, version_redirect_middleware,
};

// Re-export rate-limit types.
// - Core types (LimiteronAdapter, RateLimiter) available with `ratelimit`.
// - HTTP middleware (RateLimitLayer) available with `ratelimit-http`.
// Allows downstream users to access them via `sdforge::http::` without
// reaching into `sdforge::security::ratelimit::`.
#[cfg(feature = "ratelimit-http")]
pub use crate::security::RateLimitLayer;
#[cfg(feature = "ratelimit")]
pub use crate::security::{LimiteronAdapter, RateLimiter};

#[cfg(feature = "etag")]
pub mod etag;
#[cfg(feature = "graceful")]
pub mod graceful;
mod http_impl;
#[cfg(feature = "ratelimit-http")]
pub use http_impl::rate_limit_layer;
pub use http_impl::{build, build_with_config, build_with_redirect};

#[cfg(feature = "graceful")]
pub use graceful::{GracefulShutdownConfig, default_shutdown_signal, serve_with_graceful_shutdown};

// Re-export internal helpers for test access.
#[cfg(all(test, feature = "grpc"))]
pub(crate) use http_impl::preserve_grpc_inventory;
#[cfg(all(test, feature = "mcp"))]
pub(crate) use http_impl::preserve_mcp_inventory;
#[cfg(all(test, feature = "websocket"))]
pub(crate) use http_impl::preserve_websocket_inventory;
#[cfg(test)]
pub(crate) use http_impl::{apply_security_headers, get_or_generate_request_id};
// Health probes & metrics endpoints resolve module-prefixed paths
// when scanning for collisions with user routes.
#[cfg(test)]
pub(crate) use http_impl::resolve_route_path;
#[cfg(any(feature = "health", feature = "metrics"))]
pub(crate) use http_impl::route_path_taken;

/// Request ID header name
#[cfg_attr(feature = "context", allow(dead_code))]
pub(crate) const X_REQUEST_ID: &str = "x-request-id";

/// HTTP route registration
#[derive(Debug, Clone)]
pub struct HttpRoute {
    /// Route path (may contain module prefix placeholders)
    path: String,
    /// Handler function (includes method routing)
    handler: MethodRouter,
    /// API metadata
    metadata: ApiMetadata,
    /// Module prefix (if any) - used for route grouping
    module_prefix: Option<String>,
}

// Generated by `define_registration!` macro for unified registration system.
define_registration!(RouteRegistration, HttpRoute, ApiMetadata);

inventory::collect!(HttpRoute);

#[cfg(test)]
mod tests;