plug_rest v0.5.0 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 : :undefined
forbidden : false
generate_etag : :undefined
is_authorized : true
is_conflict : false
known_methods : ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
languages_provided : skip
last_modified : :undefined
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
.
Summary
Types
content_handler :: {binary | media_type, atom}
media_type :: {binary, binary, %{optional(binary) => binary}}
Functions
Callbacks
Specs
allow_missing_post(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
allowed_methods(conn, state) ::
{[binary], conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
charsets_provided(conn, state) ::
{[binary], conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
content_types_accepted(conn, state) ::
{[content_handler], conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
content_types_provided(conn, state) ::
{[content_handler], conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
delete_completed(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
delete_resource(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
expires(conn, state) ::
{:calendar.datetime | binary | :undefined, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
forbidden(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
generate_etag(conn, state) ::
{binary | {:weak | :strong, binary}, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
init(conn, state) ::
{:ok, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
is_authorized(conn, state) ::
{true | {false, binary}, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
is_conflict(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
known_methods(conn, state) ::
{[binary], conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
languages_provided(conn, state) ::
{[binary], conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
last_modified(conn, state) ::
{:calendar.datetime, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
malformed_request(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
moved_permanently(conn, state) ::
{{true, binary} | false, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
moved_temporarily(conn, state) ::
{{true, binary} | false, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
multiple_choices(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
options(conn, state) ::
{:ok, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
previously_existed(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
resource_exists(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
service_available(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
test(conn, state) :: {[binary], conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
uri_too_long(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
valid_content_headers(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
valid_entity_length(conn, state) ::
{boolean, conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any
Specs
variances(conn, state) ::
{[binary], conn, state} |
{:stop, conn, state} when conn: %Plug.Conn{adapter: term, assigns: term, before_send: term, body_params: term, cookies: term, halted: term, host: term, method: term, owner: term, params: term, path_info: term, peer: term, port: term, private: term, query_params: term, query_string: term, remote_ip: term, req_cookies: term, req_headers: term, request_path: term, resp_body: term, resp_cookies: term, resp_headers: term, scheme: term, script_name: term, secret_key_base: term, state: term, status: term}, state: any