# `LightningWeb.API.Request`
[🔗](https://github.com/OpenFn/lightning/blob/main/lib/lightning_web/api/request.ex#L1)

The checks on a request's ids and JSON body before the body reaches a
changeset, and telling when a create-or-replace `PUT /:id` lost the race for
its id.

# `param`

```elixir
@type param() :: {LightningWeb.API.Errors.location(), term()}
```

A value the request sent, with where it sent it, such as
`{{:path, "id"}, "a1b2..."}`. `param/2` reads one from a conn.

# `check`

```elixir
@spec check(map(), Ecto.UUID.t(), [atom()]) ::
  {:ok, [LightningWeb.API.Errors.entry()]}
  | {:error, LightningWeb.API.Problem.t()}
```

Checks `body` against the keys the route accepts and the id in its path.

`id` is the id the URL names, already known to be a UUID.

Returns `{:error, problem}` with a 400 `malformed` problem when the body is
not a JSON object. Otherwise returns `{:ok, entries}`, empty when the body
passes: one `unknown_key` entry for each key outside `accepted`, and a
`mismatch` entry when the body's `id` names another.

# `check_object`

```elixir
@spec check_object(map()) :: :ok | {:error, LightningWeb.API.Problem.t()}
```

`:ok` when `body`, a request's body params, was a JSON object. Otherwise a
400 `malformed` problem, for any route that takes an object.
Plug.Parsers puts any other JSON value under `"_json"`, alone. An object
that sends a `"_json"` key among others is still an object.

# `id`

```elixir
@spec id(param()) ::
  {:ok, Ecto.UUID.t()}
  | {:error, {:invalid_id, LightningWeb.API.Errors.location()}}
```

The id in `param`, written out as a UUID.

Returns `{:error, {:invalid_id, location}}` for anything else, naming where
the request sent it. `Ecto.UUID.cast/1` would also take any 16-byte string as
a raw UUID, landing the request under an id it doesn't name.

# `id_taken?`

```elixir
@spec id_taken?(Ecto.Changeset.t()) :: boolean()
```

Whether an insert at the path's id failed because the id's row now exists,
that is, another request created it after the route looked the id up.

# `param`

```elixir
@spec param(Plug.Conn.t(), String.t()) :: param()
```

The value of the request's parameter `name`, with where it came from: the
path, the query, or else the body.

# `unknown_keys`

```elixir
@spec unknown_keys(map(), [LightningWeb.API.Errors.segment()], [atom()]) :: [
  LightningWeb.API.Errors.entry()
]
```

One `unknown_key` entry for each key of `object` outside `accepted`, in key
order, each under `path`.

# `validate_matches_path`

```elixir
@spec validate_matches_path(Ecto.Changeset.t(), map(), atom(), Ecto.UUID.t()) ::
  Ecto.Changeset.t()
```

`changeset` with a `mismatch` error on `field` when `body` names an id there
other than `id`.

---

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