|
WebmachineResources
How to write the functions that make up a resource.
All webmachine resources should include the webmachine resource library: -include_lib("webmachine/include/webmachine.hrl").All webmachine resources should define and export init/1, which will receive a configuration property list from the dispatcher as its argument. This function should, if successful, return {ok, Context}. Context is any term, and will be threaded through all of the other webmachine resource functions. All webmachine resource functions take two arguments, conventionally referred to as (ReqProps, Context). ReqProps is accessible via two macros from the above library: ?REQ(ReqProps) -> Req Req is a webmachine_request module instance, with functions that can be called to inquire about the request in process, such as Req:get_header_value("X-My-Header"). ?PATH(ReqProps) -> Path Path is a string (erlang list) indicates the portion of the Request URI that was consumed by a '*' pathterm in the dispatcher. Context is any term, and is used to pass information along through the various resource functions. Each resource function will receive a Context and return a Context and nothing else in webmachine will care about the form or content of Context, so resources can use this in any way they see fit to manage the transient data created and used in the course of a single request. All webmachine resource functions are expected to return a two-tuple where the first element is function-specific and the second element is a Context term. There are over 30 resource functions you can define, but nearly all can be omitted as they have reasonable defaults. Each function is described below, showing the acceptable values that may be in the first element of the return tuple. The default value is the one listed first, and will be used if a resource does not define and export the function. Any function which has no description is optional and the effect of its return value should be evident from examining the diagram. resource_exists -> true | _ Returning non-true values will result in 404 Not Found. service_available -> true | _ is_authorized -> true | AuthHead If this returns anything other than true, the response will be 401 Unauthorized. The AuthHead return value will be used in the WWW-Authenticate header. forbidden -> false | _ allow_missing_post -> false | _ If the resource accepts POST requests to nonexistent resources, then this should return true. malformed_request -> false | _ uri_too_long -> false | _ known_content_type -> true | _ valid_content_headers -> true | _ valid_entity_length -> true | _ options -> [] | [Header] 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. allowed_methods -> ['GET', 'HEAD'] | [Method] If a Method not in this list is requested, then a 405 Method Not Allowed will be sent. Note that these are all-caps and are atoms. (single-quoted) delete_resource -> false | _ This is called when a DELETE request should be enacted, and should return true if the deletion succeeded. delete_completed -> true | _ 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. post_is_create -> false | _ 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. create_path -> undefined | Path This will be called on a POST request if post_is_create returns true. If this can occur, then the Path returned should be a valid URI part following the dispatcher prefix. That Path will replace the previous one in the path value of ReqProps for all subsequent resource function calls in the course of this request. process_post -> false | _ If post_is_create returns false, then this will be called to process any POST requests. If it succeeds, it should return true. content_types_provided -> [{"text/html", to_html}] | [{Mediatype, Handler}] This should return a list of pairs where each pair is of the form {Mediatype, Handler} where Mediatype is a string of content-type format and the Handler 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. content_types_accepted -> [] | [{Mediatype, Handler}] This is used similarly to content_types_provided, except that it is for incoming resource representations -- for example, PUT requests. charsets_provided -> no_charset | [{Charset, CharsetConverter}] If this is anything other than the atom no_charset, it must be a list of pairs where each pair is of the form Charset, Converter where Charset is a string naming a charset and Converter 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. encodings_provided -> [{"identity", fun(X) -> X end}] | [{Encoding, Encoder}] This must be a list of pairs where each pair is of the form Encoding, Encoder where Encoding is a string naming a valid content encoding and Encoder 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", fun(X) -> X end}, {"gzip", fun(X) -> zlib:gzip(X) end}] -- this is all that is needed to support gzip content encoding. variances -> [] | [HeaderName] 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. is_conflict -> false | _ If this returns true, the client will receive a 409 Conflict. multiple_choices -> 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. previously_existed -> false | _ moved_permanently -> false | {true, MovedURI} | _ moved_temporarily -> false | {true, MovedURI} | _ last_modified -> undefined | {{YYYY,MM,DD},{Hour,Min,Sec}} expires -> undefined | {{YYYY,MM,DD},{Hour,Min,Sec}} generate_etag -> undefined | ETag If this returns a value, it will be used as the value of the ETag header and for comparison in conditional requests. The above are all of the supported predefined resource functions. In addition to whichever of them you wish to use, you also must define all of the functions named in the return values of your content_types_provided and content_types_accepted functions. The functions named in content_types_provided are expected to return {Body, Context} where Body is the (binary or iolist) content which should make up the response body. The functions named in content_types_accepted are expected to return {true. Context} if they succeed. |