View Source Ewebmachine.Handlers (ewebmachine v2.3.2)
Implement the functions described below to make decisions in the HTTP decision tree :
service_available/2
resource_exists/2
is_authorized/2
forbidden/2
allow_missing_post/2
malformed_request/2
uri_too_long/2
known_content_type/2
valid_content_headers/2
valid_entity_length/2
options/2
allowed_methods/2
known_methods/2
content_types_provided/2
content_types_accepted/2
delete_resource/2
delete_completed/2
post_is_create/2
create_path/2
base_uri/2
process_post/2
language_available/2
charsets_provided/2
encodings_provided/2
variances/2
is_conflict/2
multiple_choices/2
previously_existed/2
moved_permanently/2
moved_temporarily/2
last_modified/2
expires/2
generate_etag/2
validate_content_checksum/2
ping/2
- Body-producing function, see
to_html/2
(but any function name can be used, as referenced bycontent_types_provided/2
- POST/PUT processing function, see
from_json/2
(but any function name can be used, as referenced bycontent_types_accepted/2
All the handlers have the same signature :
(conn :: Plug.Conn.t,state :: any)->{response :: any | {:halt,200..599},conn :: Plug.Conn.t, state :: any}
where every handler implementation :
- can change or halt the plug
conn
passed as argument - can change the user state object passed from on handler to another in its arguments
- returns something which will make decision in the HTTP decision tree (see documentation of functions in this module to see expected results and effects)
- can return
{:halt,200..599}
to end the ewebmachine automate execution, but do nothalt
theconn
, so the plug pipeline can continue.
So each handler implementation is actually a "plug" returning a response giving information allowing to make the good response code and path in the HTTP specification.
Usage
The following modules will help you to construct these handlers and use them :
Ewebmachine.Builder.Handlers
gives you macros and helpers to define the handlers and automatically create the plug to add them to yourconn.private[:resource_handlers]
Ewebmachine.Plug.Run
run the HTTP decision tree executing the handler implementations described in itsconn.private[:resource_handlers]
. The initial userstate
is taken inconn.private[:machine_init]
Summary
Functions
If the resource accepts POST requests to nonexistent resources, then this should return true
.
If a Method not in this list is requested, then a 405 Method Not Allowed will be sent. Note that these are all-caps Strings (binary).
The base URI used in the location header on resource creation (when
post_is_create
is true
), will be prepended to the create_path
If this is anything other than the atom :no_charset
, it must be a
{key,value}
Enumerable where key
is the charset and value
is a
callable function in the resource which will be called on the
produced body in a GET and ensure that it is in Charset.
This is used similarly to content_types_provided, except that it is
for incoming resource representations -- for example, PUT requests.
Handler functions usually want to use Plug.read_body(conn)
to
access the incoming request body.
This should return a key value tuple enumerable where the key is the content-type format and the value is an atom naming the function which can provide a resource representation in that media type. Content negotiation is driven by this return value. For example, if a client request includes an Accept header with a value that does not appear as a first element in any of the return tuples, then a 406 Not Acceptable will be sent.
This will be called on a POST request if post_is_create
returns
true. It is an error for this function not to produce a Path if
post_is_create returns true. The Path returned should be a valid
URI part.
This is only called after a successful delete_resource
call, and
should return false
if the deletion was accepted but cannot yet be
guaranteed to have finished.
This is called when a DELETE request should be enacted, and should
return true
if the deletion succeeded.
This must be a {key,value}
Enumerable where key
is a valid
content encoding and value
is a callable function in the resource
which will be called on the produced body in a GET and ensure that
it is so encoded. One useful setting is to have the function check
on method, and on GET requests return
If not nil
, set the expires header
Last handler, always called. Response is ignored except if it is a halt
.
Returning true will result in 403 Forbidden.
Example POST/PUT processing function, function atom name must be referenced
in content_types_accepted/2
.
If not nil
, it will be used for the ETag header and
for comparison in conditional requests.
If this returns anything other than true
, the response will be
401 Unauthorized
. The return value will be used as the value in
the WWW-Authenticate
header, for example Basic realm="Webmachine"
.
If this returns true
, the client will receive a 409 Conflict.
Returning false will result in 415 Unsupported Media Type.
Override the known methods accepted by your automate
return false if language in
Plug.Conn.get_resp_header(conn,"accept-language")
is not
available.
If this returns a datetime()
({{day,month,year},{h,m,s}}
, it
will be used for the Last-Modified
header and for comparison in
conditional requests.
Returning true will result in 400 Bad Request.
If this returns {true, uri}
, the client will receive a 301 Moved Permanently
with uri
in the Location header.
If this returns {true, uri}
, the client will receive a 307 Temporary Redirect
with uri
in the Location header.
If this returns true
, then it is assumed that multiple
representations of the response are possible and a single one
cannot be automatically chosen, so a 300 Multiple Choices
will be
sent instead of a 200 OK
.
If the OPTIONS method is supported and is used, the return value of this function is expected to be a list of pairs representing header names and values that should appear in the response.
Must be present and returning pong
to prove that handlers are
well linked to the automate
If POST requests should be treated as a request to put content into
a (potentially new) resource as opposed to being a generic
submission for processing, then this function should return true.
If it does return true
, then create_path
will be called and the
rest of the request will be treated much like a PUT to the Path
entry returned by that call.
If this returns true
, the moved_permanently
and moved_temporarily
callbacks will be invoked to determine whether the response should
be 301 Moved Permanently
, 307 Temporary Redirect
, or 410 Gone
.
If post_is_create
returns false
, then this will be called to
process any POST requests. If it succeeds, it should return true
.
Returning non-true values will result in 404 Not Found
.
Returning non-true values will result in 503 Service Unavailable
.
Example body-producing function, function atom name must be referenced in content_types_provided/2
.
Returning true will result in 414 Request-URI Too Long.
Returning false will result in 501 Not Implemented.
Returning false will result in 413 Request Entity Too Large.
if content-md5
header exists:
If this function is implemented, it should return a list of strings
with header names that should be included in a given response's
Vary header. The standard conneg headers (Accept
, Accept-Encoding
,
Accept-Charset
, Accept-Language
) do not need to be specified here
as Webmachine will add the correct elements of those automatically
depending on resource behavior.
Types
Functions
If the resource accepts POST requests to nonexistent resources, then this should return true
.
Default: false
If a Method not in this list is requested, then a 405 Method Not Allowed will be sent. Note that these are all-caps Strings (binary).
Default: ["GET", "HEAD"]
The base URI used in the location header on resource creation (when
post_is_create
is true
), will be prepended to the create_path
@spec charsets_provided(conn(), state()) :: {:no_charset | [{String.Chars.t(), (binary() -> binary())}] | Enum.t() | halt(), conn(), state()}
If this is anything other than the atom :no_charset
, it must be a
{key,value}
Enumerable where key
is the charset and value
is a
callable function in the resource which will be called on the
produced body in a GET and ensure that it is in Charset.
Default: :no_charset
@spec content_types_accepted(conn(), state()) :: {[{String.Chars.t(), atom()}] | Enum.t() | halt(), conn(), state()}
This is used similarly to content_types_provided, except that it is
for incoming resource representations -- for example, PUT requests.
Handler functions usually want to use Plug.read_body(conn)
to
access the incoming request body.
Default: []
@spec content_types_provided(conn(), state()) :: {[{String.Chars.t(), atom()}] | Enum.t() | halt(), conn(), state()}
This should return a key value tuple enumerable where the key is the content-type format and the value is an atom naming the function which can provide a resource representation in that media type. Content negotiation is driven by this return value. For example, if a client request includes an Accept header with a value that does not appear as a first element in any of the return tuples, then a 406 Not Acceptable will be sent.
Default: [{"text/html", to_html}]
This will be called on a POST request if post_is_create
returns
true. It is an error for this function not to produce a Path if
post_is_create returns true. The Path returned should be a valid
URI part.
This is only called after a successful delete_resource
call, and
should return false
if the deletion was accepted but cannot yet be
guaranteed to have finished.
This is called when a DELETE request should be enacted, and should
return true
if the deletion succeeded.
@spec encodings_provided(conn(), state()) :: {[{String.Chars.t(), (binary() -> binary())}] | Enum.t() | halt(), conn(), state()}
This must be a {key,value}
Enumerable where key
is a valid
content encoding and value
is a callable function in the resource
which will be called on the produced body in a GET and ensure that
it is so encoded. One useful setting is to have the function check
on method, and on GET requests return:
[identity: &(&1), gzip: &:zlib.gzip/1]
as this is all that is needed to support gzip content encoding.
Default: [{"identity", fn X-> X end}]
@spec expires(conn(), state()) :: {nil | {{day :: integer(), month :: integer(), year :: integer()}, {hour :: integer(), min :: integer(), sec :: integer()}} | halt(), conn(), state()}
If not nil
, set the expires header
Default: nil
Last handler, always called. Response is ignored except if it is a halt
.
Returning true will result in 403 Forbidden.
Default: false
Example POST/PUT processing function, function atom name must be referenced
in content_types_accepted/2
.
It will be called when the request is PUT
or when the
request is POST
and post_is_create
returns true.
If not nil
, it will be used for the ETag header and
for comparison in conditional requests.
Default: nil
If this returns anything other than true
, the response will be
401 Unauthorized
. The return value will be used as the value in
the WWW-Authenticate
header, for example Basic realm="Webmachine"
.
Default: true
If this returns true
, the client will receive a 409 Conflict.
Default : false
Returning false will result in 415 Unsupported Media Type.
Default: true
Override the known methods accepted by your automate
Default: ["GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", "OPTIONS"]
return false if language in
Plug.Conn.get_resp_header(conn,"accept-language")
is not
available.
@spec last_modified(conn(), state()) :: {nil | {{day :: integer(), month :: integer(), year :: integer()}, {hour :: integer(), min :: integer(), sec :: integer()}} | halt(), conn(), state()}
If this returns a datetime()
({{day,month,year},{h,m,s}}
, it
will be used for the Last-Modified
header and for comparison in
conditional requests.
Default: nil
Returning true will result in 400 Bad Request.
Default: false
If this returns {true, uri}
, the client will receive a 301 Moved Permanently
with uri
in the Location header.
Default: false
If this returns {true, uri}
, the client will receive a 307 Temporary Redirect
with uri
in the Location header.
Default: false
If this returns true
, then it is assumed that multiple
representations of the response are possible and a single one
cannot be automatically chosen, so a 300 Multiple Choices
will be
sent instead of a 200 OK
.
Default: false
If the OPTIONS method is supported and is used, the return value of this function is expected to be a list of pairs representing header names and values that should appear in the response.
Must be present and returning pong
to prove that handlers are
well linked to the automate
If POST requests should be treated as a request to put content into
a (potentially new) resource as opposed to being a generic
submission for processing, then this function should return true.
If it does return true
, then create_path
will be called and the
rest of the request will be treated much like a PUT to the Path
entry returned by that call.
Default: false
If this returns true
, the moved_permanently
and moved_temporarily
callbacks will be invoked to determine whether the response should
be 301 Moved Permanently
, 307 Temporary Redirect
, or 410 Gone
.
Default: false
If post_is_create
returns false
, then this will be called to
process any POST requests. If it succeeds, it should return true
.
Returning non-true values will result in 404 Not Found
.
Default: true
Returning non-true values will result in 503 Service Unavailable
.
Default: true
Example body-producing function, function atom name must be referenced in content_types_provided/2
.
- If the result is an
Enumerable
ofiodata
, then the HTTP response will be a chunk encoding response where each chunk on element of the enumeration. - If the result is an iodata, then it is used as the HTTP response body
Returning true will result in 414 Request-URI Too Long.
Default: false
Returning false will result in 501 Not Implemented.
Default: true
Returning false will result in 413 Request Entity Too Large.
Default: false
@spec validate_content_checksum(conn(), state()) :: {:not_validated | boolean() | halt(), conn(), state()}
if content-md5
header exists:
- If
:not_validated
, test if input body validatecontent-md5
, - if return
false
, then return a bad request
Useful if content-md5 validation does not imply only raw md5 hash
If this function is implemented, it should return a list of strings
with header names that should be included in a given response's
Vary header. The standard conneg headers (Accept
, Accept-Encoding
,
Accept-Charset
, Accept-Language
) do not need to be specified here
as Webmachine will add the correct elements of those automatically
depending on resource behavior.
Default : []