| Crates.io | oxidite-middleware |
| lib.rs | oxidite-middleware |
| version | 2.0.1 |
| created_at | 2025-12-07 13:25:47.464395+00 |
| updated_at | 2026-01-25 01:49:49.959248+00 |
| description | HTTP middleware for Oxidite v2 (CORS, logging, compression, rate limiting) |
| homepage | |
| repository | https://github.com/meshackbahati/rust-oxidite |
| max_upload_size | |
| id | 1971586 |
| size | 120,383 |
HTTP middleware for Oxidite (CORS, logging, compression, rate limiting).
oxidite-middleware provides a collection of commonly needed HTTP middleware for the Oxidite web framework. Built on top of the tower ecosystem, it offers composable, reusable components that can be easily integrated into your application's request/response pipeline.
Add this to your Cargo.toml:
[dependencies]
oxidite-middleware = "0.1"
Use the ServiceBuilder to compose multiple middleware layers:
use oxidite::prelude::*;
use oxidite_middleware::{ServiceBuilder, LoggerLayer, CorsLayer, CompressionLayer};
#[tokio::main]
async fn main() -> Result<()> {
let mut router = Router::new();
router.get("/", handler);
// Compose multiple middleware layers
let app = ServiceBuilder::new()
.layer(LoggerLayer::new())
.layer(CorsLayer::permissive())
.layer(CompressionLayer::new())
.service(router);
Server::new(app)
.listen("127.0.0.1:3000".parse().unwrap())
.await
}
Configure Cross-Origin Resource Sharing policies:
use oxidite_middleware::{CorsLayer, Origin, Method, Header};
use std::time::Duration;
let cors = CorsLayer::new()
.allow_origin(Origin::exact("https://example.com"))
.allow_methods(vec![Method::GET, Method::POST, Method::PUT, Method::DELETE])
.allow_headers(vec![Header::CONTENT_TYPE, Header::AUTHORIZATION])
.max_age(Duration::from_secs(86400)); // Cache preflight for 1 day
let app = ServiceBuilder::new()
.layer(cors)
.service(router);
Add detailed request/response logging:
use oxidite_middleware::LoggerLayer;
let app = ServiceBuilder::new()
.layer(LoggerLayer::new())
.service(router);
// Or customize the log format
let custom_logger = LoggerLayer::custom(|request, response| {
println!(
"{} {} -> {} ({})",
request.method(),
request.uri().path(),
response.status(),
response.headers().get("content-length").unwrap_or(&"0".parse().unwrap())
);
});
Enable automatic response compression:
use oxidite_middleware::CompressionLayer;
let app = ServiceBuilder::new()
.layer(CompressionLayer::new())
.service(router);
// The middleware automatically compresses responses based on Accept-Encoding header
Protect your application from abuse with rate limiting:
use oxidite_middleware::RateLimitLayer;
use std::time::Duration;
// Allow 100 requests per minute per IP address
let rate_limiter = RateLimitLayer::new(100, Duration::from_secs(60));
let app = ServiceBuilder::new()
.layer(rate_limiter)
.service(router);
// For more granular control
let custom_limiter = RateLimitLayer::builder()
.limit(50) // Max requests
.duration(Duration::from_secs(60)) // Time window
.build();
Add important security headers to responses:
use oxidite_middleware::SecurityHeadersLayer;
let security = SecurityHeadersLayer::new()
.hsts(true)
.x_frame_options("DENY")
.x_content_type_options("nosniff")
.x_xss_protection("1; mode=block");
let app = ServiceBuilder::new()
.layer(security)
.service(router);
Protect against Cross-Site Request Forgery attacks:
use oxidite_middleware::CsrfLayer;
let csrf = CsrfLayer::new()
.cookie_name("csrf-token")
.header_name("x-csrf-token");
let app = ServiceBuilder::new()
.layer(csrf)
.service(router);
Prevent hanging requests with timeouts:
use oxidite_middleware::TimeoutLayer;
use std::time::Duration;
let timeout = TimeoutLayer::new(Duration::from_secs(30));
let app = ServiceBuilder::new()
.layer(timeout)
.service(router);
Track requests across your application with unique IDs:
use oxidite_middleware::RequestIdLayer;
let request_id = RequestIdLayer::new();
let app = ServiceBuilder::new()
.layer(request_id)
.service(router);
// Request IDs can be accessed in handlers via request extensions
Combine multiple middleware for a production-ready application:
use oxidite::prelude::*;
use oxidite_middleware::{
ServiceBuilder, LoggerLayer, CorsLayer, CompressionLayer,
RateLimitLayer, SecurityHeadersLayer, TimeoutLayer
};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<()> {
let mut router = Router::new();
router.get("/", home_handler);
router.post("/api/users", create_user_handler);
// Build a comprehensive middleware stack
let app = ServiceBuilder::new()
// Security
.layer(SecurityHeadersLayer::new())
.layer(CorsLayer::permissive())
// Performance
.layer(CompressionLayer::new())
.layer(TimeoutLayer::new(Duration::from_secs(30)))
// Protection
.layer(RateLimitLayer::new(100, Duration::from_secs(60)))
// Observability
.layer(LoggerLayer::new())
.service(router);
Server::new(app)
.listen("127.0.0.1:3000".parse().unwrap())
.await
}
Create your own middleware by implementing the Tower Layer and Service traits:
use tower::{Layer, Service};
use std::task::{Context, Poll};
use http::{Request, Response};
#[derive(Clone)]
pub struct CustomMiddleware<S> {
inner: S,
}
impl<S, ReqBody, ResBody> Service<Request<ReqBody>> for CustomMiddleware<S>
where
S: Service<Request<ReqBody>, Response = Response<ResBody>>,
{
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, request: Request<ReqBody>) -> Self::Future {
// Pre-processing
println!("Processing request: {} {}", request.method(), request.uri().path());
// Call the inner service
self.inner.call(request)
}
}
#[derive(Clone)]
pub struct CustomMiddlewareLayer;
impl<S> Layer<S> for CustomMiddlewareLayer {
type Service = CustomMiddleware<S>;
fn layer(&self, inner: S) -> Self::Service {
CustomMiddleware { inner }
}
}
All middleware is designed to work seamlessly with Oxidite's architecture:
use oxidite::prelude::*;
use oxidite_middleware::{ServiceBuilder, LoggerLayer};
async fn handler(_req: OxiditeRequest) -> Result<OxiditeResponse> {
Ok(response::text("Hello, World!"))
}
#[tokio::main]
async fn main() -> Result<()> {
let mut router = Router::new();
router.get("/", handler);
// Wrap the router with middleware
let service = ServiceBuilder::new()
.layer(LoggerLayer::new())
.service(router);
Server::new(service)
.listen("127.0.0.1:3000".parse().unwrap())
.await
}
MIT