Rust Backend Coding Standards
SkillDev toolsLets your agent write or review Rust backend code for the Static Web Server project, including modules, types, and async code.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Rust Backend Coding Standards skill
About this capability
Write or review Rust backend code for the Static Web Server (SWS) project — crates, modules, functions, types, error handling, and async code
What this skill tells your AI
The instructions your AI receives, as published by static-web-server/static-web-server in .agents/skills/rust-backend/SKILL.md and read by ahel’s review.
Load this skill when writing, reviewing, or refactoring Rust code in the SWS project.
When to load: editing any file under src/, adding a new module, changing error handling, touching async code, or reviewing a PR that modifies Rust source.
Mandatory Tools
Always use the following commands to maintain code quality and consistency:
Linting
cargo clippy --features all -- -D warningscargo clippy --features all --tests -- -D warnings
Formatting
cargo fmt --all -- --check tests/*.rs
Testing
cargo test -v --features allcargo test -v --no-default-features
Cargo docs lint
cargo +nightly rustdoc --lib -Zrustdoc-map --features all \
--config "build.rustflags=[\"--cfg\", \"tokio_unstable\"]" \
-Zhost-config -Ztarget-applies-to-host \
--config "host.rustflags=[\"--cfg\", \"tokio_unstable\"]" \
--config "build.rustdocflags=[\"--cfg\", \"docsrs\", \"--cfg\", \"docsrs\", \"--cfg\", \"tokio_unstable\", \"-Z\", \"unstable-options\", \"--emit=invocation-specific\", \"--cap-lints\", \"warn\", \"--extern-html-root-takes-precedence\"]" \
-Zunstable-options -- --document-private-items
Code Quality
- All clippy commands in Mandatory Tools must pass with zero warnings before committing
unsafeis forbidden at the crate level: SWS uses#![forbid(unsafe_code)]. Consider refactoring to avoidunsafeentirely- Prefer
&Pathover&PathBufin function parameters. Acceptimpl AsRef<Path>for public APIs - Use
#[must_use]on pure functions whose return value should not be silently discarded - Derive common traits explicitly:
Debug,Clone,PartialEq,Eqon all public types unless there is a reason not to - No commented-out code: Delete it. Git history preserves it
Error Handling
- Use the crate's
Result<T>andErrortypes: Defined insrc/error.rs. All fallible functions returnResult<T>orResult<T, StatusCode>for HTTP-level errors - Use
anyhow::Contextfor wrapping:fallible_op().with_context(|| "failed to parse config")? - No
unwrap()orexpect()in production code: Use?or match. Allowexpectonly for values guaranteed by prior validation (e.g., a regex that is known to compile, a lock that should never be poisoned). Add an inline comment explaining the invariant - Log errors at the boundary: Module code returns errors. The HTTP handler (
handler.rs) logs them and converts to HTTP status codes - Distinguish HTTP status codes from internal errors:
StatusCode(hyper) for HTTP semantics;Error(anyhow) for internal failures. Functions useResult<T, StatusCode>when the only possible failures are HTTP-level
Async Code
- Use
tokioas the runtime: All async code targetstokio(multi-threaded,rt-multi-threadfeature) - No
block_onin async context: Never calltokio::runtime::Handle::block_oninside an async function - Prefer
spawn_blockingfor CPU-bound work: Offload file hashing, compression dictionary building, etc. - Use
hyperas the HTTP framework: SWS is built onhyperv1 withhttp-body-util.src/service.rsdefinesRouterServiceandRequestService, which implementhyper::service::Serviceand delegate toRequestHandler::handle()
HTTP & Request Handling
- Request pipeline ordering:
handler.rsorchestrates the request flow in a fixed order with three phases:- Pre-processing (may short-circuit with a response): method check → health/metrics → CORS → basic auth → maintenance mode → redirects → rewrites → virtual hosts → markdown negotiation
- Core: static file resolution and serving
- Post-processing (additive, runs on every response): fallback page → CORS headers → text charset → static compression → dynamic compression → cache-control → security headers → custom headers
- Post-processing is additive: Each post-processing step appends or modifies headers. No step removes headers set by a previous step unless explicitly documented
- Response body type:
crate::body::Bodyis a type alias forBoxBody<Bytes, std::io::Error>(defined insrc/body.rs). Use the constructorscrate::body::empty(),crate::body::full(impl Into<Bytes>), orcrate::body::stream<S>(s) - Static file serving is the core:
static_files.rshandles path resolution, index files, directory listing, pre-compressed variants, and byte-range requests
Settings & Configuration
- Three equivalent channels: CLI arguments (
clap), environment variables, and TOML config file. Defined insrc/settings/ - Precedence (lowest to highest): compiled defaults → TOML config file → environment variables → CLI arguments. Runtime validation runs after merging
- Feature-gated settings: Settings that require Cargo features (e.g.,
compression,directory-listing) are conditionally compiled with#[cfg(feature = "...")] - Validation at startup, not per-request: Canonicalize paths, validate TLS certificates, parse index files once at startup in
server/opts.rs
File System
- Canonicalize paths once at startup: The root directory is canonicalized in
server/opts.rs. Per-request path resolution reuses this canonical base - Path traversal prevention:
sanitize_path()(insrc/fs/path.rs) strips.., root prefixes, and other traversal components.resolve_and_contain()(insrc/static_files/security.rs) verifies the resolved path stays within the base directory - Symlink policy: When
--follow-symlinksis disabled (default),enforce_symlink_policy()(insrc/static_files/security.rs) walks each path component checking for symlinks viasymlink_metadata(). This is a syscall per component — check cheaper guards (hidden files) first - File metadata operations:
try_metadata()andtry_metadata_with_html_suffix()(insrc/fs/meta.rs) encapsulate filesystem access with proper error mapping to HTTP status codes
Patterns to Avoid
- No
Stringas an error type: Use structured errors orStatusCode - No
Box<dyn Error>: Useanyhow::Error - No global mutable state: No
static mutorlazy_static!withMutex. SWS usesArc<RequestHandlerOpts>for shared read-only config - No deep nesting: Extract nested conditionals into named functions or match guards
- No per-request canonicalize or alloc when avoidable: Cache canonical paths, reuse buffers, avoid
clone()in the hot path
Signals
- GitHub stars
- 2k
- Forks
- 130
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
rust-backend- Source
- github.com/static-web-server/static-web-server