plug_rest v0.6.1 PlugRest.Resource behaviour

Define callbacks and REST semantics for a Resource behaviour

Based on Cowboy’s cowboy_rest module. It operates on a Plug connection and a handler module which implements one or more of the optional callbacks.

For example, the route:

resource "/users/:username", MyApp.UserResource

will invoke the init/2 function of MyApp.UserResource if it exists and then continue executing to determine the state of the resource. By default the resource must implement a to_html content handler which returns a “text/html” representation of the resource.

defmodule MyApp.UserResource do

  use PlugRest.Resource

  def init(conn, _state) do
    params = read_path_params(conn)
    username = params["username"]
    state = %{username: username}
    {:ok, conn, state}
  end

  def allowed_methods(conn, state) do
    {["GET"], conn, state}
  end

  def resource_exists(conn, %{username: username} = state)
    # Look up user
    state2 = %{state | name: "John Doe"}
    {true, conn, state2}
  end

  def content_types_provided(conn, state) do
    {[{"text/html", :to_html}], conn, state}
  end

  def to_html(conn, %{name: name} = state) do
    {"<p>Hello, #{name}</p>", conn, state}
  end
end

Each callback accepts a %Plug.Conn{} struct and the current state of the resource, and returns a three-element tuple of the form {value, conn, state}.

The resource callbacks are named below, along with their default values. Some functions are skipped if they are undefined. Others have no default value.

allowed_methods        : ["GET", "HEAD", "OPTIONS"]
allow_missing_post     : true
charsets_provided      : skip
content_types_accepted : none
content_types_provided : [{{"text", "html", %{}}, :to_html}]
delete_completed       : true
delete_resource        : false
expires                : nil
forbidden              : false
generate_etag          : nil
is_authorized          : true
is_conflict            : false
known_methods          : ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
languages_provided     : skip
last_modified          : nil
malformed_request      : false
moved_permanently      : false
moved_temporarily      : false
multiple_choices       : false
options                : :ok
previously_existed     : false
resource_exists        : true
service_available      : true
uri_too_long           : false
valid_content_headers  : true
valid_entity_length    : true
variances              : []

You must also define the content handler callbacks that are specified through content_types_accepted/2 and content_types_provided/2. It is conventional to name the functions after the content types that they handle, such as from_html and to_html.

The handler function which provides a representation of the resource must return a three element tuple of the form {body, conn, state}, where body is one of:

  • binary(), which will be sent with send_resp/3
  • {:chunked, Enum.t}, which will usesend_chunked/2*{:file, binary()}, which will use send_file/3

Summary

Functions

Executes the REST state machine with a connection and resource

Types

conn :: Plug.Conn.t
content_handler :: PlugRest.State.content_handler
etag :: PlugRest.State.etag
handler :: PlugRest.State.handler
media_type :: PlugRest.State.media_type
state :: PlugRest.State.t
status_code :: 200..503

Functions

upgrade(conn, handler, handler_state)

Specs

upgrade(conn, handler, any) :: conn

Executes the REST state machine with a connection and resource

Accepts a Plug.Conn struct, a PlugRest.Resource handler module, and an initial resource state, and executes the REST state machine.

Callbacks

allow_missing_post(conn, state) (optional)

Specs

allow_missing_post(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
allowed_methods(conn, state) (optional)

Specs

allowed_methods(conn, state) ::
  {[binary], conn, state} |
  {:stop, conn, state}
charsets_provided(conn, state) (optional)

Specs

charsets_provided(conn, state) ::
  {[binary], conn, state} |
  {:stop, conn, state}
content_types_accepted(conn, state) (optional)

Specs

content_types_accepted(conn, state) ::
  {[media_type], conn, state} |
  {:stop, conn, state}
content_types_provided(conn, state) (optional)

Specs

content_types_provided(conn, state) ::
  {[content_type_p], conn, state} |
  {:stop, conn, state}
delete_completed(conn, state) (optional)

Specs

delete_completed(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
delete_resource(conn, state) (optional)

Specs

delete_resource(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
expires(conn, state) (optional)

Specs

expires(conn, state) ::
  {:calendar.datetime | binary | nil, conn, state} |
  {:stop, conn, state}
forbidden(conn, state) (optional)

Specs

forbidden(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
generate_etag(conn, state) (optional)

Specs

generate_etag(conn, state) ::
  {binary | {:weak | :strong, binary}, conn, state} |
  {:stop, conn, state}
init(conn, state) (optional)

Specs

init(conn, state) ::
  {:ok, conn, state} |
  {:stop, conn, state}
is_authorized(conn, state) (optional)

Specs

is_authorized(conn, state) ::
  {true | {false, binary}, conn, state} |
  {:stop, conn, state}
is_conflict(conn, state) (optional)

Specs

is_conflict(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
known_methods(conn, state) (optional)

Specs

known_methods(conn, state) ::
  {[binary], conn, state} |
  {:stop, conn, state}
languages_provided(conn, state) (optional)

Specs

languages_provided(conn, state) ::
  {[binary], conn, state} |
  {:stop, conn, state}
last_modified(conn, state) (optional)

Specs

last_modified(conn, state) ::
  {:calendar.datetime, conn, state} |
  {:stop, conn, state}
malformed_request(conn, state) (optional)

Specs

malformed_request(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
moved_permanently(conn, state) (optional)

Specs

moved_permanently(conn, state) ::
  {{true, binary} | false, conn, state} |
  {:stop, conn, state}
moved_temporarily(conn, state) (optional)

Specs

moved_temporarily(conn, state) ::
  {{true, binary} | false, conn, state} |
  {:stop, conn, state}
multiple_choices(conn, state) (optional)

Specs

multiple_choices(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
options(conn, state) (optional)

Specs

options(conn, state) ::
  {:ok, conn, state} |
  {:stop, conn, state}
previously_existed(conn, state) (optional)

Specs

previously_existed(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
resource_exists(conn, state) (optional)

Specs

resource_exists(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
service_available(conn, state) (optional)

Specs

service_available(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
uri_too_long(conn, state) (optional)

Specs

uri_too_long(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
valid_content_headers(conn, state) (optional)

Specs

valid_content_headers(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
valid_entity_length(conn, state) (optional)

Specs

valid_entity_length(conn, state) ::
  {boolean, conn, state} |
  {:stop, conn, state}
variances(conn, state) (optional)

Specs

variances(conn, state) ::
  {[binary], conn, state} |
  {:stop, conn, state}