resq¶
resq is a dual-mode HTTP client library: one set of verbs, with the mode and
engine selected by the adapter argument — 'requests' for synchronous calls,
'httpx' for asynchronous ones.
The package exposes exactly two names from the top level, and that is the recommended way to use it:
Requests— HTTP client, fresh connection per call in sync mode.Session— HTTP client with a persistent sync connection reused across calls.
The response wrappers (Response / AsyncResponse) and the polling routine (poll) are
not re-exported here. Reach them through the resq.http submodule only when needed —
see The resq.http surface.
Quick sync request¶
Two different timeouts
The constructor timeout is the network timeout (connect/read), set once. It is
NOT the polling window.
from resq import Requests
with Requests("https://api.example.com", adapter="requests", timeout=5) as client:
r = client.get("/users/42", params={"detail": "full"})
print(r.status_code, r.ok) # int, bool
data = r.json() # parsed body
Every verb forwards keyword arguments (params, headers, json, data, …) verbatim
to the underlying engine.
Quick async request¶
The same verbs run on a long-lived httpx client and must be awaited. Release it with
async with (preferred) or await client.close():
from resq import Session
async with Session("https://api.example.com", adapter="httpx", timeout=5) as client:
r = await client.get("/users/42")
data = r.json()
Polling for a success status¶
Pass a timeout on the method to poll until a 2xx response arrives. This is a
different timeout from the constructor one — same name, different meaning by position:
from resq import Requests
client = Requests("https://api.example.com", adapter="requests", timeout=5) # network
r = client.get("/job/42", timeout=30, delay=2) # poll up to 30s
Async is identical, awaited (adapter='httpx'). See Polling.
Handling window exhaustion¶
If the polling window elapses without a success-status response, the LAST response is
returned (its status is the final non-2xx) — no exception. Inspect ok /
status_code, or call reload to retry:
from resq import Requests
client = Requests("https://api.example.com", adapter="requests", timeout=5)
r = client.get("/job/42", timeout=30, delay=2)
if not r.ok:
r.reload() # sync; await r.reload() for an AsyncResponse
Requests vs Session¶
Requests— a fresh connection per sync call (module-levelrequestsbehavior). Pick it for one-off calls or when you do not need cookie/connection persistence.Session— one persistentrequests.Sessionreused across sync calls (shared pool and cookie jar). Pick it for repeated calls to the same host.
In async mode both flavors behave identically: each instance owns one long-lived
httpx.AsyncClient, shared across that instance's calls and reloads. Release it via
async with or await client.close().
Where to go next¶
- Clients & requests — construction, all verbs, sync and async lifecycles.
- Reading a response — the unified attribute surface.
- Reload — re-executing a request in place.
- Polling — the polling window semantics.
Behavior & preconditions¶
adapterselects mode+engine:'requests'(sync) or'httpx'(async); other values raiseValueError. Fixed per instance.- Constructor
timeout= network timeout (connect/read), set once; method-leveltimeout= polling window. Same name, different meaning by position. - With the method
timeoutleft atNone(default), a verb issues a single request and does not auto-raise on a non-2xx status — inspectr.okor callr.raise_for_status(). - Verb names are the same in both modes; in async mode they must be awaited.
- The facade re-exports only
RequestsandSession; the wrappers andpolllive inresq.httpfor advanced typing.