rust-networking
Skill5 starsChanged 10 days agoBSD-3-ClauseView on GitHub
Use when building or reviewing a production Rust network client or server with reqwest, hyper, axum, tower-http, tonic, or rustls; setting an HTTP timeout or deadline budget; retrying safely with Retry-After and jitter; keeping TLS verification on; configuring a connection pool, proxy, or DNS; enforcing a response body limit or overload bound; or adding graceful shutdown. Not for select! or task cancel safety; use `rust-async-internals`.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- adxptived/Rust-Skillstheir own version, first seen Oct 17, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- adxptived/Rust-Skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository46 other files it gives its agents.
- AGENTS.mdAGENTS.md
- cargo-workflowsSkill
- ffi-error-progress-cancelSkill
- memory-modelSkill
- rust-android-buildSkill
- rust-async-internalsSkill
- rust-borrow-semanticsSkill
- rust-callback-boundsSkill
- rust-cliSkill
- rust-code-styleSkill
- rust-compiler-errorsSkill
- rust-copy-on-writeSkill
- rust-crate-architectureSkill
- rust-crate-releaseSkill
- rust-databaseSkill
- rust-debuggingSkill
- rust-disciplineSkill
- rust-embedded-no-stdSkill
- rust-event-loop-stateSkill
- rust-hot-pathSkill
- rust-ios-buildSkill
- rust-iterator-implSkill
- rust-jniSkill
- rust-lintsSkill
- rust-macrosSkill
- rust-native-linkingSkill
- rust-observabilitySkill
- rust-panic-safetySkill
- rust-pattern-semanticsSkill
- rust-performanceSkill
- rust-pin-projectionSkill
- rust-portSkill
- rust-reviewSkill
- rust-sanitizers-miriSkill
- rust-securitySkill
- rust-send-syncSkill
- rust-serdeSkill
- rust-swift-ffiSkill
- rust-tddSkill
- rust-test-toolsSkill
- rust-type-erasureSkill
- rust-unsafeSkill
- rust-varianceSkill
- rust-wasmSkill
- uniffi-boundarySkill
- uniffi-packaging-versioningSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
28 rules. About 0 are common, 16 are distinctive, and 12 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈16
Distinctive · estimate
This author's own choices. Worth a look.
12
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 10
Use the timeout, retry, pool, body-limit, and shutdown controls of the stack that the workspace already uses.
- Very specific: line 14
Use these skills, when they are installed, for adjacent work: rust-async-internals for select!, task ownership, cancel safety, and runtime …
- Distinctive: line 36
Do not copy timeout values from another service.
- Distinctive: line 57
Read references/stack-defaults.md when the workspace uses one of these crates: it has the reqwest 0.13 upgrade changes, working client and …
- Distinctive: line 63
Run these checks when you add or review network configuration.
- Distinctive: line 102
Use the TLS backend that the workspace already selected.
- Distinctive: line 104
Verify the certificate chain and the server name on every production connection.
- Very specific: line 112
Keep certificate and hostname bypass APIs (the rg check above lists them) out of production code paths.
- Very specific: line 117
Keep private keys out of logs and error chains.
- Distinctive: line 122
Use certificate pinning only when the product has a rotation and recovery plan.
- Distinctive: line 125
Do not force a protocol-version policy that conflicts with the platform or the service contract.
- Distinctive: line 131
Create one monotonic deadline at the operation boundary.
- Distinctive: line 135
Before each phase, calculate this duration:
- Very specific: line 158
Use tokio::time::timeout_at or the runtime equivalent when the stack does not accept a deadline directly.
- Distinctive: line 179
Use this default classification, then narrow it for the target service:
- Very specific: line 194
Do not retry every 5xx. A retry can multiply overload and repeat an application failure.
- Very specific: line 208
Use exponential backoff with full jitter.
- Distinctive: line 214
Do not sleep past the operation deadline.
- Distinctive: line 216
Keep delay calculation pure.
- Distinctive: line 224
Do not trust the declaration as the only limit.
- Distinctive: line 236
Never add an unbounded queue to hide backpressure.
- Distinctive: line 243
Stop reading after cancellation, a body-limit error, or an expired deadline.
- Very specific: line 249
Read references/cancellation.md when a caller can cancel a state-changing request, or the application must recover from an Outcome unknown …
- Very specific: line 254
Read references/proxy-and-dns.md when you key or reuse a connection pool, or configure a proxy, NO_PROXY, a resolver, or a DNS cache.
- Very specific: line 259
Read references/overload-and-shutdown.md when you set server admission, concurrency, queue, or handler-timeout limits.
- Very specific: line 264
Read references/overload-and-shutdown.md when you add or review graceful shutdown for a server or a client.
- Very specific: line 269
Read references/diagnostics.md when you add a log field, metric label, or trace attribute to network code.
- Very specific: line 274
Test policy without a real public network.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Rust Networking
Apply this policy to HTTP, gRPC, WebSocket, and custom TCP clients and servers. Use the timeout, retry, pool, body-limit, and shutdown controls of the stack that the workspace already uses. Do not replace the framework to get one middleware type.
Use these skills, when they are installed, for adjacent work:
rust-async-internals for select!, task ownership, cancel safety, and runtime
configuration; rust-observability for tracing, metrics, and exporters;
rust-security for dependency advisories and untrusted-input parser hardening.
Start from one operation contract
Record these decisions next to the client or server configuration before you tune individual settings:
| Field | Required decision |
| Operation deadline | Maximum wall-clock time for all attempts and delays |
| Phase caps | DNS, connect, write idle, first-byte, and read idle caps (see "Use one absolute deadline") |
| Retry attempts | Total attempts, including the first attempt |
| Retry eligibility | Operation semantics, replayable body, and retryable result |
| Response limit | Maximum decoded bytes accepted by the caller |
| Concurrency limit | Maximum admitted work per process, route, or upstream |
| Server header limit | Maximum header bytes, field count, and read time |
| Server idle limits | Keep-alive, request-body, and response-write idle caps |
| Shutdown grace | Maximum time allowed for accepted work to drain |
Do not copy timeout values from another service. Derive them from the caller's deadline and the service latency objective. Keep all values configurable. Give each value a finite production default when the caller does not supply one.
Set the limits the stack leaves open
Most Rust network stacks ship without the limits in the contract. An unset limit compiles and passes tests, then fails under a slow or hostile peer. Set each one explicitly:
| Stack | Default | Consequence |
reqwest 0.13 async Client | No timeout, connect_timeout, or read_timeout; pool_max_idle_per_host is usize::MAX | A stalled peer holds a request forever; the idle pool has no bound |
reqwest Response::bytes, text, json | Collect the whole body with no size limit | A large response exhausts memory |
| hyper 1.x HTTP/1 server | header_read_timeout (30 s) acts only after Builder::timer; a configured value with no timer panics | Slow-header clients hold connections |
axum::serve 0.8 | Builds its hyper builder with no timer | No header-read timeout at all |
axum with_graceful_shutdown | Waits for open connections with no deadline | One open request stalls shutdown |
tower-http TimeoutLayer::new | Deprecated since 0.6.7; answers 408 | A client can repeat even a POST that the handler already ran |
tonic 0.14 Endpoint | No connect timeout; timeout does not send grpc-timeout | The server never sees the deadline, so it cannot stop at it or pass it downstream |
| rustls 0.23 | Zero or two provider features (or custom-provider) and no installed provider | ClientConfig::builder() panics at run time |
Read references/stack-defaults.md when the workspace uses one of these crates: it has the reqwest 0.13 upgrade changes, working client and server setups, and the rustls and Android TLS setup.
Verify the configuration
Run these checks when you add or review network configuration. Review each hit; a hit is not always a defect.
rg -n --type rust 'danger_accept_invalid|tls_danger_|\.dangerous\(\)|tls_sslkeylogfile\(true\)|KeyLogFile|DefaultBodyLimit::disable|\bTimeoutLayer::new|axum::serve\(|with_graceful_shutdown\(|\breqwest::get\(|\bClient(Builder)?::(new|builder)\(\)|\.(bytes|text|json)\(\)\.await|\.json::<'
cargo tree --locked -e features -i rustls --prefix none | grep -oE '^rustls feature "(ring|aws_lc_rs|custom-provider)"' | sort -u
cargo deny --config deny.toml --locked check advisories| Check | Proves | Does not prove |
rg | Each bypass, key log, unbounded body, 408 timeout, and unbounded serve or client construction is visible | That the configured values fit the contract |
cargo tree | Which rustls provider features are on. Any output other than a single ring or aws_lc_rs line means main must install a provider | That the provider is installed before first TLS use |
cargo deny | No known vulnerability in rustls, h2, hyper, quinn, or the rest of the graph. An unsound advisory in a transitive crate fails only with unsound = "all" (the rust-security skill owns this deny.toml policy) | Protocol correctness |
A green grep does not prove the timing contract; the tests in "Test deterministic seams" do. The work is complete when each contract field and each stack-defaults row has a finite, configurable, tested value, and the TLS root source, the pool key, the outcome-unknown error state, and the diagnostics field list match their sections. In a review, each gap is a finding.
Failure triage
| Symptom | Likely cause | First check |
| Request exceeds its advertised timeout | Each retry received a fresh timeout | Trace one absolute deadline across attempts |
| POST executes twice | Method-only retry policy | Check idempotency and body replayability |
| Retry storm during outage | No jitter, no attempt cap, or ignored Retry-After | Inspect delay and total attempt metrics |
| TLS works only in development | Production root source differs or verifier bypass leaks into tests | Print root source and certificate error class |
| Requests use the old endpoint | Live pooled connection survives DNS change | Compare pool reuse and connect events |
| Memory grows under slow clients | Body collection or unbounded queue | Inspect decoded-byte and queue limits |
| HTTP/2 overloads the service | Connection limit is used as request limit | Inspect in-flight streams and route permits |
| Shutdown never finishes | New work is still admitted, each step resets grace, or axum with_graceful_shutdown has no outer deadline | Trace admission close and one deadline |
| Slow clients exhaust server connections | axum::serve or a hyper builder without a timer has no header-read timeout | Send a partial header and time the close |
| Panic "Could not automatically determine the process-level CryptoProvider" | Zero or two provider features (or custom-provider) and no installed provider | Run the cargo tree check; install one provider in main |
| Metrics leak user data | Raw URI, header, or error text is a label | Apply the closed field vocabulary |
Keep TLS verification on
Use the TLS backend that the workspace already selected. Apply these rules:
- Verify the certificate chain and the server name on every production connection.
- Load trust roots from one explicit source. Choose the platform store when the
product must honor managed enterprise roots. Choose a bundled store when the
product requires the same roots on every target. A reqwest 0.12
rustls-tlsbuild (bundled webpki roots) silently moves to the platform verifier on 0.13; calltls_certs_only(roots)to keep a bundled or private set. - Fail startup or client construction when the required root store is empty.
- Keep certificate and hostname bypass APIs (the
rgcheck above lists them) out of production code paths. A test verifier must not be reachable from runtime configuration. - Send SNI for a DNS name. Verify the original service name, not the resolved IP address.
- Keep private keys out of logs and error chains. Never enable key logging in
production: reqwest
tls_sslkeylogfile(true)and rustlsKeyLogFilewrite session secrets to the file thatSSLKEYLOGFILEnames. - Rebuild the client and drain old pooled connections after a trust-root, client-certificate, or private-key rotation.
- Use certificate pinning only when the product has a rotation and recovery plan. Ship at least one backup identity before the active identity changes.
Do not force a protocol-version policy that conflicts with the platform or the service contract. Use the secure defaults of the maintained TLS backend. Raise the minimum only when the deployment matrix proves that every peer supports it.
Use one absolute deadline
Create one monotonic deadline at the operation boundary. Carry it through DNS, connect, proxy negotiation, TLS, every request attempt, response streaming, and retry delay. Do not restart the full timeout after a retry.
Before each phase, calculate this duration:
phase allowance = min(configured phase cap, operation deadline - monotonic now)Fail before the phase starts when no time remains. Report which phase consumed
the budget. Do not report every deadline failure as connect timeout. Read
references/deadlines-and-retries.md when
you set the phase caps: it gives the start, the end, and the failure mode of
each cap.
On a server, start the header-read deadline when the connection is accepted. A slow client must not hold an accepted-connection slot without completing a bounded header.
An idle timeout is not a total transfer timeout. Reset it only after useful
progress. A peer that sends one byte before every idle timeout can still consume
the operation deadline, so enforce both. With tower-http, pair
RequestBodyTimeoutLayer (idle) with RequestBodyDeadlineLayer (total,
tower-http 0.7+). With reqwest, pass the remaining time to
RequestBuilder::timeout on every attempt.
Use tokio::time::timeout_at or the runtime equivalent when the stack does not
accept a deadline directly. Dropping the timed future cancels it, so check its
cancel safety.
Retry only a safe operation
Retry only when all three conditions hold:
- The operation is idempotent by protocol semantics or by an application idempotency key that the server stores atomically.
- The complete request can be replayed byte for byte. A consumed stream is not replayable unless the caller can open a fresh stream.
- The failure is transient and the operation deadline can hold another attempt plus its delay.
HTTP GET, HEAD, PUT, DELETE, OPTIONS, and TRACE have idempotent
method semantics. Application behavior can still make an operation unsafe to
repeat. Do not infer replay safety from the method name alone. Do not retry
POST unless the application contract provides idempotency or proves that the
server did not apply the request.
Use this default classification, then narrow it for the target service:
| Result | Automatic retry |
| DNS temporary failure | Yes, if another attempt fits |
| Connect refused, reset, or timeout | Yes, for an eligible operation |
| Connection closes before response headers | Yes, for an eligible operation |
HTTP 408, 429, 502, 503, or 504 | Yes, when service policy permits it |
HTTP Retry-After | Wait at least the valid server delay, within the deadline |
Other 4xx | No |
| TLS certificate or hostname failure | No |
| Request encode or validation failure | No |
| Body stream failed after response headers | No by default |
| Cancellation or exhausted deadline | No |
Do not retry every 5xx. A retry can multiply overload and repeat an
application failure. Keep the retry status set explicit.
Count the first request as attempt one. Use a small finite attempt limit. Cap retries again with the operation deadline. Never retry forever in a background task.
Also bound retries per upstream across the process. Require a retry permit or
token before a second attempt. Limit retry concurrency, and suppress retries
when the local service is overloaded or the upstream failure rate crosses the
configured threshold. If no retry budget remains, return the original failure
instead of adding outage load. tower::retry::budget::TpsBudget implements
such a budget for a tower stack.
Use exponential backoff with full jitter. Let base be the first cap and
maximum be the largest cap. For retry number n, starting at zero, select a
uniform delay in 0 ..= min(maximum, base * 2^n).
Parse both Retry-After forms: delay seconds and HTTP date. Reject invalid or
negative values. Use the larger of the server delay and the local jitter delay.
Do not sleep past the operation deadline. Clamp arithmetic to prevent overflow.
Keep delay calculation pure. Pass the random sample and current time into it. This seam makes retry tests deterministic without a mock HTTP framework. Read references/deadlines-and-retries.md when you write the delay function: it has a tested implementation.
Stream with hard limits and backpressure
Reject a declared body length that exceeds the route limit before allocation. Do not trust the declaration as the only limit. Count actual decoded bytes as chunks arrive, and stop when the count exceeds the limit.
Apply limits to the representation that the application consumes. A small compressed body can expand into a large decoded body. If the stack exposes both wire and decoded sizes, limit and record both.
Process large bodies as streams. Do not call a collect-to-bytes helper unless
the route limit is small enough to allocate safely. On a server, use
http_body_util::Limited, axum::body::to_bytes(body, limit), or a per-route
DefaultBodyLimit::max(n). Put a bounded channel between network reads and a
slower consumer. Await capacity or cancel the request when the channel is full.
Never add an unbounded queue to hide backpressure.
For uploads, make replayability explicit. A byte buffer is replayable. A file is replayable only when each attempt opens a new handle and starts at the same offset. A live channel, socket, decoder, or one-shot generator is not replayable.
Stop reading after cancellation, a body-limit error, or an expired deadline. Release or reset the protocol stream as the library requires. Do not return a connection to the pool when its protocol state is uncertain.
Define cancellation at the network boundary
Read references/cancellation.md when a caller can cancel a state-changing
request, or the application must recover from an Outcome unknown result.
Treat proxy and DNS as connection identity
Read references/proxy-and-dns.md when you key or reuse a connection pool,
or configure a proxy, NO_PROXY, a resolver, or a DNS cache.
Bound server overload
Read references/overload-and-shutdown.md when you set server admission,
concurrency, queue, or handler-timeout limits.
Shut down in a fixed order
Read references/overload-and-shutdown.md when you add or review graceful
shutdown for a server or a client.
Emit safe network diagnostics
Read references/diagnostics.md when you add a log field, metric label, or
trace attribute to network code.
Test deterministic seams
Test policy without a real public network. Read references/test-seams.md
when you write a network policy test: it maps each control to the smallest
seam that exposes it, and gives the paused-clock and test-run rules.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

