Documentation
¶
Overview ¶
Package typhoeus is a pure-Go (CGO-free) reimplementation of the client model of Ruby's `typhoeus` gem — the parallel HTTP client that, in Ruby, drives libcurl (via Ethon) to run many requests concurrently. Here the same object model (Request, Response, Hydra, the one-shot verb helpers, on-complete callbacks and the libcurl-style return codes) is backed by Go's net/http and goroutines instead of libcurl, with no cgo and no libcurl dependency.
What it is — and isn't ¶
Everything Typhoeus models around the wire is deterministic and needs no interpreter and no libcurl, so it lives here as pure Go: the Request with its Options (params, body, headers, userpwd, timeout, followlocation), the on-complete callbacks, the Response (code, body, headers, total_time, success?/timed_out?, return_code), and — the gem's signature feature — the parallel Hydra runner that executes a queue of requests concurrently with a bounded max-concurrency and fires their callbacks.
The HTTP round-trip itself is a host seam: a Transport performs the transfer. The default production Transport is NetHTTP, backed by net/http; tests inject a TransportFunc stub, so the deterministic suite drives the whole model — including the Hydra's parallelism — without opening a socket, and the concrete net/http mapping (libcurl return-code classification, redirect and timeout policy) is exercised through the same seam. This mirrors the gem, whose Ethon adapter is the only piece that touches the network.
One-shot ¶
resp := typhoeus.Get("https://api.example.com/widgets",
typhoeus.Options{Params: typhoeus.ParamsOf([2]string{"q", "go ruby"})})
_ = resp.Code // 200
_ = resp.Body // response body string
_ = resp.Success() // true for a 2xx with return_code == :ok
Parallel (Hydra) ¶
hydra := typhoeus.NewHydra(typhoeus.HydraOptions{MaxConcurrency: 5})
for _, u := range urls {
req := typhoeus.NewRequest(u, "GET")
req.OnComplete(func(r *typhoeus.Response) { collect(r) })
hydra.Queue(req)
}
hydra.Run() // runs them concurrently, then fires callbacks in queue order
Value model ¶
Query params and url-encoded form bodies are carried as an ordered string→string Params; headers as a case-insensitive ordered Headers. A host (go-embedded-ruby / rbgo) maps its Ruby Typhoeus::Request / Response / Hydra objects to and from these shapes.
Index ¶
Constants ¶
const DefaultMaxConcurrency = 200
DefaultMaxConcurrency is the number of requests a Hydra runs at once when no MaxConcurrency is given, matching Typhoeus::Hydra's default of 200.
Variables ¶
This section is empty.
Functions ¶
func BuildQuery ¶
BuildQuery renders params as an application/x-www-form-urlencoded query string: the params are emitted in insertion order (Typhoeus preserves the params' order rather than sorting) and each key and value is run through Escape.
Types ¶
type Headers ¶
type Headers struct {
// contains filtered or unexported fields
}
Headers is a case-insensitive, insertion-ordered header map used for a request's outgoing headers and a response's headers. A lookup matches keys case-insensitively while the original casing of the first-seen key is preserved for iteration and display (so "Content-Type" and "content-type" address the same entry), mirroring the header hash Typhoeus surfaces on a response.
func (*Headers) Delete ¶
Delete removes key (case-insensitive) if present, keeping the order of the remaining headers.
type Hydra ¶
type Hydra struct {
// contains filtered or unexported fields
}
Hydra is the parallel runner — Typhoeus's signature feature. Requests are queued with Hydra.Queue and executed by Hydra.Run, which runs them concurrently (bounded by MaxConcurrency) and then fires each request's on-complete callbacks in queue order, mirroring Typhoeus::Hydra.
A Hydra is not safe for concurrent use by multiple goroutines; queue from one goroutine and call Run. Run itself is where the parallelism happens.
func NewHydra ¶
func NewHydra(opts ...HydraOptions) *Hydra
NewHydra builds a Hydra, mirroring Typhoeus::Hydra.new. With no options (or MaxConcurrency <= 0) it uses DefaultMaxConcurrency.
func (*Hydra) Abort ¶
func (h *Hydra) Abort()
Abort stops the hydra from starting further rounds, mirroring Typhoeus::Hydra#abort. Requests already in flight in the current round finish.
func (*Hydra) Queue ¶
Queue adds a request to the hydra, mirroring Typhoeus::Hydra#queue. A request may also be queued from within an on-complete callback during Hydra.Run; it is run in a following round.
func (*Hydra) QueuedCount ¶
QueuedCount reports how many requests are currently queued (Typhoeus::Hydra#queued_requests size).
func (*Hydra) Run ¶
func (h *Hydra) Run()
Run executes the queued requests concurrently and then fires their on-complete callbacks in queue order, mirroring Typhoeus::Hydra#run. It blocks until every request in flight has completed — no goroutine outlives the call — and returns once the queue is drained (or Hydra.Abort was called).
Concurrency is bounded to MaxConcurrency by a semaphore; each request writes only its own slot of the results slice, and Run waits for the whole round before reading any result, so the transports run in parallel without a data race and without a leaked goroutine. Callbacks then run on the calling goroutine, in queue order, so results are deterministic; a callback may queue more requests, which are executed in the next round.
type HydraOptions ¶
type HydraOptions struct {
// MaxConcurrency bounds how many queued requests run at once; <= 0 selects
// [DefaultMaxConcurrency].
MaxConcurrency int
}
HydraOptions configures a Hydra, mirroring Typhoeus::Hydra.new(max_concurrency:).
type NetHTTPTransport ¶
type NetHTTPTransport struct {
// contains filtered or unexported fields
}
NetHTTPTransport is the default Transport: it turns a Request into a net/http request, executes it under an http.Client configured from the request's Options (timeout and redirect policy), and maps the response — or a transport failure — onto a Response, classifying a failure into a libcurl ReturnCode.
func NetHTTP ¶
func NetHTTP() *NetHTTPTransport
NetHTTP returns the default net/http-backed Transport.
func (*NetHTTPTransport) Run ¶
func (t *NetHTTPTransport) Run(req *Request) *Response
Run performs the HTTP round-trip for req with net/http.
type Options ¶
type Options struct {
// Params are query parameters appended to the URL (curl-escaped, ordered).
Params *Params
// Body is the request body: a string sent verbatim, a [*Params] form-encoded
// as application/x-www-form-urlencoded, nil for no body, or any other value
// rendered with fmt.Sprint.
Body any
// Headers are the outgoing request headers.
Headers *Headers
// UserPwd is the HTTP Basic credential as "login:password" (curl's :userpwd);
// when set it becomes an Authorization: Basic header.
UserPwd string
// Timeout is the overall transfer timeout; 0 means no timeout.
Timeout time.Duration
// FollowLocation, when true, follows 3xx redirects (curl's :followlocation).
// When false the redirect response is returned as-is.
FollowLocation bool
// MaxRedirects caps the number of redirects to follow when FollowLocation is
// true (curl's :maxredirs); 0 leaves the transport default.
MaxRedirects int
}
Options carries the per-request settings, mirroring the options Hash passed to Typhoeus::Request.new(url, method:, params:, body:, headers:, userpwd:, timeout:, followlocation:). Every field is optional; the zero value requests a plain transfer with the transport's defaults.
type Params ¶
type Params struct {
// contains filtered or unexported fields
}
Params is an insertion-ordered string→string map used for request query parameters and url-encoded form bodies. Ruby's Typhoeus threads plain Hashes through the flow; this ordered map mirrors that, giving deterministic, order-preserving output for query strings (see BuildQuery).
func ParamsOf ¶
ParamsOf builds a Params from ordered key/value pairs (later duplicates overwrite earlier values, keeping the first position — Ruby Hash semantics).
func ParseQuery ¶
ParseQuery decodes an application/x-www-form-urlencoded query string into an ordered Params: each key and value is [Unescape]d, a bare key (no '=') maps to the empty string, an empty segment is skipped, and a later duplicate key overwrites an earlier one (keeping its position). A leading '?' is ignored.
func (*Params) Encode ¶
Encode renders the params as an order-preserving, curl-escaped query string (see BuildQuery).
type Request ¶
type Request struct {
// Method is the upper-case HTTP method ("GET", "POST", …).
Method string
// URL is the request URL (query params from Options are appended to it).
URL string
// Options are the per-request settings.
Options Options
// Transport, when non-nil, overrides [DefaultTransport] for this request — the
// injectable seam tests use to avoid the network.
Transport Transport
// contains filtered or unexported fields
}
Request is a single HTTP request, mirroring Typhoeus::Request: a method, a URL, the per-request Options, and any number of on-complete callbacks. Run it directly with Request.Run, or queue it on a Hydra to run in parallel with others.
func NewRequest ¶
NewRequest builds a Request for url with the given method and optional Options, mirroring Typhoeus::Request.new. The method is upper-cased.
func (*Request) OnComplete ¶
OnComplete registers a callback fired with the Response when the request finishes, mirroring Typhoeus::Request#on_complete. Callbacks run in registration order.
type Response ¶
type Response struct {
// Code is the HTTP status code (Response#code / #response_code); 0 when the
// transfer never produced a status (a connection/timeout failure).
Code int
// Body is the response body (Response#body).
Body string
// Headers are the response headers (Response#headers).
Headers *Headers
// TotalTime is the wall-clock duration of the transfer in seconds
// (Response#total_time).
TotalTime float64
// ReturnCode is the libcurl return code (Response#return_code): [ReturnOK] on
// success, otherwise the failure mode.
ReturnCode ReturnCode
// contains filtered or unexported fields
}
Response is the result of a transfer, mirroring Typhoeus::Response. A Response is always produced — even for a failed transfer, where Code is 0 and ReturnCode names the libcurl failure (see ReturnCode).
func Get ¶
Get performs a one-shot GET, mirroring Typhoeus.get(url, options). It builds a Request, runs it through DefaultTransport (firing any callbacks the request would carry), and returns the Response.
func (*Response) Request ¶
Request returns the Request that produced this response (Typhoeus::Response#request).
func (*Response) ReturnMessage ¶
ReturnMessage returns the human-readable return-code name (Response#return_message), e.g. "ok" or "couldnt_connect".
type ReturnCode ¶
type ReturnCode int
ReturnCode is the libcurl transfer result Typhoeus exposes as Response#return_code (a Ruby Symbol such as :ok or :operation_timedout). A successful transfer is ReturnOK; every failure mode maps to a specific code, so a failed request still yields a Response (with Code 0) rather than an error — mirroring libcurl, where failures are return codes, not exceptions.
const ( // ReturnOK is a completed transfer (CURLE_OK, :ok). ReturnOK ReturnCode = iota // ReturnCouldntResolveHost is a DNS resolution failure // (CURLE_COULDNT_RESOLVE_HOST, :couldnt_resolve_host). ReturnCouldntResolveHost // ReturnCouldntConnect is a connection failure // (CURLE_COULDNT_CONNECT, :couldnt_connect). ReturnCouldntConnect // ReturnOperationTimedout is a timeout (CURLE_OPERATION_TIMEDOUT, // :operation_timedout). ReturnOperationTimedout // ReturnRecvError is a failure receiving the response body // (CURLE_RECV_ERROR, :recv_error). ReturnRecvError // ReturnInternalError is a request that could not be built at all // (an invalid method or URL); Typhoeus reports such a handle as // :internal_error. ReturnInternalError )
The return codes modelled here, named after the libcurl CURLcode symbols Typhoeus surfaces.
func (ReturnCode) String ¶
func (c ReturnCode) String() string
String returns the libcurl symbol name for the code (e.g. "operation_timedout"), matching the Symbol Typhoeus returns from Response#return_code. An unknown code renders as "unknown".
type Transport ¶
Transport is the host seam that performs a request's HTTP round-trip, the role libcurl plays for Typhoeus via Ethon. Given a Request, a Transport performs the transfer and returns the Response — including the failure case, which is reported as a Response with a non-OK ReturnCode rather than an error, exactly as libcurl reports a CURLcode.
The default production Transport is NetHTTP, backed by net/http. The model opens no socket itself: every request runs through whatever Transport is set, so tests inject a stub (see TransportFunc) and the deterministic suite — the Hydra parallelism included — never touches the network.
type TransportFunc ¶
TransportFunc adapts a function to the Transport interface, the convenient way to inject a stub transport in tests or a custom transport in a host.
