View Source OpenApiSpex.ControllerSpecs (open_api_spex v3.21.2)

Macros for defining operation specs, shared operation tags, and shared security specs in a Phoenix controller.

Example

Here is an example Phoenix controller that uses the ControllerSpecs Operation specs:

defmodule MyAppWeb.UserController do
  use Phoenix.Controller
  use OpenApiSpex.ControllerSpecs

  alias MyAppWeb.Schemas.{UserParams, UserResponse}

  tags ["users"]
  security [%{}, %{"petstore_auth" => ["write:users", "read:users"]}]

  operation :update,
    summary: "Update user",
    parameters: [
      id: [
        in: :path,
        description: "User ID",
        type: :integer,
        example: 1001
      ]
    ],
    request_body: {"User params", "application/json", UserParams},
    responses: [
      ok: {"User response", "application/json", UserResponse}
    ]

  def update(conn, %{"id" => id}) do
    json(conn, %{
      data: %{
        id: id,
        name: "joe user",
        email: "joe@gmail.com"
      }
    })
  end
end

If you use Elixir Formatter, :open_api_spex can be added to the :import_deps list in the .formatter.exs file of your project to make parentheses of the macros optional.

.formatter.exs:

[
  import_deps: [:open_api_spex]
]

parameters

parameters is a keyword list (or map) of request parameters (not body parameters). They each represent the OpenAPI Parameter Object.

There is a convenient shortcut :type for base data types supported by open api

parameters: [
  id: [in: :query, type: :integer, required: true, description: "User ID", example: 1001]
]

This is equivalent to:

parameters: [
  id: [in: :query, schema: %OpenApiSpex.Schema{type: :integer}, required: true, description: "User ID", example: 1001]
]

The keyword value is the parameter name. Each value in the keyword list correlates to a field in the OpenAPI ParameterObject.

request_body

The request_body defines the OpenAPI RequestBodyObject.

The request_body takes a tuple that is 2-4 elements in length. The elements of the tuple are:

  1. The RequestBody description field.
  2. The RequestBody content field, consisting of a mapping of content types to their MediaType objects, or a simple content type string (e.g., "application/json").
    content: "application/json"
    Or:
    content: %{"application/text" => [example: "some text!"]}
    Or:
    content: %{"application/text" => [%OpenApiSpex.MediaType{example: "some text!"}]}
  3. The default schema of the RequestBody.
  4. A keyword list of options.

responses

The responses key defines the OpenAPI Responses Object

The responses value is a keyword list or map that maps the HTTP status to a ResponseObject.

If the the responses is defined using keyword list syntax, the HTTP status codes can be replaced with their text equivalents:

responses: [
  ok: {"User response", "application/json", MyAppWeb.Schemas.UserResponse},
  unprocessable_entity: {"Bad request parameters", "application/json", MyAppWeb.Schemas.BadRequestParameters},
  not_found: {"Not found", "application/json", MyAppWeb.Schemas.NotFound}
]

The full set of atom keys are defined in Plug.Conn.Status.code/1.

Alternately, the HTTP status codes can be specified directly:

responses: %{
  200 => {"User response", "application/json", MyAppWeb.Schemas.UserResponse},
  422 => {"Bad request parameters", "application/json", MyAppWeb.Schemas.BadRequestParameters},
  404 => {"Not found", "application/json", MyAppWeb.Schemas.NotFound}
}

The ResponseObject is represented as a tuple that is 2-4 elements in length. The elements of the tuple are:

  1. The ResponseObject description field.
  2. The ResponseObject content field, consisting of a mapping of content types to their MediaType objects, or a simple content type string (e.g., "application/json").
    content: %{"application/json" => [example: "{[]}"]}
    Or:
    content: "application/json"
  3. The default schema of the response body.
  4. A keyword list of options to add to the OpenApiSpex.Response or OpenApiSpex.MediaType structs that are generated.

Summary

Functions

Defines an Operation spec for a controller action.

Define an Operation for a controller action.

Defines security requirements shared by all operations defined in a controller.

Defines a list of tags that all operations in a controller will share.

Functions

Link to this macro

operation(action, spec)

View Source (macro)
@spec operation(action :: atom(), spec :: Keyword.t()) :: any()

Defines an Operation spec for a controller action.

Example

operation :update,
  summary: "Update user",
  description: "Updates a user record from the given ID path parameter and request body parameters.",
  parameters: [
    id: [
      in: :path,
      description: "User ID",
      type: :integer,
      example: 1001
    ]
  ],
  request_body: {"User params", "application/json", UserParams},
  responses: [
    ok: {"User response", "application/json", UserResponse}
  ],
  security: [%{}, %{"petstore_auth" => ["write:pets", "read:pets"]}],
  tags: ["users"]

Options

These options correlate to the Operation fields specified in the Open API spec. One difference however, is that the fields defined in Open API use camelCase naming, while the fields used in ControllerSpecs use snake_case to match Elixir's convention.

  • summary The operation summary

  • parameters The endpoint's parameters. The syntax for parameters can take multiple forms:

    • The common form is a keyword list, where each key is the parameter name, and the value is a keyword list of options that correlate to the fields in an Open API Parameter Object. For example:

        parameters: [
          id: [
            in: :path,
            description: "User ID",
            type: :integer,
            example: 1001
          ]
        ]
    • A parameters list can also contain references to parameter schemas. There are two ways to do that:

      parameters: [
        "$ref": "#/components/parameters/user_id"
        # or
        %OpenApiSpex.Reference{"$ref": "#/components/parameters/user_id"}
      ]
  • request_body The endpoint's request body. There are multiple ways to specify a request body:

    • A three or four-element tuple:
        request_body: {
          "User update request body",
          "application/json",
          UserUpdateRequest,
          required: true
        }
      The tuple consists of the following:
      1. The description
      2. The content-type
      3. An Open API schema. This can be a schema module that implements the OpenApiSpex.Schema behaviour, or an OpenApiSpex.Schema struct.
      4. A optional keyword list of options. There is only one option available, and that is required: boolean.
  • responses The endpoint's responses, for each HTTP status code the endpoint may respond with. Multiple syntaxes are supported:

    • A common syntax is a keyword list, where each key is the textual name of an HTTP status code. For example:

        [
          ok: {"User response", "application/json", User},
          not_found: {"User not found", "application/json", NotFound}
        ]

      The list of names and their code mappings is defined in Plug.Conn.Status.code/1.

    • If a map is used, the keys can either be the same atom keys used in the keyword syntax (%{ok: ...}), or they can be integers representing the HTTP status code directly:

        responses: %{
          200 => {"User response", "application/json", User},
          404 => {"User not found", "application/json", NotFound}
        }
    • Each response can be a three-element tuple:

        responses: [
          ok: {"User response", "application/json", User}
          # Or
          ok: {"User response", "application/json", %OpenApiSpex.Schema{...}}
        ]

      This tuple consists of:

      1. A Description string
      2. A content-type string
      3. An Open API schema. This can be a schema module that implements the OpenApiSpex.Schema behaviour, or an OpenApiSpex.Schema struct.
      4. An optional Keyword list with the following optional key/values: a. example: an example string b. examples: a list of example strings c. headers: a Map with string keys defining the header name and an OpenApiSpex.Header struct as a value.
    • If the response represents an empty response, the definition value can be a single string representing the response description. For example:

        responses: [
          no_content: "Empty response"
        ]
    • A response can also be defined as an OpenApiSpex.RequestBody struct. In fact, all response body syntaxes resolve to this struct.

  • Additional fields: There are other Operation fields that can be specified that are not described here. See OpenApiSpex.Operation for all the fields.

Link to this function

operation_spec(module, action, spec)

View Source

Define an Operation for a controller action.

See OpenApiSpex.ControllerSpecs for usage and examples.

Link to this macro

security(requirements)

View Source (macro)
@spec security([%{required(String.t()) => [String.t()]}]) :: any()

Defines security requirements shared by all operations defined in a controller.

See Security Requirement Object spec and OpenApiSpex.SecurityRequirement for more information.

@spec tags(tags :: [String.t()]) :: any()

Defines a list of tags that all operations in a controller will share.

Example

tags ["users"]

All operations defined in the controller will inherit the tags specified by this call. If an operation defines its own tags, the tags in this call will be appended to the operation's tags.