Ewebmachine.Handlers
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↑
allow_missing_post(conn, state) | If the resource accepts POST requests to nonexistent resources, then this should return |
allowed_methods(conn, state) | 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) |
base_uri(conn, state) | The base URI used in the location header on resource creation (when |
charsets_provided(conn, state) | If this is anything other than the atom |
content_types_accepted(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 |
content_types_provided(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 |
create_path(conn, state) | This will be called on a POST request if |
delete_completed(conn, state) | This is only called after a successful |
delete_resource(conn, state) | This is called when a DELETE request should be enacted, and should return |
encodings_provided(conn, state) | This must be a |
expires(conn, state) | If not |
finish_request(conn, state) | Last handler, always called. Response is ignored except if it is a |
forbidden(conn, state) | Returning true will result in 403 Forbidden |
from_json(conn, state) | Example POST/PUT processing function, function atom name must be referenced in |
generate_etag(conn, state) | If not |
is_authorized(conn, state) | If this returns anything other than |
is_conflict(conn, state) | If this returns |
known_content_type(conn, state) | Returning false will result in 415 Unsupported Media Type |
known_methods(conn, state) | Override the known methods accepted by your automate |
language_available(conn, state) | return false if language in |
last_modified(conn, state) | If this returns a |
malformed_request(conn, state) | Returning true will result in 400 Bad Request |
moved_permanently(conn, state) | If this returns |
moved_temporarily(conn, state) | If this returns |
multiple_choices(conn, state) | If this returns |
options(conn, state) | 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 |
ping(conn, state) | Must be present and returning |
post_is_create(conn, state) | 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 |
previously_existed(conn, state) | If this returns |
process_post(conn, state) | If |
resource_exists(conn, state) | Returning non-true values will result in |
service_available(conn, state) | Returning non-true values will result in |
to_html(conn, state) | Example body-producing function, function atom name must be referenced in |
uri_too_long(conn, state) | Returning true will result in 414 Request-URI Too Long |
valid_content_headers(conn, state) | Returning false will result in 501 Not Implemented |
valid_entity_length(conn, state) | Returning false will result in 413 Request Entity Too Large |
validate_content_checksum(conn, state) | if |
variances(conn, state) | 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 ( |
Types ↑
conn :: Plug.Conn.t
state :: any
halt :: {:halt, 200 .. 599}
Functions
Specs:
If the resource accepts POST requests to nonexistent resources, then this should return true
.
Default: false
Specs:
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"]
Specs:
The base URI used in the location header on resource creation (when post_is_create
is true
), will be prepended to the create_path
Specs:
- 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
Specs:
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: []
Specs:
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}]
Specs:
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.
Specs:
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.
Specs:
This is called when a DELETE request should be enacted, and should return true
if the deletion succeeded.
Specs:
- 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}]
Specs:
- 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
Specs:
Last handler, always called. Response is ignored except if it is a halt
.
Specs:
Returning true will result in 403 Forbidden.
Default: false
Specs:
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.
Specs:
If not nil
, it will be used for the ETag header and for comparison in conditional requests.
Default: nil
Specs:
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
Specs:
If this returns true
, the client will receive a 409 Conflict.
Default : false
Specs:
Returning false will result in 415 Unsupported Media Type.
Default: true
Specs:
Override the known methods accepted by your automate
Default: ["GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", "OPTIONS"]
Specs:
return false if language in Plug.Conn.get_resp_header(conn,"accept-language")
is not available.
Specs:
- 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
Specs:
Returning true will result in 400 Bad Request.
Default: false
Specs:
If this returns {true, uri}
, the client will receive a 301 Moved Permanently
with uri
in the Location header.
Default: false
Specs:
If this returns {true, uri}
, the client will receive a 307 Temporary Redirect
with uri
in the Location header.
Default: false
Specs:
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
Specs:
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.
Specs:
Must be present and returning pong
to prove that handlers are well linked to the automate
Specs:
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
Specs:
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
Specs:
If post_is_create
returns false
, then this will be called to process any POST requests. If it succeeds, it should return true
.
Specs:
Returning non-true values will result in 404 Not Found
.
Default: true
Specs:
Returning non-true values will result in 503 Service Unavailable
.
Default: true
Specs:
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
Specs:
Returning true will result in 414 Request-URI Too Long.
Default: false
Specs:
Returning false will result in 501 Not Implemented.
Default: true
Specs:
Returning false will result in 413 Request Entity Too Large.
Default: false
Specs:
if content-md5
header exists: - If :not_validated
, test if input body validate content-md5
, - if return false
, then return a bad request
Useful if content-md5 validation does not imply only raw md5 hash
Specs:
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 : []