OpenApiSpex (open_api_spex v3.22.0)

View Source

Provides the entry-points for defining schemas, validating and casting.

Summary

Functions

Add more schemas to an existing OpenApi struct.

Get casted body params from a Plug.Conn. If the conn has not been yet casted nil is returned.

Build a Schema struct from the given keyword list.

Cast params to conform to a OpenApiSpex.Schema.

Cast all params in Plug.Conn to conform to the schemas for OpenApiSpex.Operation.

Cast and validate a value against a given Schema.

Cast and validate a value against a given Schema belonging to a given OpenApi spec.

Raises compile time errors for improperly defined schemas.

Get casted params from a Plug.Conn. If the conn has not been yet casted nil is returned.

Resolve a schema or reference to a schema.

Adds schemas to the api spec from the modules specified in the Operations.

Creates an %OpenApi{} struct from a map.

Validate params against OpenApiSpex.Schema.

Validate all params in Plug.Conn against OpenApiSpex.Operation parameter and requestBody schemas.

Validate the compiled schema's properties to ensure the schema is not improperly defined. Only errors which would cause a given schema to always fail should be raised here.

Used for validating the schema at compile time, otherwise we're forced to raise errors for improperly defined schemas at runtime.

Types

cast_opt()

@type cast_opt() ::
  {:replace_params, boolean()}
  | {:apply_defaults, boolean()}
  | {:read_write_scope, read_write_scope()}

read_write_scope()

@type read_write_scope() :: nil | :read | :write

Functions

add_parameter_content_parser(spec, content_type, parser)

@spec add_parameter_content_parser(
  OpenApiSpex.OpenApi.t(),
  content_type | [content_type],
  parser :: module()
) :: OpenApiSpex.OpenApi.t()
when content_type: String.t() | Regex.t()

add_schemas(spec, schema_modules)

@spec add_schemas(OpenApiSpex.OpenApi.t(), [module()]) :: OpenApiSpex.OpenApi.t()

Add more schemas to an existing OpenApi struct.

This is useful when the schemas are not used by a Plug or Controller. Perhaps they're used by a Phoenix Channel.

Example

defmodule MyAppWeb.ApiSpec do
  def spec do
    %OpenApiSpex.OpenApi{
      # ...
      paths: OpenApiSpex.Paths.from_router(MyAppWeb.Router)
      # ...
    }
    |> OpenApiSpex.resolve_schema_modules()
    |> OpenApiSpex.add_schemas([
      MyAppWeb.Schemas.Message,
      MyAppWeb.Schemas.Channel
    ])
  end
end

body_params(conn)

@spec body_params(Plug.Conn.t()) :: nil | map()

Get casted body params from a Plug.Conn. If the conn has not been yet casted nil is returned.

build_schema(body, opts \\ [])

Build a Schema struct from the given keyword list.

This function adds functionality over defining a schema with struct literal sytax using %OpenApiSpex.Struct{}:

  • When the :module option is given, the :"x-struct and :title attributes of the schema will be autopopulated based on the given module
  • Validations are performed on the schema to ensure it is correct.

Options

  • :module (module) - A module in the application that the schema should be associated with.

cast(spec, schema, params)

This function is deprecated. Use OpenApiSpex.cast_value/3 or cast_value/2 instead.
@spec cast(
  OpenApiSpex.OpenApi.t(),
  OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t(),
  any()
) ::
  {:ok, any()} | {:error, String.t()}

Cast params to conform to a OpenApiSpex.Schema.

See OpenApiSpex.Schema.cast/3 for additional examples and details.

cast(spec, operation, conn, content_type \\ nil)

This function is deprecated. Use OpenApiSpex.cast_and_validate/3 instead.
@spec cast(
  OpenApiSpex.OpenApi.t(),
  OpenApiSpex.Operation.t(),
  Plug.Conn.t(),
  content_type | nil
) ::
  {:ok, Plug.Conn.t()} | {:error, String.t()}
when content_type: String.t()

Cast all params in Plug.Conn to conform to the schemas for OpenApiSpex.Operation.

Returns {:ok, Plug.Conn.t} with params and body_params fields updated if successful, or {:error, reason} if casting fails.

content_type may optionally be supplied to select the requestBody schema.

cast_and_validate(spec, operation, conn, content_type \\ nil, opts \\ [])

@spec cast_and_validate(
  OpenApiSpex.OpenApi.t(),
  OpenApiSpex.Operation.t(),
  Plug.Conn.t(),
  content_type :: nil | String.t(),
  opts :: [cast_opt()]
) :: {:error, [OpenApiSpex.Cast.Error.t()]} | {:ok, Plug.Conn.t()}

cast_value(value, schema)

Cast and validate a value against a given Schema.

cast_value(value, schema, spec, opts \\ [])

Cast and validate a value against a given Schema belonging to a given OpenApi spec.

error!(error, schema, details \\ [])

@spec error!(atom(), OpenApiSpex.Schema.t(), keyword()) :: no_return()

Raises compile time errors for improperly defined schemas.

error_message(error)

params(conn)

@spec params(Plug.Conn.t()) :: nil | map()

Get casted params from a Plug.Conn. If the conn has not been yet casted nil is returned.

path_to_string(error)

resolve_schema(schema, schemas)

Resolve a schema or reference to a schema.

resolve_schema_modules(spec)

@spec resolve_schema_modules(OpenApiSpex.OpenApi.t()) :: OpenApiSpex.OpenApi.t()

Adds schemas to the api spec from the modules specified in the Operations.

Eg, if the response schema for an operation is defined with:

responses: %{
  200 => Operation.response("User", "application/json", UserResponse)
}

Then the UserResponse.schema() function will be called to load the schema, and a Reference to the loaded schema will be used in the operation response.

See OpenApiSpex.schema/2 macro for a convenient syntax for defining schema modules.

Known Issues

Resolving schemas expects the schema title to be unique for the generated references to be unique.

For schemas defined with the OpenApiSpex.schema/2 macro, the title is automatically set to the last part of module name. For example MyAppWeb.Schemas.User will have the title "User", and MyAppWeb.OtherSchemas.User will also have the title "User" which can lead to conflicts.

The recommendation is to set the title explicitly in the schema definition.

schema(body, opts \\ [])

(macro)

Declares a struct based OpenApiSpex.Schema

  • defines the schema/0 callback
  • ensures the schema is linked to the module by "x-struct" extension property
  • defines a struct with keys matching the schema properties
  • defines a @type t for the struct
  • derives a Jason.Encoder and/or Poison.Encoder for the struct

See OpenApiSpex.Schema for additional examples and details.

Example

require OpenApiSpex

defmodule User do
  OpenApiSpex.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", pattern: ~r/[a-zA-Z][a-zA-Z0-9_]+/},
      email: %Schema{type: :string, description: "Email address", format: :email},
      inserted_at: %Schema{type: :string, description: "Creation timestamp", format: :'date-time'},
      updated_at: %Schema{type: :string, description: "Update timestamp", format: :'date-time'}
    },
    required: [:name, :email],
    example: %{
      "id" => 123,
      "name" => "Joe User",
      "email" => "joe@gmail.com",
      "inserted_at" => "2017-09-12T12:34:55Z",
      "updated_at" => "2017-09-13T10:11:12Z"
    }
  }
end

Example

This example shows the :struct? and :derive? options that may be passed to schema/2:

defmodule MyAppWeb.Schemas.User do
  require OpenApiSpex
  alias OpenApiSpex.Schema

  OpenApiSpex.schema(
    %{
      type: :object,
      properties: %{
        name: %Schema{type: :string}
      }
    },
    struct?: false,
    derive?: false
  )
end

Options

  • :struct? (boolean) - When false, prevents the automatic generation of a struct definition for the schema module.
  • :derive? (boolean) When false, prevents the automatic generation of a @derive call for either Poison.Encoder or Jason.Encoder. Using this option can prevent "... protocol has already been consolidated ..." compiler warnings.

schema_from_map(map)

Creates an %OpenApi{} struct from a map.

This is useful when importing existing JSON or YAML encoded schemas.

Example

# Importing an existing JSON encoded schema
open_api_spec_from_json = "encoded_schema.json"
  |> File.read!()
  |> Jason.decode!()
  |> OpenApiSpex.OpenApi.Decode.decode()

# Importing an existing YAML encoded schema
open_api_spec_from_yaml = "encoded_schema.yaml"
  |> YamlElixir.read_all_from_file!()
  |> OpenApiSpex.OpenApi.Decode.decode()

title_from_module(module)

validate(spec, schema, params)

This function is deprecated. Use OpenApiSpex.cast_value/3 or cast_value/2 instead.
@spec validate(
  OpenApiSpex.OpenApi.t(),
  OpenApiSpex.Schema.t() | OpenApiSpex.Reference.t(),
  any()
) ::
  :ok | {:error, String.t()}

Validate params against OpenApiSpex.Schema.

See OpenApiSpex.Schema.validate/3 for examples of error messages.

validate(spec, operation, conn, content_type \\ nil)

This function is deprecated. Use OpenApiSpex.cast_and_validate/4 instead.
@spec validate(
  OpenApiSpex.OpenApi.t(),
  OpenApiSpex.Operation.t(),
  Plug.Conn.t(),
  content_type | nil
) ::
  :ok | {:error, String.t()}
when content_type: String.t()

Validate all params in Plug.Conn against OpenApiSpex.Operation parameter and requestBody schemas.

content_type may be optionally supplied to select the requestBody schema.

validate_compiled_schema(schema)

Validate the compiled schema's properties to ensure the schema is not improperly defined. Only errors which would cause a given schema to always fail should be raised here.

validate_compiled_schema(arg, schema)

Used for validating the schema at compile time, otherwise we're forced to raise errors for improperly defined schemas at runtime.