QBittorrent::Client
HTTP client for the qBittorrent WebUI API v2 (qBittorrent 5.x).
Authentication is cookie/session based, not an API key. On the first
authenticated request (or an explicit #login) the client posts the
credentials to auth/login, captures the session cookie, and attaches it —
together with a Referer/Origin header matching the server host — to
every subsequent call.
The session-cookie name is dynamic on real 5.x builds: it is
QBT_SID_<port> (e.g. QBT_SID_8080), not the SID name older docs
describe. The client therefore stores both the cookie name and value
and echoes them verbatim. Sessions expire (server default 3600 s); a 403
from an authenticated call triggers a single transparent re-login + retry.
client = QBittorrent::Client.new("http://localhost:8080", "admin", "adminadmin")
body = client.request_text("GET", "app/version") # => "v5.2.3"
client.logout
Endpoint groups (app, torrents, ...) are built on top of the request
helpers below (#request, #request_text, #request_json).
Constants
Common path prefix for every WebUI API v2 method.
Constructors
Class methods
Builds a multipart/form-data body from form fields and files parts.
Returns {content_type, body} where content_type is the
multipart/form-data; boundary=... header value and body is the encoded
bytes. Pure (no I/O beyond the in-memory buffer) so the encoding is
unit-testable without a server.
Builds the full request path (/api/v2/<path> plus an optional encoded
query string). path may be given with or without a leading slash.
Extracts the session cookie as {name, value} from the Set-Cookie
headers of a login response, or nil if none was set. Prefers the cookie
whose name starts with QBT_SID (the real 5.x session cookie, e.g.
QBT_SID_8080); otherwise falls back to the first cookie set.
Interprets a raw auth/login response. Returns the session cookie as
{name, value} on success; raises AuthError for every failure mode.
Pure (no I/O) so the auth decision logic is unit-testable without a server.
Success is any 2xx status (real 5.x: 204, empty body; legacy:
200 Ok.) that also sets a session cookie — the Ok. body is NOT
required. Failures: HTTP 401 or legacy 200 Fails. (bad credentials);
HTTP 403 (banned IP / host-header check); a 2xx with no cookie.
Derives the Referer/Origin value (scheme://host[:port]) from uri.
Instance methods
Performs POST auth/login, storing the session cookie on success.
Success on real 5.x is HTTP 204 with an empty body that sets a
QBT_SID_<port> cookie; older builds answer 200 Ok.. Both are accepted.
Raises AuthError on wrong credentials (HTTP 401, or the legacy
200 Fails.), a 2xx response with no session cookie, or HTTP 403
(banned IP / failed host-header validation).
Core request primitive used by the endpoint groups.
Ensures a session exists (logging in on demand), attaches the session
cookie and Referer/Origin headers, sends query as a URL query string
and form as an application/x-www-form-urlencoded body, and returns the
raw HTTP::Client::Response.
On a 403 (expired/invalidated session) it re-logs-in once and
retries. Any remaining non-2xx response raises ApiError carrying the
status code and body.
Like #request but deserializes the JSON body into type.
info = client.request_json(BuildInfo, "GET", "app/buildInfo")
Like #request but sends a multipart/form-data body — required by
endpoints that accept file uploads (notably torrents/add with .torrent
files). form carries the plain text fields and files the file parts as
fieldname => {filename:, content:}. Shares the session/login handling of
#request (a 403 triggers a single re-login + retry) and raises
ApiError on any non-2xx response.