# `PhoenixKit.API.RequestContext`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.64.1/lib/phoenix_kit/api/request_context.ex#L1)

What the API knows about the request besides who sent it: the language and
currency to answer in, the hosts this install serves, and the base URL for
absolute links.

Core's defaults are deliberately plain:

  * `:language` is the install's primary language
    (`PhoenixKit.Utils.Multilang.primary_language/0`);
  * `:currency` is `nil`, because core does not depend on Billing. A
    module that knows a base currency fills it;
  * `:hosts` is the request host;
  * `:base_url` is `scheme://host[:port]` of the request.

A host app overrides any of `:language`, `:currency` and `:hosts` per
request (a multi-domain install maps the domain to a language and a
currency):

    config :phoenix_kit, :api_request_context, {MyApp.ApiContext, :resolve}

The function takes the `Plug.Conn` and returns a map with any of those three
keys. A key of the wrong type is ignored. A function that raises is logged
and the defaults are used, so a bug in the hook cannot take the API down.
The log names the hook, the exception module and the shape of a bad result,
never their values: the hook gets the whole connection, headers included.

A call without a connection (`PhoenixKit.API.Executor.execute_as/5`, on behalf of a
live session) has no request to read: its caller passes the context as options and
`from_options/1` takes it as given. The hook is not called there, because it expects a
`Plug.Conn`.

# `t`

```elixir
@type t() :: %{
  language: String.t(),
  currency: String.t() | nil,
  hosts: [String.t()],
  base_url: String.t() | nil
}
```

# `from_options`

```elixir
@spec from_options(keyword()) :: t()
```

The context of a call without a connection, from `options` (`:language`, `:currency`,
`:hosts`, `:base_url`). A missing option, or one of the wrong type, gets the default:
the install's primary language, no currency, no hosts, no base URL. An element of
`options` that is not a `{key, value}` pair is ignored.

# `resolve`

```elixir
@spec resolve(Plug.Conn.t()) :: t()
```

Resolves the context of `conn`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
