Page MenuHomePhorge

No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/open_api_spex/plug/cast.ex b/lib/open_api_spex/plug/cast.ex
index f58728c..afd6fc7 100644
--- a/lib/open_api_spex/plug/cast.ex
+++ b/lib/open_api_spex/plug/cast.ex
@@ -1,86 +1,86 @@
defmodule OpenApiSpex.Plug.Cast do
@moduledoc """
Module plug that will cast the `Conn.params` according to the schemas defined for the operation.
The operation_id can be given at compile time as an argument to `init`:
plug OpenApiSpex.Plug.Cast, operation_id: "MyApp.ShowUser"
For phoenix applications, the operation_id can be obtained at runtime automatically.
defmodule MyAppWeb.UserController do
use Phoenix.Controller
plug OpenApiSpex.Plug.Cast
...
end
If you want customize the error response, you can provide the `:render_error` option to register a plug which creates
a custom response in the case of a validation error.
## Example
defmodule MyAppWeb.UserController do
use Phoenix.Controller
plug OpenApiSpex.Plug.Cast,
render_error: MyApp.RenderError
...
end
defmodule MyApp.RenderError do
def init(opts), do: opts
def call(conn, reason) do
msg = %{error: reason} |> Posion.encode!()
conn
|> Conn.put_resp_content_type("application/json")
|> Conn.send_resp(400, msg)
end
end
"""
@behaviour Plug
alias Plug.Conn
@impl Plug
def init(opts), do: Keyword.put_new(opts, :render_error, OpenApiSpex.Plug.DefaultRenderError)
@impl Plug
def call(conn = %{private: %{open_api_spex: private_data}}, operation_id: operation_id, render_error: render_error) do
spec = private_data.spec
operation = private_data.operation_lookup[operation_id]
content_type = Conn.get_req_header(conn, "content-type")
- |> Enum.at(0)
+ |> Enum.at(0, "")
|> String.split(";")
|> Enum.at(0)
private_data = Map.put(private_data, :operation_id, operation_id)
conn = Conn.put_private(conn, :open_api_spex, private_data)
case OpenApiSpex.cast(spec, operation, conn, content_type) do
{:ok, params} -> %{conn | params: params}
{:error, reason} ->
opts = render_error.init(reason)
conn
|> render_error.call(opts)
|> Plug.Conn.halt()
end
end
def call(conn = %{private: %{phoenix_controller: controller, phoenix_action: action, open_api_spex: _pd}}, opts) do
operation_id = controller.open_api_operation(action).operationId
if (operation_id) do
call(conn, Keyword.put(opts, :operation_id, operation_id))
else
raise "operationId was not found in action API spec"
end
end
def call(_conn = %{private: %{open_api_spex: _pd}}, _opts) do
raise ":operation_id was neither provided nor inferred from conn. Consider putting plug OpenApiSpex.Plug.Cast rather into your phoenix controller."
end
def call(_conn, _opts) do
raise ":open_api_spex was not found under :private. Maybe OpenApiSpex.Plug.PutApiSpec was not called before?"
end
end
diff --git a/lib/open_api_spex/plug/validate.ex b/lib/open_api_spex/plug/validate.ex
index 7dd5c5a..54e9fd5 100644
--- a/lib/open_api_spex/plug/validate.ex
+++ b/lib/open_api_spex/plug/validate.ex
@@ -1,84 +1,84 @@
defmodule OpenApiSpex.Plug.Validate do
@moduledoc """
Module plug that validates params against the schema defined for an operation.
If validation fails, the plug will send a 422 response with the reason as the body.
This plug should always be run after `OpenApiSpex.Plug.Cast`, as it expects the params map to
have atom keys and query params converted from strings to the appropriate types.
## Example
defmodule MyApp.UserController do
use Phoenix.Controller
plug OpenApiSpex.Plug.Cast
plug OpenApiSpex.Plug.Validate
...
end
If you want customize the error response, you can provide the `:render_error` option to register a plug which creates
a custom response in the case of a validation error.
## Example
defmodule MyApp.UserController do
use Phoenix.Controller
plug OpenApiSpex.Plug.Cast
plug OpenApiSpex.Plug.Validate,
render_error: MyApp.RenderError
def render_error(conn, reason) do
msg = %{error: reason} |> Posion.encode!()
conn
|> Conn.put_resp_content_type("application/json")
|> Conn.send_resp(400, msg)
end
...
end
defmodule MyApp.RenderError do
def init(opts), do: opts
def call(conn, reason) do
msg = %{error: reason} |> Posion.encode!()
conn
|> Conn.put_resp_content_type("application/json")
|> Conn.send_resp(400, msg)
end
end
"""
@behaviour Plug
alias Plug.Conn
@impl Plug
def init(opts), do: Keyword.put_new(opts, :render_error, OpenApiSpex.Plug.DefaultRenderError)
@impl Plug
def call(conn, render_error: render_error) do
spec = conn.private.open_api_spex.spec
operation_id = conn.private.open_api_spex.operation_id
operation_lookup = conn.private.open_api_spex.operation_lookup
operation = operation_lookup[operation_id]
content_type = Conn.get_req_header(conn, "content-type")
- |> Enum.at(0)
+ |> Enum.at(0, "")
|> String.split(";")
|> Enum.at(0)
with :ok <- OpenApiSpex.validate(spec, operation, conn, content_type) do
conn
else
{:error, reason} ->
opts = render_error.init(reason)
conn
|> render_error.call(opts)
|> Plug.Conn.halt()
end
end
def render_error(conn, reason) do
conn |> Conn.send_resp(422, "#{reason}")
end
end
\ No newline at end of file
diff --git a/test/param_test.exs b/test/param_test.exs
index 7580d7b..f66225f 100644
--- a/test/param_test.exs
+++ b/test/param_test.exs
@@ -1,70 +1,64 @@
defmodule ParamTest do
use ExUnit.Case
describe "Param" do
test "Valid Param" do
conn =
:get
|> Plug.Test.conn("/api/users?validParam=true")
- |> Plug.Conn.put_req_header("content-type", "application/json")
|> OpenApiSpexTest.Router.call([])
assert conn.status == 200
end
test "Invalid value" do
conn =
:get
|> Plug.Test.conn("/api/users?validParam=123")
- |> Plug.Conn.put_req_header("content-type", "application/json")
|> OpenApiSpexTest.Router.call([])
assert conn.status == 422
end
test "Invalid Param" do
conn =
:get
|> Plug.Test.conn("/api/users?validParam=123&inValidParam=123&inValid2=hi")
- |> Plug.Conn.put_req_header("content-type", "application/json")
|> OpenApiSpexTest.Router.call([])
assert conn.status == 422
assert conn.resp_body == "Undefined query parameter: \"inValid2\""
end
end
describe "Param with custom error handling" do
test "Valid Param" do
conn =
:get
|> Plug.Test.conn("/api/custom_error_users?validParam=true")
- |> Plug.Conn.put_req_header("content-type", "application/json")
|> OpenApiSpexTest.Router.call([])
assert conn.status == 200
end
test "Invalid value" do
conn =
:get
|> Plug.Test.conn("/api/custom_error_users?validParam=123")
- |> Plug.Conn.put_req_header("content-type", "application/json")
|> OpenApiSpexTest.Router.call([])
assert conn.status == 400
end
test "Invalid Param" do
conn =
:get
|> Plug.Test.conn("/api/custom_error_users?validParam=123&inValidParam=123&inValid2=hi")
- |> Plug.Conn.put_req_header("content-type", "application/json")
|> OpenApiSpexTest.Router.call([])
assert conn.status == 400
assert conn.resp_body == "Undefined query parameter: \"inValid2\""
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Sun, Dec 1, 6:42 PM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41800
Default Alt Text
(7 KB)

Event Timeline