Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ nats-transport = ["dep:async-nats", "dep:tokio"]
rabbitmq-transport = ["dep:lapin", "dep:tokio"]
redis-transport = ["dep:redis", "dep:tokio"]
schedule = ["dep:chrono", "dep:cron", "dep:tokio"]
security = []
security = ["dep:sha2"]
session = ["dep:getrandom"]
shutdown-hooks = ["dep:tokio", "tokio/macros", "tokio/signal"]
static = ["dep:tokio"]
Expand Down Expand Up @@ -73,6 +73,7 @@ schemars = { version = "1", optional = true }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_urlencoded = "0.7"
sha2 = { version = "0.10", optional = true }
thiserror = "2"
tokio = { version = "1", features = ["fs", "io-util", "net", "rt", "sync", "time"], optional = true }
tonic = { version = "0.14.6", default-features = false, features = ["codegen", "transport"], optional = true }
Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ are opt-in.
| Lifecycle | `shutdown-hooks` | SIGINT and SIGTERM shutdown handling |
| Configuration | `config` | ACL-backed typed configuration parsing |
| Authentication | `auth` | Strategy-backed authentication guards |
| Security | `security` | CORS, CSRF, rate limiting, and security headers |
| Security | `security` | CORS, CSRF, local or provider-backed rate limiting, and security headers |
| Sessions | `session` | Session middleware and replaceable stores |
| Cache | `cache` | Cache abstraction, interceptor, and in-memory store |
| Database | `database` | Replaceable database facade and in-memory backend |
Expand Down Expand Up @@ -284,6 +284,23 @@ from `schemars::JsonSchema` types.
Optional HTTP modules add multipart uploads, static files, gzip compression,
views, sessions, security policies, request context, and an outbound HTTP client.

### Provider-backed rate limiting

The `security` feature keeps `use_global_rate_limit` process-local by default.
Applications that need one budget across multiple processes can implement the
public `RateLimitProvider` contract and register it with
`use_global_rate_limit_provider`. Each atomic acquisition receives a stable
policy identifier, a policy-scoped SHA-256 subject digest, and the configured
request limit and window. Selected header values and bearer credentials do not
cross the provider boundary in plaintext.

Every process using the same policy identifier must use identical limits and
windows. Provider errors reject guarded requests instead of bypassing the
limit. Boot deliberately does not select or bundle a distributed backend; the
built-in `InMemoryRateLimitProvider` does not share state between processes.
This boundary does not cover the separate streaming-disconnect, backpressure,
or graceful-drain work.

## Protocols

### WebSocket
Expand Down
7 changes: 5 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,8 @@ Nest equivalent areas:
- streamable file and download responses (implemented)
- file upload (implemented)
- static assets and SPA shells (implemented)
- security helpers such as CORS, CSRF, helmet-like headers, and rate limiting
- security helpers such as CORS, CSRF, helmet-like headers, process-local rate
limiting, and a provider-neutral atomic boundary for shared rate limits
(implemented)
- sessions (implemented)

Expand Down Expand Up @@ -1042,7 +1043,9 @@ Acceptance:
hidden dotfile defaults, and root traversal protection. (Covered)
- Security helpers can handle CORS preflight and actual response headers, add
helmet-like response headers, reject invalid CSRF tokens on unsafe methods,
and enforce in-memory fixed-window rate limits. (Covered)
enforce in-memory fixed-window rate limits, and delegate atomic acquisitions
to an application-supplied shared provider without exposing plaintext
credentials. Boot does not select a distributed backend. (Covered)
- Sessions can register a provider-backed `SessionManager`, expose
request-bound `Session` handles through `BootRequest::session()` and
Nest-style `#[session]` arguments, bind session ids before handlers, persist
Expand Down
17 changes: 16 additions & 1 deletion src/app/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{CompressionInterceptor, CompressionOptions};
#[cfg(feature = "security")]
use crate::{
CorsMiddleware, CorsOptions, CorsPreflightRoute, CorsResponseInterceptor, CsrfGuard,
CsrfOptions, RateLimitGuard, RateLimitOptions, SecurityHeadersInterceptor,
CsrfOptions, RateLimitGuard, RateLimitOptions, RateLimitProvider, SecurityHeadersInterceptor,
SecurityHeadersOptions,
};
#[cfg(feature = "session")]
Expand Down Expand Up @@ -315,6 +315,21 @@ impl BootApplicationBuilder {
self
}

/// Add an application-wide rate limit guard backed by a shared provider.
#[cfg(feature = "security")]
pub fn use_global_rate_limit_provider<P>(
mut self,
options: RateLimitOptions,
provider: P,
) -> Self
where
P: RateLimitProvider,
{
self.global_pipeline
.push_guard(RateLimitGuard::with_provider(options, provider));
self
}

/// Add global session middleware and cookie persistence.
#[cfg(feature = "session")]
pub fn use_global_sessions(mut self, manager: SessionManager) -> Self {
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ pub use schedule::{
#[cfg(feature = "security")]
pub use security::{
CorsMiddleware, CorsOptions, CorsPreflightRoute, CorsResponseInterceptor, CsrfGuard,
CsrfOptions, RateLimitGuard, RateLimitOptions, SecurityHeadersInterceptor,
SecurityHeadersOptions,
CsrfOptions, InMemoryRateLimitProvider, RateLimitDecision, RateLimitGuard, RateLimitOptions,
RateLimitProvider, RateLimitRequest, SecurityHeadersInterceptor, SecurityHeadersOptions,
};
pub use serialization::{SerializationInterceptor, SerializationOptions};
#[cfg(feature = "session")]
Expand Down
5 changes: 4 additions & 1 deletion src/security/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ mod rate_limit;
pub use cors::{CorsMiddleware, CorsOptions, CorsPreflightRoute, CorsResponseInterceptor};
pub use csrf::{CsrfGuard, CsrfOptions};
pub use headers::{SecurityHeadersInterceptor, SecurityHeadersOptions};
pub use rate_limit::{RateLimitGuard, RateLimitOptions};
pub use rate_limit::{
InMemoryRateLimitProvider, RateLimitDecision, RateLimitGuard, RateLimitOptions,
RateLimitProvider, RateLimitRequest,
};
Loading
Loading