-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Confusion around reading YAML into ApiSpec #582
Comments
So as to not confuse this with my specific API I moved to a new phoenix application and am using the OpenAPI 3 petstore.yaml and still running into similar issues. The documentation doesn't describe this use case where the operation that is used in the controller comes from an already parsed API schema. I'm trying things like this but it's not working |
Interesting. I am considering using this for an already defined openapi.yaml file. The documents do seem to suggest you can read them in and get all the benefits of validation. This was a few months ago, any updates? |
@pauldemarco My understanding by reviewing the code and the README is that for YAML and JSON specs, one needs to implement their own wrapper for validations. You can try using a plug like the following: defmodule MyServiceWeb.ValidateOpenAPI do
@moduledoc """
## Usage
pipeline :api_docs do
plug OpenApiSpex.Plug.PutApiSpec, module: MyServiceWeb.ApiSpec
end
scope "/v1", OrdersServiceWeb.V2, as: :v1 do
pipe_through :api_docs
post "/my_resouce", MyResourceController, :create
end
defmodule MyResourceController do
use MyServiceWeb, :controller
plug(MyServiceWeb.ValidateWithOpenAPI, [operation_id: "my-resource-create-v1"] when action in [:create])
def create(conn, params) do
end
end
"""
@behaviour Plug
require Logger
alias OpenApiSpex.Operation
@impl Plug
def init(opts), do: Map.new(opts)
@impl Plug
def call(
%{private: %{open_api_spex: _}} = conn,
%{operation_id: operation_id}
) do
{spec, operation_lookup} = OpenApiSpex.Plug.PutApiSpec.get_spec_and_operation_lookup(conn)
case operation_lookup[operation_id] do
nil ->
warn(%{
conn: conn,
operation_id: operation_id,
errors: "Misconfigured OpenAPI validation for #{inspect(operation_id)}"
})
conn
operation ->
validate_operation(conn, operation, spec)
end
end
def call(conn, _opts), do: conn
defp validate_operation(conn, %Operation{operationId: operation_id} = operation, spec) do
case OpenApiSpex.cast_and_validate(spec, operation, conn, nil, []) do
{:ok, _conn} ->
conn
{:error, errors} ->
render_errors(errors)
end
end
defp render_errors(conn, %{errors: errors}) do
conn
|> Conn.put_resp_content_type("application/json")
|> Conn.send_resp(:unprocessable_entity, %{errors: format_errors(errors)})
end
defp format_errors(errors) do
Enum.map(errors, fn error ->
pointer = OpenApiSpex.path_to_string(error)
%{
title: "Invalid value",
source: %{
pointer: pointer
},
detail: to_string(error)
}
end)
end
end |
This was it! I am now seeing if there is a better way to connect all of the operationId's with Elixir functions in the module. plug(MyServiceWeb.ValidateWithOpenAPI, [operation_id: "my-resource-create-v1"] when action in [:create])
plug(MyServiceWeb.ValidateWithOpenAPI, [operation_id: "my-resource-update-v1"] when action in [:update])
plug(MyServiceWeb.ValidateWithOpenAPI, [operation_id: "my-resource-delete-v1"] when action in [:delete]) Any thoughts on how to consolidate? |
You can tweak plug(MyServiceWeb.ValidateWithOpenAPI, [
%{operation_id: "my-resource-delete-v1", action: :delete},
%{operation_id: "my-resource-update"], action: :update}
] when action in [:delete, :update]) |
The documentation implies that you can use either Elixir code to create your OpenAPI schema or parse and read a YAML( or JSON) OpenAPI schema. I need to do the former and I have this in my code and it parses and reads the file without an error. I also have configured the SwaggerUI and it renders the API documentation correctly which to me implies this is configured correctly:
But when I'm trying to use the functionality described in the documentation it doesn't appear that the data structures are created correctly in the modules used by the documentation. e.g. the README section "Validate Responses" has a test like this which I modified to use my module
And if I run the test I get the following error
So in effect MyApiWeb.Schemas is empty and I saw this while trying to do request validation in my Phoenix controllers as well. I know there is a PutApiSpec that's mentioned in doing validation which I have setup in my router.ex (see comment above about the swagger ui working correctly which I believe relies on this) but I get the same error there as if the module created doesn't get populated with the data from my OpenAPI schema YAML file even though it parses it and can render the docs. Note I did a quick test with the Ruby on Rails
committee
gem to confirm if this was something wrong with my schema that maybe OpenApiSpex didn't like and it worked fine without any issues.If someone could steer me in the right direction I'd appreciate it.
The text was updated successfully, but these errors were encountered: