Packages
open_api_spex
3.16.3
3.22.3
3.22.2
3.22.1
3.22.0
3.21.5
3.21.4
3.21.3
3.21.2
3.21.1
3.21.0
3.20.1
3.20.0
3.19.1
3.19.0
3.18.3
3.18.2
3.18.1
3.18.0
3.17.3
3.17.2
3.17.1
3.17.0
3.16.4
3.16.3
3.16.2
3.16.1
3.16.0
3.15.0
3.14.0
3.13.0
3.12.0
3.11.0
3.10.0
3.9.0
3.8.0
3.7.0
3.6.0
3.5.2
3.5.1
3.5.0
3.4.0
3.3.0
3.2.1
3.2.0
3.1.0
3.0.0
2.3.1
2.3.0
2.2.0
2.1.1
2.1.0
2.0.0
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
Leverage Open Api Specification 3 (swagger) to document, test, validate and explore your Plug and Phoenix APIs.
Current section
Files
Jump to
Current section
Files
lib/open_api_spex/operation2.ex
defmodule OpenApiSpex.Operation2 do
@moduledoc """
Casts and validates a request from a Plug conn.
"""
alias OpenApiSpex.{
Cast,
CastParameters,
Components,
OpenApi,
Operation,
Reference,
RequestBody
}
alias OpenApiSpex.Cast.Error
alias Plug.Conn
@spec cast(
OpenApi.t(),
Operation.t(),
Conn.t(),
String.t() | nil,
opts :: [OpenApiSpex.cast_opt()]
) ::
{:error, [Error.t()]} | {:ok, Conn.t()}
def cast(
spec = %OpenApi{components: components},
operation = %Operation{},
conn = %Conn{},
content_type,
opts \\ []
) do
replace_params = Keyword.get(opts, :replace_params, true)
with {:ok, conn} <- cast_parameters(conn, operation, spec, opts),
{:ok, body} <-
cast_request_body(
operation.requestBody,
conn.body_params,
content_type,
components,
opts
) do
{:ok, conn |> cast_conn(body) |> maybe_replace_body(body, replace_params)}
end
end
## Private functions
defp cast_conn(conn, body) do
private_data =
conn
|> Map.get(:private)
|> Map.get(:open_api_spex, %{})
|> Map.put(:body_params, body)
Plug.Conn.put_private(conn, :open_api_spex, private_data)
end
defp maybe_replace_body(conn, _body, false), do: conn
defp maybe_replace_body(conn, body, true), do: %{conn | body_params: body}
defp cast_parameters(conn, operation, spec, opts) do
CastParameters.cast(conn, operation, spec, opts)
end
defp cast_request_body(ref = %Reference{}, body_params, content_type, components, opts) do
request_body = Reference.resolve_request_body(ref, components.requestBodies)
cast_request_body(request_body, body_params, content_type, components, opts)
end
defp cast_request_body(nil, _, _, _, _), do: {:ok, %{}}
defp cast_request_body(%{required: false}, _, nil, _, _), do: {:ok, %{}}
defp cast_request_body(%{required: true}, _, nil, _, _) do
{:error, [Error.new(%{path: [], value: nil}, {:missing_header, "content-type"})]}
end
# Special case to handle strings or arrays in request body that come inside _json
# https://hexdocs.pm/plug/Plug.Parsers.JSON.html
defp cast_request_body(
request_body,
%{"_json" => body_params},
content_type,
components = %Components{},
opts
) do
case cast_request_body(request_body, body_params, content_type, components, opts) do
{:ok, body_params} -> {:ok, %{"_json" => body_params}}
error -> error
end
end
defp cast_request_body(
%RequestBody{content: content},
params,
content_type,
components = %Components{},
opts
) do
case content do
%{^content_type => media_type} ->
Cast.cast(media_type.schema, params, components.schemas, opts)
_ ->
{:error, [Error.new(%{path: [], value: content_type}, {:invalid_header, "content-type"})]}
end
end
end