Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F112361
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/README.md b/README.md
index 7193b0d..322b3dd 100644
--- a/README.md
+++ b/README.md
@@ -1,149 +1,191 @@
# Open API Spex
Add Open API Specification 3 (formerly swagger) to Plug applications.
## Installation
The package can be installed by adding `open_api_spex` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:open_api_spex, github: "mbuhot/open_api_spex"}
]
end
```
-## Usage
+## Generating an API spec
Start by adding an `ApiSpec` module to your application.
```elixir
defmodule MyApp.ApiSpec do
alias OpenApiSpex.{OpenApi, Server, Info, Paths}
def spec do
%OpenApi{
servers: [
# Populate the Server info from a phoenix endpoint
Server.from_endpoint(MyAppWeb.Endpoint, otp_app: :my_app)
],
info: %Info{
title: "My App",
version: "1.0"
},
# populate the paths from a phoenix router
paths: Paths.from_router(MyAppWeb.Router)
}
|> OpenApiSpex.resolve_schema_modules() # discover request/response schemas from path specs
end
end
```
For each plug (controller) that will handle api requests, add an `open_api_operation` callback.
It will be passed the plug opts that were declared in the router, this will be the action for a phoenix controller.
```elixir
defmodule MyApp.UserController do
alias OpenApiSpex.Operation
@spec open_api_operation(any) :: Operation.t
def open_api_operation(action), do: apply(__MODULE__, :"#{action}_operation", [])
@spec show_operation() :: Operation.t
def show_operation() do
%Operation{
tags: ["users"],
summary: "Show user",
description: "Show a user by ID",
operationId: "UserController.show",
parameters: [
Operation.parameter(:id, :path, :integer, "User ID", example: 123)
],
responses: %{
200 => Operation.response("User", "application/json", Schemas.UserResponse)
}
}
end
def show(conn, %{"id" => id}) do
{:ok, user} = MyApp.Users.find_by_id(id)
json(conn, 200, user)
end
end
```
Declare the JSON schemas for request/response bodies in a `Schemas` module:
```elixir
defmodule MyApp.Schemas do
alias OpenApiSpex.Schema
defmodule User do
def schema do
%Schema{
title: "User",
description: "A user of the app",
type: :object,
properties: %{
id: %Schema{type: :integer, description: "User ID"},
name: %Schema{type: :string, description: "User name"},
email: %Schema{type: :string, description: "Email address", format: :email},
inserted_at: %Schema{type: :string, description: "Creation timestamp", format: :datetime},
updated_at: %Schema{type: :string, description: "Update timestamp", format: :datetime}
}
}
end
end
defmodule UserResponse do
def schema do
%Schema{
title: "UserResponse",
description: "Response schema for single user",
type: :object,
properties: %{
data: User
}
}
end
end
end
```
Now you can create a mix task to write the swagger file to disk:
```elixir
defmodule Mix.Tasks.MyApp.OpenApiSpec do
def run([output_file]) do
json =
MyApp.ApiSpec.spec()
|> Poison.encode!(pretty: true)
:ok = File.write!(output_file, json)
end
end
```
Generate the file with: `mix myapp.openapispec spec.json`
-You can also serve the swagger through a controller:
+## Serving the API Spec from a Controller
```elixir
defmodule MyApp.OpenApiSpecController do
def show(conn, _params) do
spec =
MyApp.ApiSpec.spec()
json(conn, spec)
end
end
```
+## Use the API Spec to cast params
+
+Add the `OpenApiSpex.Plug.Cast` plug to a controller to cast the request parameters to elixir types defined by the operation schema.
+
+```elixir
+plug OpenApiSpex.Plug.Cast, operation_id: "UserController.show"
+```
+
+The `operation_id` can be inferred when used from a Phoenix controller from the contents of `conn.private`.
+
+```elixir
+defmodule MyApp.UserController do
+ use MyAppWeb, :controller
+ alias OpenApiSpex.Operation
+
+ plug OpenApiSpex.Plug.Cast
+
+ def open_api_operation(action) do
+ apply(__MODULE__, "#{action}_operation", [])
+ end
+
+ def create_operation do
+ import Operation
+ %Operation{
+ tags: ["users"],
+ summary: "Create user",
+ description: "Create a user",
+ operationId: "UserController.create",
+ parameters: [],
+ requestBody: request_body("The user attributes", "application/json", Schemas.UserRequest),
+ responses: %{
+ 201 => response("User", "application/json", Schemas.UserResponse)
+ }
+ }
+ end
+
+ def create(conn, %{user: %{name: name, email: email, birthday: birthday = %Date{}}}) do
+ # params will have atom keys with values cast to standard elixir types
+ end
+end
+```
+
TODO: SwaggerUI 3.0
TODO: Request Validation
TODO: Validating examples in the spec
TODO: Validating responses in tests
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 10:50 AM (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38945
Default Alt Text
(5 KB)
Attached To
Mode
R22 open_api_spex
Attached
Detach File
Event Timeline
Log In to Comment