Expand description
§axum-turnstile
Cloudflare Turnstile verification middleware for Axum.
This crate provides middleware for verifying Cloudflare Turnstile tokens in Axum web applications. Turnstile is Cloudflare’s privacy-first CAPTCHA alternative that helps protect your application from bots and abuse.
§Features
- 🔒 Easy integration with Axum applications
- 🎯 Tower middleware layer for flexible composition
- ⚙️ Configurable header names and verification endpoints
- 🧪 Support for Cloudflare’s test keys
- 📦 Minimal dependencies
§Quick Start
Add this to your Cargo.toml:
[dependencies]
axum-turnstile = "0.1"
axum = "0.8"
tokio = { version = "1", features = ["full"] }§Basic Usage
use axum::{routing::post, Router};
use axum_turnstile::{TurnstileLayer, VerifiedTurnstile};
#[tokio::main]
async fn main() {
// Create a protected endpoint
let app = Router::new()
.route("/api/protected", post(protected_handler))
.layer(TurnstileLayer::from_secret("your-secret-key"));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
// Handler that requires Turnstile verification
async fn protected_handler(_verified: VerifiedTurnstile) -> &'static str {
"Success! Turnstile token verified."
}§How It Works
- Client includes the Turnstile token in the
CF-Turnstile-Tokenheader - Middleware extracts and verifies the token with Cloudflare’s API
- If valid, the request proceeds and handlers can extract
VerifiedTurnstile - If invalid or missing, the request is rejected with an appropriate status code
§Advanced Configuration
use axum_turnstile::{TurnstileConfig, TurnstileLayer};
let config = TurnstileConfig::new("your-secret-key")
.with_header_name("X-Custom-Turnstile-Token")
.with_verify_url("https://custom-endpoint.example.com/verify");
let layer = TurnstileLayer::new(config);§Testing
Cloudflare provides test keys that always pass or fail verification:
- Always passes:
1x0000000000000000000000000000000AA - Always fails:
2x0000000000000000000000000000000AA
use axum_turnstile::TurnstileLayer;
// Use the test key that always passes
let layer = TurnstileLayer::from_secret("1x0000000000000000000000000000000AA");§Response Codes
400 Bad Request: Turnstile token header is missing403 Forbidden: Token verification failed500 Internal Server Error: Error communicating with Cloudflare’s API
§Extracting the Verified Marker
The VerifiedTurnstile type implements FromRequestParts,
so you can use it as an extractor in your handlers:
use axum_turnstile::VerifiedTurnstile;
async fn handler(_verified: VerifiedTurnstile) -> &'static str {
"Only reached if Turnstile verification succeeded"
}Structs§
- Turnstile
Config - Configuration for Turnstile verification
- Turnstile
Layer - Layer that applies Turnstile verification middleware
- Turnstile
Middleware - Middleware that verifies Turnstile tokens
- Verified
Turnstile - Marker type that can be extracted in handlers after successful verification