Reusing swagger parameters
When building an API it can be common to have headers or parameters that are common to multiple actions.
Scenario
For example, let's say we've got two endpoints:
GET /projects
GET /books
Both of these endpoints can be sorted using by sort_by
and sort_direction
parameters and both require an Authorization header.
Here's what the swagger spec in our ProjectsController
would look like:
defmodule ProjectsController do
use PhoenixSwagger
swagger_path :index do
get "/projects"
produces "application/json"
parameter("Authorization", :header, :string, "OAuth2 access token", required: true)
parameters do
sort_by :query, :string, "The property to sort by"
sort_direction :query, :string, "The sort direction", enum: [:asc, :desc], default: :asc
company_id :string, :query, "The company id"
end
end
end
Our BooksController swagger would look very similar, also defining the Authorization
header and the sort_by
and sort_direction
headers.
Extracting parameters into a module for reuse
The swagger_path
macro layer is actually just some syntactic sugar over regular elixir functions, intended to be easily extended. Any function that accepts a %PhoenixSwagger.Path.PathObject{}
as its first argument and returns an updated %PathObject{}
can be used in the swagger_path
macro.
Knowing this, we can easily extract some of the common logic into a module and reuse it in our controllers.
defmodule CommonParameters do
@moduledoc "Common parameter declarations for phoenix swagger"
alias PhoenixSwagger.Path.PathObject
import PhoenixSwagger.Path
def authorization(path = %PathObject{}) do
path |> parameter("Authorization", :header, :string, "OAuth2 access token", required: true)
end
def sorting(path = %PathObject{}) do
path
|> parameter(:sort_by, :query, :string, "The property to sort by")
|> parameter(:sort_direction, :query, :string, "The sort direction", enum: [:asc, :desc], default: :asc)
end
end
This can also be done using the parameters
macro:
def sorting(path = %PathObject{}) do
parameters path do
sort_by :query, :string, "The property to sort by"
sort_direction :query, :string, "The sort direction", enum: [:asc, :desc], default: :asc
end
end
Reusing the common parameters
Now, instead of defining these parameters in every controller, we can just reference the CommonParameters
module:
defmodule ProjectsController do
use PhoenixSwagger
swagger_path :index do
get "/users"
produces "application/json"
CommonParameters.authorization
CommonParameters.sorting
parameters do
company_id :string, :query, "The company id"
end
end
end