Documentation
¶
Overview ¶
Package faraday is a pure-Go (CGO-free) reimplementation of the deterministic core of Ruby's `faraday` gem — the ubiquitous middleware-based HTTP client abstraction: the connection builder, the request/response objects, the middleware stack (request and response middleware plus the adapter), and the URL/params/headers/body handling that Faraday performs around a transport.
What it is — and isn't ¶
Everything Faraday does *around* the wire is deterministic and needs no interpreter, so it lives here as pure Go: building the request URL (path resolution against the base URL, order-preserving escaped query strings), running the request through the middleware stack (url-encoded and JSON body encoding, Basic and token authorization, JSON response parsing, status→error mapping, logging), and exposing the Response. The HTTP round-trip itself is a host seam: the terminal Doer (the adapter) performs the transport. The default production Doer is NetHTTP, backed by net/http; tests inject a DoerFunc stub, and the core opens no socket itself. This mirrors the gem, whose adapter is the last middleware and the only piece that touches the network.
Flow ¶
conn := faraday.New(faraday.Options{
URL: "https://api.example.com",
Headers: faraday.HeadersOf([2]string{"Accept", "application/json"}),
}, func(c *faraday.Connection) {
c.Request("json") // encode a struct/map body as JSON
c.Request("authorization", "Bearer", "the-token")
c.Response("json") // parse a JSON response body
c.Response("raise_error") // map 4xx/5xx to a Faraday error
c.Adapter(faraday.NetHTTP()) // transport seam (a stub in tests)
})
resp, err := conn.Post("/widgets", map[string]any{"name": "gadget"},
func(req *faraday.Request) { req.SetParam("verbose", "1") })
if err != nil { /* a Faraday.Error: ResourceNotFound, ServerError, … */ }
_ = resp.Status() // 201
_ = resp.Body() // parsed JSON value
_ = resp.Success() // true for 2xx
Value model ¶
Query params and url-encoded bodies are carried as an ordered string→string Params; headers as a case-insensitive ordered Headers. A request body is an arbitrary value that the request middleware encode (a *Params for a form, any value for JSON) into the string the adapter sends. A host (go-embedded-ruby / rbgo) maps its Ruby Faraday::Connection / Request / Response / Env objects to and from these shapes.
Index ¶
- Variables
- func BasicHeaderFrom(login, password string) string
- func BuildQuery(params *Params) string
- func Escape(s string) string
- func IsClientError(err error) bool
- func IsServerError(err error) bool
- func Unescape(s string) string
- type Builder
- type Connection
- func (c *Connection) Adapter(d Doer)
- func (c *Connection) BuildRequest(method, path string, body any, headers *Headers, block func(*Request)) *Request
- func (c *Connection) BuildURL(path string, params *Params) string
- func (c *Connection) Delete(path string, block ...func(*Request)) (*Response, error)
- func (c *Connection) Get(path string, block ...func(*Request)) (*Response, error)
- func (c *Connection) Head(path string, block ...func(*Request)) (*Response, error)
- func (c *Connection) Headers() *Headers
- func (c *Connection) Options(path string, block ...func(*Request)) (*Response, error)
- func (c *Connection) Params() *Params
- func (c *Connection) Patch(path string, body any, block ...func(*Request)) (*Response, error)
- func (c *Connection) Post(path string, body any, block ...func(*Request)) (*Response, error)
- func (c *Connection) Put(path string, body any, block ...func(*Request)) (*Response, error)
- func (c *Connection) Request(name string, args ...string)
- func (c *Connection) Response(name string, w ...io.Writer)
- func (c *Connection) RunRequest(method, path string, body any, headers *Headers, block func(*Request)) (*Response, error)
- func (c *Connection) Trace(path string, block ...func(*Request)) (*Response, error)
- func (c *Connection) URLPrefix() string
- func (c *Connection) Use(m Middleware)
- type Doer
- type DoerFunc
- type Env
- type Error
- type ErrorKind
- type Handler
- type Headers
- func (h *Headers) Clone() *Headers
- func (h *Headers) Delete(key string)
- func (h *Headers) Get(key string) (string, bool)
- func (h *Headers) Has(key string) bool
- func (h *Headers) Len() int
- func (h *Headers) Merge(other *Headers) *Headers
- func (h *Headers) Pairs() []Pair
- func (h *Headers) Set(key, val string)
- func (h *Headers) SetDefault(key, val string)
- type Middleware
- type NetHTTPDoer
- type Options
- type Pair
- type Params
- func (p *Params) Clone() *Params
- func (p *Params) Delete(key string)
- func (p *Params) Encode() string
- func (p *Params) Get(key string) (string, bool)
- func (p *Params) Has(key string) bool
- func (p *Params) Len() int
- func (p *Params) Merge(other *Params) *Params
- func (p *Params) Pairs() []Pair
- func (p *Params) Set(key, val string)
- type Request
- type RequestOptions
- type Response
Constants ¶
This section is empty.
Variables ¶
var ( ErrError = &Error{Kind: KindError, Message: string(KindError)} ErrClientError = &Error{Kind: KindClientError, Message: string(KindClientError)} ErrBadRequest = &Error{Kind: KindBadRequest, Message: string(KindBadRequest)} ErrForbidden = &Error{Kind: KindForbidden, Message: string(KindForbidden)} ErrResourceNotFound = &Error{Kind: KindResourceNotFound, Message: string(KindResourceNotFound)} ErrProxyAuth = &Error{Kind: KindProxyAuth, Message: string(KindProxyAuth)} ErrConflict = &Error{Kind: KindConflict, Message: string(KindConflict)} ErrUnprocessableEntity = &Error{Kind: KindUnprocessableEntity, Message: string(KindUnprocessableEntity)} ErrTooManyRequests = &Error{Kind: KindTooManyRequests, Message: string(KindTooManyRequests)} ErrServerError = &Error{Kind: KindServerError, Message: string(KindServerError)} ErrNilStatus = &Error{Kind: KindNilStatus, Message: string(KindNilStatus)} ErrConnectionFailed = &Error{Kind: KindConnectionFailed, Message: string(KindConnectionFailed)} ErrTimeout = &Error{Kind: KindTimeout, Message: string(KindTimeout)} ErrSSL = &Error{Kind: KindSSL, Message: string(KindSSL)} ErrParsing = &Error{Kind: KindParsing, Message: string(KindParsing)} )
Sentinel errors for errors.Is matching. Each names a Faraday error kind; a concrete Error with that Kind (or a subtree of it) matches via Error.Is.
Functions ¶
func BasicHeaderFrom ¶
BasicHeaderFrom returns the Basic Authorization header value for a login and password, mirroring Faraday::Utils.basic_header_from: "Basic " followed by the newline-free base64 of "login:password".
func BuildQuery ¶
BuildQuery renders params as an application/x-www-form-urlencoded query string, byte-faithful to Faraday::Utils.build_query: the params are emitted in insertion order (Faraday preserves the params' order rather than sorting) and each key and value is run through Escape.
func Escape ¶
Escape percent-encodes s the way Faraday::Utils.escape does: the unreserved set [A-Za-z0-9 .\-_~] is left literal except that a space is rewritten to '+', and every other byte becomes %XX with upper-case hex.
func IsClientError ¶
IsClientError reports whether err is a Faraday 4xx client error (or subclass).
func IsServerError ¶
IsServerError reports whether err is a Faraday 5xx server error (or subclass).
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder is the middleware stack, mirroring Faraday::RackBuilder. It records the request and response middleware (in declaration order) and the terminal adapter, then composes them into a single Handler. Registration by symbolic name (request/response) matches Faraday's DSL; the typed constructors in middleware.go are the underlying implementations, also usable via Builder.Use.
func (*Builder) Use ¶
func (b *Builder) Use(m Middleware)
Use appends an already-constructed Middleware to the stack, mirroring Faraday's `use`. Middleware run in declaration order (outermost first).
type Connection ¶
type Connection struct {
// contains filtered or unexported fields
}
Connection is a configured HTTP client bound to a base URL, default headers and params, and a middleware stack, mirroring Faraday::Connection. Build one with New; issue requests with the verb methods or Connection.RunRequest.
func New ¶
func New(opts Options, block ...func(*Connection)) *Connection
New builds a Connection, mirroring Faraday.new(...) { |conn| ... }. The options seed the base URL, default headers and params; the optional block configures the middleware stack (conn.Request/Response/Adapter). If no adapter is set in the block, the connection defaults to the net/http adapter (NetHTTP) — tests override it with a stub via conn.Adapter.
func (*Connection) Adapter ¶
func (c *Connection) Adapter(d Doer)
Adapter sets the terminal transport (the host seam), mirroring Faraday::Connection#adapter. Pass NetHTTP for the default net/http transport or any Doer (e.g. a DoerFunc stub in tests).
func (*Connection) BuildRequest ¶
func (c *Connection) BuildRequest(method, path string, body any, headers *Headers, block func(*Request)) *Request
BuildRequest constructs the Request for a verb call: it seeds the request with clones of the connection's default headers and params, applies method, path, body and per-call headers, then runs the block, mirroring Faraday::Connection#build_request.
func (*Connection) BuildURL ¶
func (c *Connection) BuildURL(path string, params *Params) string
BuildURL resolves path against the connection's base URL and appends the merged query params (base-URL query overlaid by the request params), mirroring Faraday::Connection#build_url. Params keep their order and are escaped by BuildQuery.
func (*Connection) Delete ¶
func (c *Connection) Delete(path string, block ...func(*Request)) (*Response, error)
Delete issues a DELETE request (Faraday::Connection#delete).
func (*Connection) Get ¶
func (c *Connection) Get(path string, block ...func(*Request)) (*Response, error)
Get issues a GET request for path (resolved against the base URL), optionally configured by a block (Faraday::Connection#get).
func (*Connection) Head ¶
func (c *Connection) Head(path string, block ...func(*Request)) (*Response, error)
Head issues a HEAD request (Faraday::Connection#head).
func (*Connection) Headers ¶
func (c *Connection) Headers() *Headers
Headers returns the connection's default headers (Faraday::Connection#headers).
func (*Connection) Options ¶
func (c *Connection) Options(path string, block ...func(*Request)) (*Response, error)
Options issues an OPTIONS request (Faraday::Connection#options).
func (*Connection) Params ¶
func (c *Connection) Params() *Params
Params returns the connection's default query params (Faraday::Connection#params).
func (*Connection) Patch ¶
Patch issues a PATCH request with the given body (Faraday::Connection#patch).
func (*Connection) Post ¶
Post issues a POST request with the given body (Faraday::Connection#post).
func (*Connection) Request ¶
func (c *Connection) Request(name string, args ...string)
Request registers a request middleware by symbolic name, mirroring Faraday::Connection#request. See [Builder.request] for the supported names ("url_encoded", "json", "authorization" type+value, "basic_auth" login+pass).
func (*Connection) Response ¶
func (c *Connection) Response(name string, w ...io.Writer)
Response registers a response middleware by symbolic name, mirroring Faraday::Connection#response. Supported names: "json", "raise_error", and "logger". For "logger", pass a destination writer (nil ⇒ os.Stderr).
func (*Connection) RunRequest ¶
func (c *Connection) RunRequest(method, path string, body any, headers *Headers, block func(*Request)) (*Response, error)
RunRequest builds the request, assembles the Env, runs it through the middleware stack, and returns the finished Response, mirroring Faraday::Connection#run_request. A middleware (or the adapter) that aborts the stack is returned as the error, with a nil response.
func (*Connection) Trace ¶
func (c *Connection) Trace(path string, block ...func(*Request)) (*Response, error)
Trace issues a TRACE request (Faraday::Connection#trace).
func (*Connection) URLPrefix ¶
func (c *Connection) URLPrefix() string
URLPrefix returns the connection's base URL string (Faraday::Connection#url_prefix).
func (*Connection) Use ¶
func (c *Connection) Use(m Middleware)
Use appends an already-constructed Middleware to the stack (Faraday::Connection#use).
type Doer ¶
Doer is the transport host seam, mirroring the role a Faraday::Adapter plays as the terminal middleware. Given a prepared Env (Method, URL, RequestHeaders, and a string RequestBody left by the request middleware), a Doer performs the HTTP round-trip and fills in the response half (Status, ResponseHeaders, ResponseBody, Reason), or returns an error.
The default production Doer is NetHTTP, backed by net/http. The core opens no socket itself: every request runs through whatever Doer the connection's adapter is set to, so tests inject a stub (see DoerFunc) and never touch the network.
type DoerFunc ¶
DoerFunc adapts a function to the Doer interface, the convenient way to inject a stub adapter in tests or a custom transport in a host.
type Env ¶
type Env struct {
// Method is the upper-case HTTP method ("GET", "POST", …).
Method string
// URL is the fully-built request URL (path resolved against the connection's
// url_prefix, with the merged query string appended).
URL string
// RequestHeaders are the outgoing headers.
RequestHeaders *Headers
// RequestBody is the outgoing body. It starts as whatever the caller set
// (a [*Params] for a form, an arbitrary value for JSON, or a string) and is
// rewritten to the encoded string by the request middleware.
RequestBody any
// Params are the request query parameters (already merged into URL; kept for
// middleware that inspect them).
Params *Params
// Request carries the per-request options (see [RequestOptions]).
Request RequestOptions
// Status is the response status code, set by the adapter.
Status int
// ResponseHeaders are the response headers, set by the adapter.
ResponseHeaders *Headers
// ResponseBody is the response body: the raw string as delivered by the
// adapter, rewritten to a parsed value by response middleware (e.g. JSON).
ResponseBody any
// Reason is the response reason phrase, when the adapter supplies one.
Reason string
// contains filtered or unexported fields
}
Env is the mutable state threaded through the middleware stack, mirroring Faraday::Env. Request middleware read and rewrite the request half (Method/URL/RequestHeaders/RequestBody/Params) on the way in; the adapter fills in the response half (Status/ResponseHeaders/ResponseBody/Reason); then response middleware read and rewrite it on the way out.
type Error ¶
type Error struct {
// Kind names the specific Faraday error subclass (see the Err* sentinels).
Kind ErrorKind
// Message is the error text (Faraday::Error#message).
Message string
// Response is the response context when the error was raised from a response
// (raise_error / a 4xx–5xx status); nil for transport errors.
Response *Response
// Cause is the underlying transport error, if any (ConnectionFailed /
// TimeoutError wrap the adapter's error).
Cause error
}
Error is the root of Faraday's error tree (Faraday::Error). Every Faraday error carries a human message and, for errors raised from a response by the raise_error middleware, the response context (Error.Response) so callers can inspect the status, headers and body that triggered it.
The concrete kinds are distinguished by Error.Kind; the standard predicate helpers (IsClientError, IsServerError, …) and the sentinel values (ErrClientError, …) let callers match with errors.Is, mirroring Ruby's rescue of a Faraday::Error subclass.
func (*Error) Is ¶
Is reports whether e matches target: true when target is a *Error whose Kind is e's Kind or an ancestor of it, so errors.Is(err, ErrClientError) matches any 4xx-specific Faraday error, and errors.Is(err, ErrError) matches every Faraday error — mirroring Ruby's rescue of a superclass.
type ErrorKind ¶
type ErrorKind string
ErrorKind identifies a Faraday error subclass.
const ( KindError ErrorKind = "Faraday::Error" KindClientError ErrorKind = "Faraday::ClientError" KindBadRequest ErrorKind = "Faraday::BadRequestError" KindForbidden ErrorKind = "Faraday::ForbiddenError" KindResourceNotFound ErrorKind = "Faraday::ResourceNotFound" KindProxyAuth ErrorKind = "Faraday::ProxyAuthError" KindConflict ErrorKind = "Faraday::ConflictError" KindUnprocessableEntity ErrorKind = "Faraday::UnprocessableEntityError" KindTooManyRequests ErrorKind = "Faraday::TooManyRequestsError" KindServerError ErrorKind = "Faraday::ServerError" KindNilStatus ErrorKind = "Faraday::NilStatusError" KindConnectionFailed ErrorKind = "Faraday::ConnectionFailed" KindTimeout ErrorKind = "Faraday::TimeoutError" KindSSL ErrorKind = "Faraday::SSLError" KindParsing ErrorKind = "Faraday::ParsingError" )
The Faraday error subclasses, named as in the gem.
type Handler ¶
Handler is one step of the resolved middleware stack: it receives the Env, does its work (possibly calling the next handler), and returns an error to abort the stack. The terminal handler is the adapter.
type Headers ¶
type Headers struct {
// contains filtered or unexported fields
}
Headers is a case-insensitive, insertion-ordered header map, mirroring Faraday::Utils::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).
func (*Headers) Delete ¶
Delete removes key (case-insensitive) if present, keeping the order of the remaining headers.
func (*Headers) Merge ¶
Merge overlays other's headers onto a copy of h and returns the result (an existing key is overwritten in place, a new key is appended).
func (*Headers) Pairs ¶
Pairs returns the headers in insertion order (with first-seen key casing). The slice must not be mutated.
func (*Headers) Set ¶
Set inserts or replaces the value for key (case-insensitive). An existing key keeps its original casing and position; only the value is updated.
func (*Headers) SetDefault ¶
SetDefault inserts key→val only if key is absent (case-insensitive), matching middleware that fills in a header without clobbering a caller override.
type Middleware ¶
Middleware wraps a downstream Handler and returns a new one, mirroring a Faraday::Middleware instance in the RackBuilder. The stack is composed outermost-first; a request middleware acts before calling next, a response middleware acts after next returns.
func Authorization ¶
func Authorization(typ, value string) Middleware
Authorization is the request middleware Faraday::Request::Authorization for a scheme with a single token: it sets "Authorization: <typ> <value>" (e.g. "Bearer <token>", "Token <token>") unless the header is already present. For HTTP Basic use BasicAuth.
func BasicAuth ¶
func BasicAuth(login, password string) Middleware
BasicAuth is the request middleware for HTTP Basic authentication (Faraday::Request::Authorization with the :basic scheme): it sets "Authorization: Basic base64(login:password)" unless already present.
func JSONRequest ¶
func JSONRequest() Middleware
JSONRequest is the request middleware Faraday::Request::Json: when the request body is a non-string value and the content type is unset or JSON, it JSON-encodes the body and sets Content-Type: application/json. A body that is already a string (pre-encoded) is left untouched; a value that cannot be marshalled raises a Faraday error.
func JSONResponse ¶
func JSONResponse() Middleware
JSONResponse is the response middleware Faraday::Response::Json: when the response Content-Type is a JSON media type and the body is a non-blank string, it parses the body and replaces env.ResponseBody with the decoded value (map/slice/scalar). A malformed JSON body raises a Faraday parsing error.
func Logger ¶
func Logger(w io.Writer) Middleware
Logger is the response middleware Faraday::Response::Logger: it writes a line for the outgoing request and one for the completed response to w (os.Stderr when w is nil), leaving the request/response otherwise unchanged.
func RaiseError ¶
func RaiseError() Middleware
RaiseError is the response middleware Faraday::Response::RaiseError: on completion it maps the response status to a Faraday error, so a 4xx/5xx response aborts the stack with the matching subclass. Specific codes get their named error (404 → ResourceNotFound, 422 → UnprocessableEntity, …); other 4xx map to ClientError and 5xx to ServerError. A 2xx/3xx status passes through.
func UrlEncoded ¶
func UrlEncoded() Middleware
UrlEncoded is the request middleware Faraday::Request::UrlEncoded: when the request body is a *Params and the content type is unset or already form-encoded, it encodes the body to an application/x-www-form-urlencoded string and sets the Content-Type header. Any other body is left untouched.
type NetHTTPDoer ¶
type NetHTTPDoer struct {
// Client performs the request; defaults to http.DefaultClient.
Client httpClient
}
NetHTTPDoer is the default Doer: it turns an Env into a net/http request, executes it with its Client, and maps the response (or a transport failure) back onto the env. It mirrors Faraday's net_http adapter, including the mapping of a timeout to a Faraday TimeoutError and any other transport failure to a ConnectionFailed error.
func (*NetHTTPDoer) Call ¶
func (d *NetHTTPDoer) Call(env *Env) error
Call performs the HTTP round-trip for env with net/http.
type Options ¶
type Options struct {
// URL is the base URL (url_prefix) that request paths resolve against.
URL string
// Headers are default headers merged into every request.
Headers *Headers
// Params are default query params merged into every request.
Params *Params
}
Options configures a new Connection, mirroring the keyword options of Faraday.new(url:, headers:, params:). Empty fields take Faraday'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 bodies. Ruby's Faraday 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, mirroring Faraday::Utils.parse_query: 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, escaped query string (see BuildQuery).
func (*Params) Merge ¶
Merge returns a new Params with p's entries first (in order), overlaid by other's (an existing key is overwritten in place, a new key is appended). This is how a connection's default params merge with a request's, matching Faraday::Connection#build_url's params.merge(request.params).
type Request ¶
type Request struct {
// Method is the upper-case HTTP method.
Method string
// Path is the request path or URL passed to the verb method; it is resolved
// against the connection's url_prefix when the URL is built.
Path string
// Params are the request query parameters (seeded from the connection's
// defaults; the block may add to or overwrite them).
Params *Params
// Headers are the request headers (seeded from the connection's defaults).
Headers *Headers
// Body is the request body (nil, a [*Params] for a form, an arbitrary value
// for JSON, or a pre-encoded string).
Body any
// Options carries the per-request settings (timeouts, context).
Options RequestOptions
}
Request is the mutable request the caller configures inside a per-request block, mirroring Faraday::Request. A verb method (Get/Post/…) yields a fresh Request pre-seeded with the connection's default headers and params; the block then tweaks its method, path, params, headers and body before the middleware stack runs.
type RequestOptions ¶
type RequestOptions struct {
// Timeout is the overall request timeout; 0 means unset.
Timeout int
// OpenTimeout is the connection-open timeout; 0 means unset.
OpenTimeout int
// Context is a free-form bag for middleware to stash per-request state,
// mirroring env[:request][:context].
Context map[string]any
}
RequestOptions carries the per-request settings Faraday keeps on env[:request]: connect/read timeouts and any middleware-specific context. The deterministic core does not open sockets, so the timeouts are metadata a host adapter may honour.
type Response ¶
type Response struct {
// contains filtered or unexported fields
}
Response is the result of running a request through the middleware stack, mirroring Faraday::Response. It is a thin, read-only view over the finished Env: Status, Headers and Body reflect the response half after every response middleware has run.
func (*Response) Body ¶
Body returns the response body (Faraday::Response#body): the raw string, or the parsed value after a parsing middleware (e.g. JSON) has run.
func (*Response) Finished ¶
Finished reports whether the response has completed (Faraday::Response#finished?).
func (*Response) OnComplete ¶
OnComplete registers a callback to run when the response finishes, mirroring Faraday::Response#on_complete. If the response has already finished, the callback runs immediately.
func (*Response) ReasonPhrase ¶
ReasonPhrase returns the response reason phrase, if any (Faraday::Response#reason_phrase).
