HTTP.Headers (http_fetch v0.5.0)

Module for processing HTTP headers with utilities for parsing, normalizing, and manipulating headers.

Summary

Functions

Adds a new header value without removing existing headers with the same name.

Removes a header by name (case-insensitive).

Formats headers for display (useful for debugging).

Converts a map of headers to a HTTP.Headers struct.

Gets a header value by name (case-insensitive).

Gets all header values for a given header name (case-insensitive).

Checks if a header exists (case-insensitive).

Merges two HTTP.Headers structs, with the second taking precedence.

Creates a new HTTP.Headers struct.

Normalizes header names to title case (e.g., "content-type" becomes "Content-Type").

Parses a header string into a {name, value} tuple.

Parses a Content-Type header to extract the media type and parameters.

Sets a header value, replacing any existing header with the same name.

Sets a header only if it doesn't already exist (case-insensitive).

Returns the underlying list of headers.

Converts a HTTP.Headers struct to a map for easy lookup.

Returns the default User-Agent string used by the library.

Types

header()

@type header() :: {String.t(), String.t()}

headers_list()

@type headers_list() :: [header()]

t()

@type t() :: %HTTP.Headers{headers: headers_list()}

Functions

add(headers_struct, name, value)

@spec add(t(), String.t(), String.t()) :: t()

Adds a new header value without removing existing headers with the same name.

Examples

iex> headers = HTTP.Headers.new([{"Accept", "text/html"}])
iex> updated = HTTP.Headers.add(headers, "Accept", "application/json")
iex> HTTP.Headers.get_all(updated, "Accept")
["text/html", "application/json"]

iex> headers = HTTP.Headers.new()
iex> updated = HTTP.Headers.add(headers, "Authorization", "Bearer token")
iex> HTTP.Headers.get(updated, "Authorization")
"Bearer token"

iex> headers = HTTP.Headers.new([{"Content-Type", "text/plain"}])
iex> updated = HTTP.Headers.add(headers, "Authorization", "Bearer token")
iex> HTTP.Headers.get(updated, "Authorization")
"Bearer token"
iex> HTTP.Headers.get(updated, "Content-Type")
"text/plain"

delete(headers_struct, name)

@spec delete(t(), String.t()) :: t()

Removes a header by name (case-insensitive).

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}, {"Authorization", "Bearer token"}])
iex> updated = HTTP.Headers.delete(headers, "content-type")
iex> HTTP.Headers.has?(updated, "content-type")
false
iex> HTTP.Headers.has?(updated, "Authorization")
true

format(headers)

@spec format(t()) :: String.t()

Formats headers for display (useful for debugging).

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}, {"Authorization", "Bearer token"}])
iex> HTTP.Headers.format(headers)
"Content-Type: application/json

Authorization: Bearer token"

from_map(map)

@spec from_map(map()) :: t()

Converts a map of headers to a HTTP.Headers struct.

Examples

iex> headers = HTTP.Headers.from_map(%{"content-type" => "application/json", "authorization" => "Bearer token"})
iex> {"Content-Type", "application/json"} in headers.headers
true
iex> {"Authorization", "Bearer token"} in headers.headers
true

get(headers, name)

@spec get(t(), String.t()) :: String.t() | nil

Gets a header value by name (case-insensitive).

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}])
iex> HTTP.Headers.get(headers, "content-type")
"application/json"

iex> headers = HTTP.Headers.new([{"Authorization", "Bearer token"}])
iex> HTTP.Headers.get(headers, "missing")
nil

get_all(headers, name)

@spec get_all(t(), String.t()) :: [String.t()]

Gets all header values for a given header name (case-insensitive).

Examples

iex> headers = HTTP.Headers.new([{"Accept", "text/html"}, {"Accept", "application/json"}])
iex> HTTP.Headers.get_all(headers, "accept")
["text/html", "application/json"]

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}, {"Authorization", "Bearer token"}])
iex> HTTP.Headers.get_all(headers, "content-type")
["application/json"]

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}])
iex> HTTP.Headers.get_all(headers, "missing")
[]

has?(headers, name)

@spec has?(t(), String.t()) :: boolean()

Checks if a header exists (case-insensitive).

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}])
iex> HTTP.Headers.has?(headers, "content-type")
true

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}])
iex> HTTP.Headers.has?(headers, "missing")
false

merge(headers1, headers2)

@spec merge(t(), t()) :: t()

Merges two HTTP.Headers structs, with the second taking precedence.

Examples

iex> headers1 = HTTP.Headers.new([{"Content-Type", "text/plain"}])
iex> headers2 = HTTP.Headers.new([{"Content-Type", "application/json"}])
iex> merged = HTTP.Headers.merge(headers1, headers2)
iex> HTTP.Headers.get(merged, "Content-Type")
"application/json"

iex> headers1 = HTTP.Headers.new([{"A", "1"}])
iex> headers2 = HTTP.Headers.new([{"B", "2"}])
iex> merged = HTTP.Headers.merge(headers1, headers2)
iex> HTTP.Headers.get(merged, "A")
"1"
iex> HTTP.Headers.get(merged, "B")
"2"

new(headers \\ [])

@spec new(headers_list()) :: t()

Creates a new HTTP.Headers struct.

Examples

iex> HTTP.Headers.new([{"Content-Type", "application/json"}])
%HTTP.Headers{headers: [{"Content-Type", "application/json"}]}

iex> HTTP.Headers.new()
%HTTP.Headers{headers: []}

normalize_name(name)

@spec normalize_name(String.t()) :: String.t()

Normalizes header names to title case (e.g., "content-type" becomes "Content-Type").

Examples

iex> HTTP.Headers.normalize_name("content-type")
"Content-Type"

iex> HTTP.Headers.normalize_name("AUTHORIZATION")
"Authorization"

parse(header_str)

@spec parse(String.t()) :: header()

Parses a header string into a {name, value} tuple.

Examples

iex> HTTP.Headers.parse("Content-Type: application/json")
{"Content-Type", "application/json"}

iex> HTTP.Headers.parse("Authorization: Bearer token123")
{"Authorization", "Bearer token123"}

parse_content_type(content_type)

@spec parse_content_type(String.t()) :: {String.t(), map()}

Parses a Content-Type header to extract the media type and parameters.

Examples

iex> HTTP.Headers.parse_content_type("application/json; charset=utf-8")
{"application/json", %{"charset" => "utf-8"}}

iex> HTTP.Headers.parse_content_type("text/plain")
{"text/plain", %{}}

set(headers_struct, name, value)

@spec set(t(), String.t(), String.t()) :: t()

Sets a header value, replacing any existing header with the same name.

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "text/plain"}])
iex> updated = HTTP.Headers.set(headers, "Content-Type", "application/json")
iex> HTTP.Headers.get(updated, "Content-Type")
"application/json"

iex> headers = HTTP.Headers.new()
iex> updated = HTTP.Headers.set(headers, "Authorization", "Bearer token")
iex> HTTP.Headers.get(updated, "Authorization")
"Bearer token"

set_default(headers_struct, name, value)

@spec set_default(t(), String.t(), String.t()) :: t()

Sets a header only if it doesn't already exist (case-insensitive).

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "text/plain"}])
iex> updated = HTTP.Headers.set_default(headers, "Content-Type", "application/json")
iex> HTTP.Headers.get(updated, "Content-Type")
"text/plain"

iex> headers = HTTP.Headers.new([{"Accept", "text/html"}])
iex> updated = HTTP.Headers.set_default(headers, "User-Agent", "CustomAgent/1.0")
iex> HTTP.Headers.get(updated, "User-Agent")
"CustomAgent/1.0"

iex> headers = HTTP.Headers.new()
iex> updated = HTTP.Headers.set_default(headers, "Authorization", "Bearer token")
iex> HTTP.Headers.get(updated, "Authorization")
"Bearer token"

to_list(headers)

@spec to_list(t()) :: headers_list()

Returns the underlying list of headers.

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}])
iex> HTTP.Headers.to_list(headers)
[{"Content-Type", "application/json"}]

to_map(headers)

@spec to_map(t()) :: map()

Converts a HTTP.Headers struct to a map for easy lookup.

Examples

iex> headers = HTTP.Headers.new([{"Content-Type", "application/json"}, {"Authorization", "Bearer token"}])
iex> HTTP.Headers.to_map(headers)
%{"content-type" => "application/json", "authorization" => "Bearer token"}

user_agent()

@spec user_agent() :: String.t()

Returns the default User-Agent string used by the library.

Examples

iex> user_agent = HTTP.Headers.user_agent()
iex> user_agent =~ "Mozilla/5.0"
true
iex> user_agent =~ "http_fetch/"
true