SuperAPI AI Directory

reqwest

Coding & development

View repository

Updated 10-15 20:32

About this skill

reqwest

A Client cloneable, created at boot. Not reqwest::get per request (no pool, no timeout). Runtime: tokio. Signed webhooks: webhooks. Contracts: api-design. Tests: rust-unit-testing (fake or wiremock if the crate already has it).

Non-negotiable rules

  • Client in the AppState (or OnceLock in the binary). Clone is cheap (handle).
  • Timeouts: connect + timeout total in the builder (and/or per request). No eternal hang.
  • Retry only on network / 429 / 5xx with backoff and cap. Do not retry 4xx business.
  • JSON: serde types. Status ≠ 2xx → AppError mapped, not unwrap in the json().await.
  • Do not log body with token/PII (tracing).

Client

let client = reqwest::Client::builder()
    .timeout(Duration::from_secs(10))
    .connect_timeout(Duration::from_secs(3))
    .user_agent("myapp/1.0")
    .build()?;
  • TLS: default (rustls or native-tls from Cargo.toml). Do not disable verify in prod.
  • HTTP/2: leave the crate default unless the partner requires it.
  • Redirect: limit; outbound webhooks (webhooks) — beware SSRF (private IPs) if the URL is user-supplied.

In Axum

async fn proxy(
    State(st): State<AppState>,
    Path(id): Path<Uuid>,
) -> Result<Json<Dto>, AppError> {
    let res = st.http.get(url).send().await?;
    let status = res.status();
    let dto = res.json::<Dto>().await?;
    // mapeie status
}
  • error_for_status or explicit match. bytes() for HMAC signature (raw body).
  • Cancel: dropping the future on request abort cancels the I/O — do not ignore JoinHandle of a loose spawn.

Retries

  • Idempotent: GET, PUT with idempotency-key. POST payment: do not blind retry.
  • Jitter + cap. Circuit: only if the repo already has it (do not invent Hystrix).
  • background-jobs for slow fan-out; the handler does not wait 30s for a partner.

Anti-patterns

  • reqwest::get(url).await? in a loop (new client)
  • expect("http") on the hot path
  • Retry on 400/409
  • Trust Content-Type without serde
  • Mutable global Client reconfigured in the handler

Integration with other skills

  • Runtime: tokio
  • Logs/spans: tracing
  • HTTP app: axum
  • Callbacks: webhooks
  • Production: rust-axum-production (server timeouts ≠ client timeouts)

Completion criteria

  • One Client in state; timeouts defined
  • HTTP errors mapped; typed JSON
  • Retry only transient; critical POST without blind replay
  • No PII in the log
  • SSRF aware if the URL is input