HTTPower.Codec (HTTPower v0.22.0)

Copy Markdown View Source

Request encoding for HTTPower.

This module handles encoding of request bodies and query parameters before they are passed to the adapter layer.

Body Encoding

Supports three mutually exclusive body options:

  • json: data — Encodes data as JSON, sets Content-Type: application/json and Accept: application/json headers (unless already present).
  • form: data — Encodes data as a URL-encoded form string, sets Content-Type: application/x-www-form-urlencoded (unless already present).
  • body: data — Passes data through as-is. No encoding, no headers added.

Only one body option may be used per request. Combining json:, form:, or body: in the same opts list returns an error.

Query Parameters

  • params: data — Encodes data as query parameters and appends to the request URL. Merges with any existing query string. Uses URI.encode_query/1 (flat key-value only). Can be combined with any body option.

Examples

# JSON encoding
iex> request = HTTPower.Request.new(:post, URI.parse("https://api.example.com/users"))
iex> {:ok, encoded, opts} = HTTPower.Codec.encode_request(request, json: %{name: "Alice"})
iex> encoded.body
~s({"name":"Alice"})
iex> encoded.headers["Content-Type"]
"application/json"
iex> opts
[]

# Form encoding
iex> request = HTTPower.Request.new(:post, URI.parse("https://api.example.com/login"))
iex> {:ok, encoded, opts} = HTTPower.Codec.encode_request(request, form: [user: "alice", pass: "secret"])
iex> encoded.headers["Content-Type"]
"application/x-www-form-urlencoded"
iex> opts
[]

# Existing Content-Type is preserved
iex> request = HTTPower.Request.new(:post, URI.parse("https://api.example.com/users"), nil, %{"content-type" => "application/vnd.api+json"})
iex> {:ok, encoded, _opts} = HTTPower.Codec.encode_request(request, json: %{name: "Alice"})
iex> encoded.headers["content-type"]
"application/vnd.api+json"
iex> Map.has_key?(encoded.headers, "Content-Type")
false

Summary

Functions

Decodes the response body based on the Content-Type header.

Encodes the request body based on the encoding option present in opts.

Returns true if the given content type string is a JSON media type.

Functions

decode_response(response, opts)

@spec decode_response(
  HTTPower.Response.t(),
  keyword()
) :: HTTPower.Response.t()

Decodes the response body based on the Content-Type header.

Returns the updated response struct (not a tuple). Decoding is skipped when:

  • raw: true is present in opts
  • The body is not a binary (already decoded, e.g. a dedup cache hit)
  • The body is nil or an empty string
  • The Content-Type is not a JSON media type

Invalid JSON is left as the raw binary (no error is raised).

encode_request(request, opts)

@spec encode_request(
  HTTPower.Request.t(),
  keyword()
) :: {:ok, HTTPower.Request.t(), keyword()} | {:error, HTTPower.Error.t()}

Encodes the request body based on the encoding option present in opts.

Returns {:ok, updated_request, updated_opts} on success, or {:error, %HTTPower.Error{}} on failure.

The encoding option (:json or :form) is removed from the returned opts.

json_content_type?(content_type)

@spec json_content_type?(String.t() | nil) :: boolean()

Returns true if the given content type string is a JSON media type.

Recognises application/json (with optional parameters) and any media type with a +json structured-syntax suffix, such as application/vnd.api+json. Returns false for nil.