Skip to main content
rust-middleware Web middleware expert covering request tracking, CORS configuration, rate limiting, authentication guards, compression, and middleware composition patterns.
Ir a la instalación Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/huiali/rust-skills --skill rust-middlewareEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... Más de este repositorio Actor model expert covering message passing, state isolation, supervision trees, deadlock prevention, fault tolerance, Actix framework, and Erlang-style concurrency patterns.
Rust anti-patterns and common mistakes expert. Handles code review issues with clone abuse, unwrap in production, String misuse, index loops, and refactoring guidance.
Advanced async patterns expert covering Stream implementation, zero-copy buffers, tokio::spawn lifetimes, plugin system scheduling, tonic streaming, and async lifetime management.
Explorador de archivos
4 archivos Ocupaciones relacionadas SOC
Basado en la clasificación ocupacional SOC
name rust-middleware description Web middleware expert covering request tracking, CORS configuration, rate limiting, authentication guards, compression, and middleware composition patterns. metadata {"triggers":["middleware","CORS","rate limiting","request tracking","authentication guard","compression","middleware pattern"]}
Solution Patterns
Pattern 1: Request Tracking Middleware (Actix)
use actix_web::{
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
Error, HttpMessage,
};
use futures::future::{ready, LocalBoxFuture, Ready};
use std::rc::Rc;
use uuid::Uuid;
#[derive(Debug, Clone)]
pub struct RequestId (pub String );
pub struct RequestTracking ;
impl <S, B> Transform<S, ServiceRequest> for RequestTracking
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static ,
S::Future: 'static ,
B: 'static ,
{
type Response = ServiceResponse<B>;
= Error;
= ();
= RequestTrackingMiddleware<S>;
= Ready< < ::Transform, ::InitError>>;
(& , service: S) ::Future {
( (RequestTrackingMiddleware {
service: Rc:: (service),
}))
}
}
<S> {
service: Rc<S>,
}
<S, B> Service<ServiceRequest> <S>
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + ,
S::Future: ,
B: ,
{
= ServiceResponse<B>;
= Error;
= LocalBoxFuture< , < ::Response, ::Error>>;
forward_ready!(service);
(& , req: ServiceRequest) ::Future {
= Rc:: (& .service);
:: ( {
= req
. ()
. ( )
. (|| req. (). ( ))
. (|v| v. (). ())
. (|s| s. ())
. (|| Uuid:: (). ());
req. (). ( (request_id. ()));
= std::time::Instant:: ();
log::info!( , req. (), req. (), request_id);
= service. (req). ?;
= start_time. ();
log::info!(
,
res. (). (),
duration,
request_id
);
res. (). (
actix_web::http::header::HeaderName:: ( ),
actix_web::http::header::HeaderValue:: (&request_id). (),
);
(res)
})
}
}
actix_web::{web, App, HttpServer};
() std::io:: <()> {
HttpServer:: (|| {
App:: ()
. (RequestTracking)
. ( , web:: (). (handler))
})
. ( )?
. ()
.
}
type
Error
type
InitError
type
Transform
type
Future
Result
Self
Self
fn
new_transform
self
->
Self
ready
Ok
new
pub
struct
RequestTrackingMiddleware
impl
for
RequestTrackingMiddleware
where
'static
'static
'static
type
Response
type
Error
type
Future
'static
Result
Self
Self
fn
call
self
->
Self
let
service
clone
self
Box
pin
async
move
let
request_id
headers
get
"X-Request-ID"
or_else
headers
get
"Request-ID"
and_then
to_str
ok
map
to_string
unwrap_or_else
new_v4
to_string
extensions_mut
insert
RequestId
clone
let
start_time
now
"Request: {} {} - ID: {}"
method
path
let
mut
res
call
await
let
duration
elapsed
"Response: {} - Duration: {:?} - ID: {}"
status
as_u16
headers_mut
insert
from_static
"x-request-id"
from_str
unwrap
Ok
use
#[actix_web::main]
async
fn
main
->
Result
new
new
wrap
route
"/api"
get
to
bind
"127.0.0.1:8080"
run
await
Pattern 2: CORS Configuration use actix_cors::Cors;
use actix_web::http::header;
pub struct CorsBuilder ;
impl CorsBuilder {
pub fn production (allowed_origins: &[&str ]) -> Cors {
Cors::default ()
.allowed_origin_fn (move |origin, _req_head| {
let origin_str = origin.to_str ().unwrap_or ("" );
let allowed = allowed_origins.iter ().any (|&o| o == origin_str);
log::debug!("CORS: origin={} allowed={}" , origin_str, allowed);
allowed
})
.allowed_methods (vec! ["OPTIONS" , "HEAD" , "GET" , "POST" , "PUT" , "PATCH" , "DELETE" ])
.allowed_headers (vec! [
header::AUTHORIZATION,
header::ACCEPT,
header::CONTENT_TYPE,
])
.expose_headers (vec! ["x-request-id" ])
.supports_credentials ()
.max_age (3600 )
}
pub fn development () -> Cors {
Cors::default ()
.allow_any_origin ()
.allow_any_method ()
.allow_any_header ()
.supports_credentials ()
}
pub fn api (strict_origins: &[&str ]) -> Cors {
Cors::default ()
.allowed_origins (strict_origins)
.allowed_methods (vec! ["GET" , "POST" , "PUT" , "DELETE" , "PATCH" ])
.allowed_headers (vec! [header::AUTHORIZATION, header::CONTENT_TYPE])
.max_age (86400 )
}
}
HttpServer::new (|| {
App::new ()
.wrap (CorsBuilder::production (&["https://example.com" ]))
.service (api_routes ())
})
Pattern 3: Rate Limiting Middleware use actix_web::{
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
Error, HttpResponse,
};
use futures::future::{ready, LocalBoxFuture, Ready};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::RwLock;
#[derive(Debug, Clone)]
pub struct RateLimitConfig {
pub requests_per_second: u64 ,
pub window_seconds: u64 ,
pub whitelist: Vec <String >,
}
struct SlidingWindow {
count: u64 ,
window_start: Instant,
}
pub struct RateLimiting {
config: RateLimitConfig,
counters: Arc<RwLock<HashMap<String , SlidingWindow>>>,
}
impl RateLimiting {
pub fn new (config: RateLimitConfig) -> Self {
Self {
config,
counters: Arc::new (RwLock::new (HashMap::new ())),
}
}
async fn is_rate_limited (&self , key: &str ) -> bool {
let mut counters = self .counters.write ().await ;
let now = Instant::now ();
counters.retain (|_, w| {
now.duration_since (w.window_start) < Duration::from_secs (self .config.window_seconds)
});
match counters.get_mut (key) {
Some (window) => {
if now.duration_since (window.window_start)
< Duration::from_secs (self .config.window_seconds)
{
window.count += 1 ;
window.count > self .config.requests_per_second
} else {
window.count = 1 ;
window.window_start = now;
false
}
}
None => {
counters.insert (
key.to_string (),
SlidingWindow {
count: 1 ,
window_start: now,
},
);
false
}
}
}
}
impl <S, B> Transform<S, ServiceRequest> for RateLimiting
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static ,
S::Future: 'static ,
B: 'static ,
{
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
type Transform = RateLimitingMiddleware<S>;
type Future = Ready<Result <Self ::Transform, Self ::InitError>>;
fn new_transform (&self , service: S) -> Self ::Future {
ready (Ok (RateLimitingMiddleware {
service,
config: self .config.clone (),
counters: self .counters.clone (),
}))
}
}
pub struct RateLimitingMiddleware <S> {
service: S,
config: RateLimitConfig,
counters: Arc<RwLock<HashMap<String , SlidingWindow>>>,
}
impl <S, B> Service<ServiceRequest> for RateLimitingMiddleware <S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static ,
S::Future: 'static ,
B: 'static ,
{
type Response = ServiceResponse<B>;
type Error = Error;
type Future = LocalBoxFuture<'static , Result <Self ::Response, Self ::Error>>;
forward_ready!(service);
fn call (&self , req: ServiceRequest) -> Self ::Future {
let client_ip = req
.connection_info ()
.peer_addr ()
.map (|s| s.to_string ())
.unwrap_or_else (|| "unknown" .to_string ());
if self .config.whitelist.contains (&client_ip) {
return Box ::pin (self .service.call (req));
}
let counters = self .counters.clone ();
let config = self .config.clone ();
let service = self .service.clone ();
Box ::pin (async move {
let limiter = RateLimiting {
config,
counters,
};
if limiter.is_rate_limited (&client_ip).await {
let response = HttpResponse::TooManyRequests ().json (serde_json::json!({
"error" : "RATE_LIMIT_EXCEEDED" ,
"message" : "Too many requests"
}));
return Ok (ServiceResponse::new (req.into_parts ().0 , response));
}
service.call (req).await
})
}
}
let rate_limit = RateLimiting::new (RateLimitConfig {
requests_per_second: 100 ,
window_seconds: 60 ,
whitelist: vec! ["127.0.0.1" .to_string ()],
});
HttpServer::new (move || {
App::new ()
.wrap (rate_limit.clone ())
.service (api_routes ())
})
Pattern 4: Authentication Guard (Axum) use axum::{
extract::Request,
http::StatusCode,
middleware::Next,
response::{IntoResponse, Response},
};
#[derive(Clone)]
pub struct Claims {
pub sub: String ,
pub exp: usize ,
}
pub async fn auth_middleware (
mut req: Request,
next: Next,
) -> Result <Response, StatusCode> {
let auth_header = req
.headers ()
.get ("Authorization" )
.and_then (|h| h.to_str ().ok ())
.ok_or (StatusCode::UNAUTHORIZED)?;
let token = auth_header
.strip_prefix ("Bearer " )
.ok_or (StatusCode::UNAUTHORIZED)?;
let claims = verify_jwt (token)
.map_err (|_| StatusCode::UNAUTHORIZED)?;
req.extensions_mut ().insert (claims);
Ok (next.run (req).await )
}
fn verify_jwt (token: &str ) -> Result <Claims, jsonwebtoken::errors::Error> {
todo!()
}
use axum::{middleware, routing::get, Router};
async fn protected_handler (
Extension (claims): Extension<Claims>,
) -> impl IntoResponse {
format! ("Hello, user {}" , claims.sub)
}
let app = Router::new ()
.route ("/protected" , get (protected_handler))
.layer (middleware::from_fn (auth_middleware));
Pattern 5: Compression Middleware use actix_web::middleware::Compress;
HttpServer::new (|| {
App::new ()
.wrap (Compress::default ())
.service (api_routes ())
})
use tower_http::compression::CompressionLayer;
let app = Router::new ()
.route ("/" , get (handler))
.layer (CompressionLayer::new ());
Middleware Composition Patterns
Layer-Based Ordering Request Flow:
↓
┌─────────────────────┐
│ Request Tracking │ 1. Generate request ID
├─────────────────────┤
│ CORS │ 2. Handle preflight
├─────────────────────┤
│ Compression │ 3. Compress response
├─────────────────────┤
│ Rate Limiting │ 4. Check rate limits
├─────────────────────┤
│ Authentication │ 5. Verify credentials
├─────────────────────┤
│ Handler │ 6. Business logic
└─────────────────────┘
↓
Response
Workflow
Step 1: Identify Cross-Cutting Concerns Common middleware needs:
→ Request tracking? Add request ID middleware
→ API from web clients? Add CORS
→ Public API? Add rate limiting
→ Protected routes? Add authentication guard
→ Large responses? Add compression
→ Logging? Add logger middleware
Step 2: Choose Middleware Order Recommended order (outer to inner):
1. Request tracking (first, for logging)
2. CORS (handle preflight early)
3. Compression (wrap entire response)
4. Rate limiting (before expensive operations)
5. Authentication (verify before business logic)
6. Handler (business logic)
Step 3: Configure Per Environment Development:
→ Permissive CORS
→ Verbose logging
→ No rate limiting
Production:
→ Strict CORS with whitelist
→ Info logging only
→ Rate limiting enabled
→ Compression enabled
Review Checklist When implementing middleware:
Verification Commands
curl -X OPTIONS http://localhost:8080/api \
-H "Origin: https://example.com" \
-H "Access-Control-Request-Method: POST" \
-v
for i in {1..150}; do
curl http://localhost:8080/api &
done
curl http://localhost:8080/api \
-H "Accept-Encoding: gzip" \
-v | grep "Content-Encoding"
curl http://localhost:8080/protected \
-H "Authorization: Bearer <token>" \
-v
wrk -t4 -c100 -d30s http://localhost:8080/api
Common Pitfalls
1. Incorrect CORS Configuration Symptom : Preflight requests fail, browser blocks requests
Cors::default ()
.allow_any_origin ()
.supports_credentials ()
Cors::default ()
.allowed_origins (&["https://example.com" ])
.supports_credentials ()
2. Rate Limiting Memory Leak Symptom : Memory grows unbounded
let counters : HashMap<String , Counter> = HashMap::new ();
counters.retain (|_, window| {
now.duration_since (window.start) < window_duration
});
3. Blocking Operations in Middleware Symptom : Request latency spikes, thread starvation
async fn bad_middleware (req: Request, next: Next) -> Response {
std::fs::read ("config.json" ).unwrap ();
next.run (req).await
}
async fn good_middleware (req: Request, next: Next) -> Response {
tokio::fs::read ("config.json" ).await .unwrap ();
next.run (req).await
}
Related Skills
rust-web - Web framework basics
rust-auth - Authentication implementations
rust-async - Async middleware patterns
rust-error - Error handling in middleware
rust-performance - Middleware optimization
Localized Reference