# PhoenixSwagger [![Build Status](https://travis-ci.org/xerions/phoenix_swagger.svg?branch=master)](https://travis-ci.org/xerions/phoenix_swagger)
`PhoenixSwagger` is the library that provides [swagger](http://swagger.io/) integration
to the [phoenix](http://www.phoenixframework.org/) web framework.
The `PhoenixSwagger` generates `Swagger` specification for `Phoenix` controllers and
validates the requests.
## Installation
`PhoenixSwagger` provides `phoenix.swagger.generate` mix task for the swagger-ui `json`
file generation that contains swagger specification that describes API of the `phoenix`
application.
You just need to add the swagger DSL to your controllers and then run this one mix task
to generate the json files.
To use `PhoenixSwagger` with a phoenix application just add it to your list of
dependencies in the `mix.exs` file:
```elixir
def deps do
[{:phoenix_swagger, "~> 0.3.0"}]
end
```
Now you can use `phoenix_swagger` to generate `swagger-ui` file for you application.
## Usage
To generate [Info Object](https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#infoObject)
you must provide `swagger_info/0` function in your `mix.exs` file. This function returns
a keyword list that contains `Info Object` fields:
```elixir
def swagger_info do
[version: "0.0.0", title: "My awesome phoenix application"]
end
```
The `version` and `title` are mandatory fields. By default the `version` will be `0.0.1`
and the `title` will be `<enter your title>` if you will not provide `swagger_info/0`
function.
Fields that can be in the `swagger_info`:
Name | Required | Type | Default value
-------------- | -------- | -------------------------------------- | -------------
title | true | string | `<enter your title>`
version | true | string | `0.0.1`
description | false | string |
termsOfService | false | string |
contact | false | [name: "...", url: "...", email:"..."] |
license | false | [name: "...", url: "..."] |
`PhoenixSwagger` provides `swagger_model/2` macro that generates swagger specification
for the certain phoenix controller.
Example:
```elixir
use PhoenixSwagger
swagger_model :index do
description "Short description"
parameter :query, :id, :integer, :required, "Property id"
responses 200, "Description"
end
def index(conn, _params) do
posts = Repo.all(Post)
render(conn, "index.json", posts: posts)
end
```
The `swagger_model` macro takes two parameters:
* Name of controller action;
* `do` block that contains `swagger` definitions.
The `PhoenixSwagger` supports three definitions:
1. The `description` takes one elixir's `String` and provides short description for the
given controller action.
2. The `parameter` provides description of the routing parameter for the given action and
may take five parameters:
* The location of the parameter. Possible values are `query`, `header`, `path`, `formData` or `body`. [required];
* The name of the parameter. [required];
* The type of the parameter. Allowed only [swagger data types](https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types
) [required];
* Determines whether this parameter is mandatory, just remove it if a parameter non-required;
* Description of a parameter. Can be elixir's `String` or function/0 that returns elixir's string;
Note that order of parameters is important now.
And the third definition is `responses` that takes three parameters (third parameter is not mandatory)
and generates definition of the response for the given controller action. The first argument is http
status code and has `:integer` data type. The second is the short description of the response. The third
non-mandatory field is a schema of the response. It must be elixir `function/0` that returns a map in a
swagger schema format.
For example:
```elixir
use PhoenixSwagger
swagger_model :get_person do
description "Get persons according to the age"
parameter :query, :id, :integer, :required
responses 200, "Description", schema
end
def schema do
%{type: :array, title: "Persons",
items:
%{title: "Person", type: :object, properties: %{ name: %{type: :string}}}
}
end
def get_person_schema(conn, _params) do
...
...
...
end
```
That's all. Recompile your app `mix phoenix.server`, then run the `phoenix.swagger.generate`
mix task for the `swagger-ui` json file generation into directory with `phoenix` application:
```
mix phoenix.swagger.generate
```
As the result there will be `swagger.json` file into root directory of the `phoenix` application.
To generate `swagger` file with the custom name/place, pass it to the main mix task:
```
mix phoenix.swagger.generate ~/my-phoenix-api.json
```
For more informantion, you can find `swagger` specification [here](https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md).
## Validator
Besides generator of `swagger` schemas, the `phoenix_swagger` provides validator of input parameters of resources.
Suppose you have following resource in your schema:
```
...
...
"/history": {
"get": {
"parameters": [
{
"name": "offset",
"in": "query",
"type": "integer",
"format": "int32",
"description": "Offset the list of returned results by this amount. Default is zero."
},
{
"name": "limit",
"in": "query",
"type": "integer",
"format": "int32",
"description": "Integer of items to retrieve. Default is 5, maximum is 100."
}]
}
}
...
...
```
Before usage of swagger validator, add the `PhoenixSwagger.Validator.Supervisor` to the supervisor tree of
your application.
The `phoenix_swagger` provides `PhoenixSwagger.Validator.parse_swagger_schema/1` API to load a swagger schema by
the given path or list of paths. This API should be called during application startup to parse/load a swagger schema.
After this, the `PhoenixSwagger.Validator.validate/2` can be used to validate resources.
For example:
```elixir
iex(1)> Validator.validate("/history", %{"limit" => "10"})
{:error,"Type mismatch. Expected Integer but got String.", "#/limit"}
iex(2)> Validator.validate("/history", %{"limit" => 10, "offset" => 100})
:ok
```
Besides `validate/2` API, the `phoenix_swagger` validator can be used via Plug to validate
intput parameters of your controllers.
Just add `PhoenixSwagger.Plug.Validate` plug to your router:
```elixir
pipeline :api do
plug :accepts, ["json"]
plug PhoenixSwagger.Plug.Validate
end
scope "/api", MyApp do
pipe_through :api
post "/users", UsersController, :send
end
```