To set up the Open API endpoints for your application, first include the :open_api_spex
dependency:
{:open_api_spex, "~> 3.16"},
Then in the module where you call use AshJsonApi.Router
add the following option:
use AshJsonApi.Router, domains: [...], open_api: "/open_api"
Finally, you can use utilities provided by open_api_spex
to show UIs for your API. Be sure to put your forward
call last, if you are putting your API at a sub-path.
forward "/api/swaggerui",
OpenApiSpex.Plug.SwaggerUI,
path: "/api/open_api",
default_model_expand_depth: 4
forward "/api/redoc",
Redoc.Plug.RedocUI,
spec_url: "/api/open_api"
forward "/api", YourApp.YourApiRouter
Now you can go to /api/swaggerui
and /api/redoc
!
To set up the open API endpoints for your application, first include the :open_api_spex
and :redoc_ui_plug
dependency:
{:open_api_spex, "~> 3.16"},
{:redoc_ui_plug, "~> 0.2.1"},
Then in the module where you call use AshJsonApi.Router
add the following option:
use AshJsonApi.Router, domains: [...], open_api: "/open_api"
Finally, you can use utilities provided by open_api_spex
to show UIs for your API. Be sure to put your forward
call last, if you are putting your API at a sub-path.
forward "/api/swaggerui",
to: OpenApiSpex.Plug.SwaggerUI,
init_opts: [
path: "/api/open_api",
default_model_expand_depth: 4
]
forward "/api/redoc",
to: Redoc.Plug.RedocUI,
init_opts: [
spec_url: "/api/open_api"
]
forward "/api", YourApp.YourApiRouter
Now you can go to /api/swaggerui
and /api/redoc
!
To customize the main values of the OpenAPI spec, a few options are available:
use AshJsonApi.Router,
domains: [...],
open_api: "/open_api",
open_api_title: "Title",
open_api_version: "1.0.0",
open_api_servers: ["http://domain.com/api/v1"]
If :open_api_servers
is not specified, a default server is automatically derived from your app's Phoenix endpoint, as retrieved from inbound connections on the open_api
HTTP route.
In case an active connection is not available, for example when generating the OpenAPI spec via CLI, you can explicitely specify a reference to the Phoenix endpoint:
use AshJsonApi.Router,
domains: [...],
open_api: "/open_api",
phoenix_endpoint: MyAppWeb.Endpoint
To override any value in the OpenApi documentation you can use the :modify_open_api
options key:
use AshJsonApi.Router,
domains: [...],
open_api: "/open_api",
modify_open_api: {__MODULE__, :modify_open_api, []}
def modify_open_api(spec, _, _) do
%{
spec
| info: %{spec.info | title: "MyApp Title JSON API", version: Application.spec(:my_app, :vsn) |> to_string()}
}
end
You can write the OpenAPI spec file to disk using the Mix tasks provided by OpenApiSpex.
Supposing you have setup AshJsonApi as:
defmodule MyAppWeb.AshJsonApi
use AshJsonApi.Router, domains: [...], open_api: "/open_api"
end
you can generate the files with:
mix openapi.spec.json --spec MyAppWeb.AshJsonApi
mix openapi.spec.yaml --spec MyAppWeb.AshJsonApi
The route prefix in normal usage is automatically inferred, but when generating files we will use the
prefix
option set in thejson_api
section of the relevantAsh.Domain
module.
To generate the YAML file you need to add the ymlr dependency.
def deps do
[
{:ymlr, "~> 2.0"}
]
end
You can also use the --check
option to confirm that your checked in spec file(s) match.
mix openapi.spec.json --spec MyAppWeb.AshJsonApiRouter --check
mix openapi.spec.yaml --spec MyAppWeb.AshJsonApiRouter --check
To avoid generating the spec every time your open_api endpoint is hit, you can use
the open_api_file
option. Ensure that it points to an existing .json
file.
You will almost certainly want to do this only for production so that the schema
is generated dynamically in dev, but served statically in production.
open_api_file =
if Mix.env() == :prod do
"priv/static/open_api.json"
else
nil
end
use AshJsonApi.Router,
domains: [...],
open_api: "/open_api",
modify_open_api: {__MODULE__, :modify_open_api, []},
open_api_file: open_api_file
SwaggerUI does not properly render recursive types. This affects the examples and type documentation for the filter
parameter especially.
Redoc does not show all available schemas in the sidebar. This means that some schemas that are referenced only but have no endpoints that refer to them are effectively un-discoverable without downloading the spec and hunting them down yourself.