Skip to main content

Module rest

Module rest 

Source
Expand description

Slack Web API REST client — apps.connections.open (Socket Mode URL fetch) + chat.postMessage for outbound delivery.

Rate limiting: v1 implements only per-channel ~1msg/s spacing (enforced by the caller in socket.rs’s outbound loop) and reactive 429/Retry-After backoff. Full token-bucket accounting for every documented Slack API tier is explicitly out of scope (spec §2.6) — mirrors Discord’s and Telegram’s rest.rs, neither of which does header-driven throttling beyond reacting to a rate-limit signal.

Secret-in-error-message hygiene: both Slack tokens (xoxb-/xapp-) are sent as Authorization: Bearer headers, never embedded in request URLs — unlike Telegram’s bot{token} path convention — so reqwest::Error’s Display (which can embed request URLs on connection failures) does not leak either token via that vector, and no redact()-style scrubbing of reqwest::Error text is needed here the way telegram/rest.rs needs it. The one Slack-specific value that is both URL-embedded and secret is the Socket Mode WS URL’s ticket= query param returned by apps.connections.open: it’s a single-use, short-lived credential (spec §2.1, §9.6). We never pass that URL through this module’s error paths (the WS connect happens in socket.rs), but we still provide redact_ticket here so any code that logs the URL (today: one debug! call in socket.rs) redacts it first — unnecessary exposure in a log that can persist long past the ticket’s few-seconds validity window is not worth the convenience of an unredacted log line.

Structs§

SlackApiError
Error from a Slack Web API call, carrying the Retry-After seconds when present (429 responses only — Slack signals rate limits via the HTTP header, not a response-body field like Telegram’s parameters.retry_after — spec §2.6).

Constants§

REQUEST_TIMEOUT_SECS 🔒
SLACK_API 🔒

Functions§

open_connection
POST apps.connections.open — Authorization: Bearer {app_token}. Returns the ephemeral Socket Mode WS URL. Must be called before the initial connect and before every reconnect (spec §2.1) — the URL is single-use and short-lived; never cache/reuse it.
parse_retry_after 🔒
Parses an HTTP Retry-After header value (seconds, per RFC 9110 — Slack always sends the delta-seconds form, never the HTTP-date form).
post_message
POST chat.postMessage — Authorization: Bearer {bot_token}. MUST check body.ok, not just HTTP status: Slack’s REST responses are HTTP 200 even on many logical failures (e.g. channel_not_found, not_in_channel) — spec §2.4.
post_response_url
POST to a slash-command response_url. Stub for the deferred-response path (spec §2.5, §4.3) — not called anywhere in v1 scope; slash commands are explicitly out of scope for this PR. Kept so the module shape doesn’t need rework when they land.
redact_ticket
Redacts the single-use ticket query param from a Socket Mode WS URL before it’s ever logged (spec §9.6). Leaves the rest of the URL (host, app_id, path) intact since that part isn’t secret and is useful for debugging connection issues.