Browse Source

Update the cowboy_rest manual

Loïc Hoguin 8 years ago
parent
commit
f7094ad78f

+ 4 - 5
doc/src/guide/resource_design.asciidoc

@@ -164,11 +164,10 @@ implement the `moved_permanently` callback.
 
 
 === The request
 === The request
 
 
-Do we need to perform extra checks to make sure the request
-is valid? Cowboy will do many checks when receiving the
-request already, do we need more? Note that this only
-applies to the request-line and headers of the request,
-and not the body. Implement `malformed_request`.
+Do you need to read the query string? Individual headers?
+Implement `malformed_request` and do all the parsing and
+validation in this function. Note that the body should not
+be read at this point.
 
 
 May there be a request body? Will I know its size?
 May there be a request body? Will I know its size?
 What's the maximum size of the request body I'm willing
 What's the maximum size of the request body I'm willing

+ 448 - 309
doc/src/manual/cowboy_rest.asciidoc

@@ -6,287 +6,363 @@ cowboy_rest - REST handlers
 
 
 == Description
 == Description
 
 
-The `cowboy_rest` module implements REST semantics on top of
-the HTTP protocol.
+The module `cowboy_rest` implements the HTTP state machine.
 
 
-This module is a sub protocol that defines many callbacks
-be implemented by handlers. The `init/2` and `terminate/3`
-callbacks are common to all handler types and are documented
-in the manual for the link:cowboy_handler.asciidoc[cowboy_handler] module.
+Implementing REST handlers is not enough to provide a REST
+interface; this interface must also follow the REST
+constraints including HATEOAS (hypermedia as the engine
+of application state).
 
 
-All other callbacks are optional, though some may become
-required depending on the return value of previous callbacks.
+== Callbacks
+
+REST handlers implement the following interface:
+
+[source,erlang]
+----
+init(Req, State)
+    -> {cowboy_rest, Req, State}
+     | {cowboy_rest, Req, State, hibernate}
+     | {cowboy_rest, Req, State, timeout()}
+     | {cowboy_rest, Req, State, timeout(), hibernate}
+
+Callback(Req, State)
+    -> {Result, Req, State}
+     | {stop, Req, State}
 
 
-== Meta values
+terminate(Reason, Req, State) -> ok  %% optional
 
 
-charset = binary()::
-	Negotiated charset.
-	+
-	This value may not be defined if no charset was negotiated.
+Req    :: cowboy_req:req()
+State  :: any()
+Reason :: normal
+        | {crash, error | exit | throw, any()}
 
 
-language = binary()::
-	Negotiated language.
-	+
-	This value may not be defined if no language was negotiated.
+Callback - see below
+Result   - see below
+Default  - see below
+----
 
 
-media_type = {binary(), binary(), '*' | [{binary(), binary()}]}::
-	Negotiated media-type.
-	+
-	The media-type is the content-type, excluding the charset.
-	+
-	This value is always defined after the call to
-	`content_types_provided/2`.
+The `init/2` callback is common to all handlers. To switch
+to the REST handler behavior, it must return `cowboy_rest`
+as the first element of the tuple.
 
 
-== Terminate reasons
+The `Callback/2` above represents all the REST-specific
+callbacks. They are described in the following section
+of this manual. REST-specific callbacks differ by their
+name, semantics, result and default values. The default
+value is the one used when the callback has not been
+implemented. They otherwise all follow the same interface.
 
 
-The following values may be received as the terminate reason
-in the optional `terminate/3` callback.
+The `stop` tuple can be returned to stop REST processing.
+If no response was sent before then, Cowboy will send a
+'204 No Content'.
+
+The optional `terminate/3` callback will ultimately be called
+with the reason for the termination of the handler.
+Cowboy will terminate the process right after this. There
+is no need to perform any cleanup in this callback.
+
+The following terminate reasons are defined for loop handlers:
 
 
 normal::
 normal::
-	The connection was closed normally.
+    The handler terminated normally.
 
 
 {crash, Class, Reason}::
 {crash, Class, Reason}::
-	A crash occurred in the handler. `Class` and `Reason` can be
-	used to obtain more information about the crash. The function
-	`erlang:get_stacktrace/0` can also be called to obtain the
-	stacktrace of the process when the crash occurred.
+    A crash occurred in the handler. `Class` and `Reason` can be
+    used to obtain more information about the crash. The function
+    `erlang:get_stacktrace/0` can also be called to obtain the
+    stacktrace of the process when the crash occurred.
 
 
-== Callbacks
+== REST callbacks
 
 
-=== Callback(Req, State) -> {Value, Req, State} | {stop, Req, State}
+=== AcceptCallback
 
 
-Callback:: One of the REST callbacks described below.
-Req = cowboy_req:req():: The Req object.
-State = any():: Handler state.
-Value:: See the REST callbacks description below.
+// @todo The flowcharts should rename AcceptResource into AcceptCallback.
 
 
-Please see the REST callbacks description below for details
-on the `Value` type, the default value if the callback is
-not defined, and more general information on when the
-callback is called and what its intended use is.
+[source,erlang]
+----
+AcceptCallback(Req, State) -> {Result, Req, State}
 
 
-The `stop` tuple can be returned to stop REST processing.
-It is up to the resource code to send a reply before that,
-otherwise a `204 No Content` will be sent.
+Result  :: true | {true, URI :: iodata()} | false}
+Default  - crash
+----
+
+Process the request body.
+
+This function should create or update the resource using the
+request body.
 
 
-== REST callbacks description
+For PUT requests, the body is a representation of the resource
+that is being created or replaced.
+
+For POST requests, the body is typically application-specific
+instructions on how to process the request, but it may also
+be a representation of the resource. When creating a new
+resource with POST at a different location, return `{true, URI}`
+with `URI` the new location.
+
+For PATCH requests, the body is a series of instructions on
+how to update the resource. Patch files or JSON Patch are
+examples of such media types.
+
+A response body may be sent. The appropriate media type, charset
+and language for the response can be retrieved from the Req
+object using the `media_type`, `charset` and `language` keys,
+respectively. The body can be set using
+link:man:cowboy_req:set_resp_body(3)[cowboy_req:set_resp_body(3)].
 
 
 === allowed_methods
 === allowed_methods
 
 
-Methods:: all
-Value type:: [binary()]
-Default value:: `[<<"GET">>, <<"HEAD">>, <<"OPTIONS">>]`
+[source,erlang]
+----
+allowed_methods(Req, State) -> {Result, Req, State}
 
 
-Return the list of allowed methods.
+Result  :: [binary()]  %% case sensitive
+Default :: [<<"GET">>, <<"HEAD">>, <<"OPTIONS">>]
+----
 
 
-Methods are case sensitive. Standard methods are always uppercase.
+Return the list of allowed methods.
 
 
 === allow_missing_post
 === allow_missing_post
 
 
-Methods:: POST
-Value type:: boolean()
-Default value:: true
+[source,erlang]
+----
+allow_missing_post(Req, State) -> {Result, Req, State}
+
+Result  :: boolean()
+Default :: true
+----
 
 
 Return whether POST is allowed when the resource doesn't exist.
 Return whether POST is allowed when the resource doesn't exist.
 
 
 Returning `true` here means that a new resource will be
 Returning `true` here means that a new resource will be
-created. The URL to the created resource should also be
-returned from the `AcceptResource` callback.
+created. The URI for the newly created resource should be
+returned from the `AcceptCallback` function.
 
 
 === charsets_provided
 === charsets_provided
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: [binary()]
-Default behavior:: Skip to the next step if undefined.
+[source,erlang]
+----
+charsets_provided(Req, State) -> {Result, Req, State}
 
 
-Return the list of charsets the resource provides.
+Result  :: [binary()]  %% lowercase; case insensitive
+Default  - skip this step
+----
 
 
-The list must be ordered in order of preference.
+Return the list of charsets the resource provides in order
+of preference.
 
 
-If the accept-charset header was not sent, the first charset
-in the list will be selected. Otherwise Cowboy will select
-the most appropriate charset from the list.
+During content negotiation Cowboy will pick the most
+appropriate charset for the client. The client advertises
+charsets it prefers with the accept-charset header. When
+that header is missing, Cowboy picks the first charset
+from the resource.
 
 
-The chosen charset will be set in the `Req` object as the meta
-value `charset`.
+// @todo We should explain precisely how charsets are picked.
 
 
-While charsets are case insensitive, this callback is expected
-to return them as lowercase binary.
+Cowboy will add the negotiated `charset` to the Req object
+after this step completes:
+
+[source,erlang]
+----
+req() :: #{
+    charset => binary()  %% lowercase; case insensitive
+}
+----
 
 
 === content_types_accepted
 === content_types_accepted
 
 
-Methods:: POST, PUT, PATCH
-Value type:: [{binary() | {Type, SubType, Params}, AcceptResource}]
-Default behavior:: Crash if undefined.
+[source,erlang]
+----
+content_types_accepted(Req, State) -> {Result, Req, State}
 
 
-With types:
+Result     :: [{binary() | ParsedMime, AcceptCallback :: atom()}]
+ParsedMime :: {Type :: binary(), SubType :: binary(), '*' | Params}
+Params     :: [{Key :: binary(), Value :: binary()}]
 
 
-* Type = SubType = binary()
-* Params = '*' | [{binary(), binary()}]
-* AcceptResource = atom()
+Default     - crash
+----
 
 
-Return the list of content-types the resource accepts.
+// @todo Case sensitivity of parsed mime content?
 
 
-The list must be ordered in order of preference.
+Return the list of media types the resource accepts in
+order of preference.
 
 
-Each content-type can be given either as a binary string or as
-a tuple containing the type, subtype and parameters.
+A media type is made of different parts. The media type
+`text/html;charset=utf-8` is of type `text`, subtype `html`
+and has a single parameter `charset` with value `utf-8`.
 
 
-Cowboy will select the most appropriate content-type from the list.
-If any parameter is acceptable, then the tuple form should be used
-with parameters set to `'*'`. If the parameters value is set to `[]`
-only content-type values with no parameters will be accepted. All
-parameter values are treated in a case sensitive manner except the
-`charset` parameter, if present, which is case insensitive.
+// @todo Cowboy needs to ignore the boundary parameter for
+// multipart, as we never want to match against it. Or allow
+// ignoring specific parameters at the very least.
 
 
-This function will be called for POST, PUT and PATCH requests.
-It is entirely possible to define different callbacks for different
-methods if the handling of the request differs. Simply verify
-what the method is with `cowboy_req:method/1` and return a
-different list for each methods.
+Cowboy will match the content-type request header against
+the media types the server accepts and select the appropriate
+callback. When that header is missing, or when the server does not
+accept this media type, the request fails and an error response
+is returned. Cowboy will execute the callback immediately otherwise.
 
 
-The `AcceptResource` value is the name of the callback that will
-be called if the content-type matches. It is defined as follows.
+// @todo We should explain precisely how media types are picked.
 
 
-Value type:: true | {true, URL} | false
-Default behavior:: Crash if undefined.
+An empty parameters list `[]` means that no parameters will be
+accepted. When any parameter is acceptable, the tuple form
+should be used with parameters as the atom `'*'`.
 
 
-Process the request body.
+Cowboy treats all parameters as case sensitive, except for the
+`charset` parameter, which is known to be case insensitive. You
+should therefore always provide the charset as a lowercase
+binary string.
 
 
-This function should create or update the resource with the
-information contained in the request body. This information
-may be full or partial depending on the request method.
+// @todo Maybe this should be in the user guide instead.
+//This function will be called for POST, PUT and PATCH requests.
+//It is entirely possible to define different callbacks for different
+//methods if the handling of the request differs. Simply verify
+//what the method is with `cowboy_req:method/1` and return a
+//different list for each methods.
 
 
-If the request body was processed successfully, `true` must
-be returned. If the request method is POST, `{true, URL}` may
-be returned instead, and Cowboy will redirect the client to
-the location of the newly created resource.
+=== content_types_provided
 
 
-If a response body must be sent, the appropriate media-type, charset
-and language can be retrieved using the `cowboy_req:meta/{2,3}`
-functions. The respective keys are `media_type`, `charset`
-and `language`. The body can be set using `cowboy_req:set_resp_body/2`.
+[source,erlang]
+----
+content_types_provided(Req, State) -> {Result, Req, State}
 
 
-=== content_types_provided
+Result     :: [{binary() | ParsedMime, ProvideCallback :: atom()}]
+ParsedMime :: {Type :: binary(), SubType :: binary(), '*' | Params}
+Params     :: [{Key :: binary(), Value :: binary()}]
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: [{binary() | {Type, SubType, Params}, ProvideResource}]
+Default     - [{{ <<"text">>, <<"html">>, '*'}, to_html}]
+----
+
+// @todo Case sensitivity of parsed mime content?
 // @todo Space required for the time being: https://github.com/spf13/hugo/issues/2398
 // @todo Space required for the time being: https://github.com/spf13/hugo/issues/2398
-Default value:: `[{{ <<"text">>, <<"html">>, '*'}, to_html}]`
 
 
-With types:
+Return the list of media types the resource provides in
+order of preference.
 
 
-* Type = SubType = binary()
-* Params = '*' | [{binary(), binary()}]
-* ProvideResource = atom()
+A media type is made of different parts. The media type
+`text/html;charset=utf-8` is of type `text`, subtype `html`
+and has a single parameter `charset` with value `utf-8`.
 
 
-Return the list of content-types the resource provides.
+// @todo Cowboy needs to ignore the boundary parameter for
+// multipart, as we never want to match against it. Or allow
+// ignoring specific parameters at the very least.
 
 
-The list must be ordered in order of preference.
+During content negotiation Cowboy will pick the most appropriate
+media type for the client. The client advertises media types it
+prefers with the accept header. When that header is missing,
+the content negotiation fails and an error response is returned.
 
 
-Each content-type can be given either as a binary string or as
-a tuple containing the type, subtype and parameters.
+The callback given for the selected media type will be called
+at the end of the execution of GET and HEAD requests when a
+representation must be sent to the client.
 
 
-Cowboy will select the most appropriate content-type from the list.
-If any parameter is acceptable, then the tuple form should be used
-with parameters set to `'*'`. If the parameters value is set to `[]`
-only content-type values with no parameters will be accepted. All
-parameter values are treated in a case sensitive manner except the
-`charset` parameter, if present, which is case insensitive.
+// @todo We should explain precisely how media types are picked.
 
 
-The `ProvideResource` value is the name of the callback that will
-be called if the content-type matches. It will only be called when
-a representation of the resource needs to be returned. It is defined
-as follow.
+An empty parameters list `[]` means that no parameters will be
+accepted. When any parameter is acceptable, the tuple form
+should be used with parameters as the atom `'*'`.
 
 
-Methods:: GET, HEAD
-Value type:: iodata() | {stream, Fun} | {stream, Len, Fun} | {chunked, ChunkedFun}
-Default behavior:: Crash if undefined.
+Cowboy treats all parameters as case sensitive, except for the
+`charset` parameter, which is known to be case insensitive. You
+should therefore always provide the charset as a lowercase
+binary string.
 
 
-Return the response body.
+Cowboy will add the negotiated `media_type` to the Req object
+after this step completes:
 
 
-The response body may be provided directly or through a fun.
-If a fun tuple is returned, the appropriate `set_resp_body_fun`
-function will be called. Please refer to the documentation for
-these functions for more information about the types.
+[source,erlang]
+----
+req() :: #{
+    media_type => ParsedMime
+}
+----
 
 
-The call to this callback happens a good time after the call to
-`content_types_provided/2`, when it is time to start rendering
-the response body.
+// @todo Case sensitivity of parsed mime content?
 
 
 === delete_completed
 === delete_completed
 
 
-Methods:: DELETE
-Value type:: boolean()
-Default value:: true
+[source,erlang]
+----
+delete_completed(Req, State) -> {Result, Req, State}
 
 
-Return whether the delete action has been completed.
+Result  :: boolean()
+Default :: true
+----
 
 
-This function should return `false` if there is no guarantee
-that the resource gets deleted immediately from the system,
-including from any internal cache.
+Return whether the resource has been fully deleted from the
+system, including from any internal cache.
 
 
-When this function returns `false`, a `202 Accepted`
-response will be sent instead of a `200 OK` or `204 No Content`.
+Returning `false` will result in a '202 Accepted' response
+being sent instead of a '200 OK' or '204 No Content'.
 
 
 === delete_resource
 === delete_resource
 
 
-Methods:: DELETE
-Value type:: boolean()
-Default value:: false
+[source,erlang]
+----
+delete_resource(Req, State) -> {Result, Req, State}
+
+Result  :: boolean()
+Default :: false
+----
 
 
 Delete the resource.
 Delete the resource.
 
 
-The value returned indicates if the action was successful,
-regardless of whether the resource is immediately deleted
-from the system.
+Cowboy will send an error response when this function
+returns `false`.
 
 
 === expires
 === expires
 
 
-Methods:: GET, HEAD
-Value type:: calendar:datetime() | binary() | undefined
-Default value:: undefined
+[source,erlang]
+----
+expires(Req, State) -> {Result, Req, State}
 
 
-Return the date of expiration of the resource.
+Result  :: calendar:datetime() | binary() | undefined
+Default :: undefined
+----
 
 
-This date will be sent as the value of the expires header.
+Return the resource's expiration date.
 
 
 === forbidden
 === forbidden
 
 
-Methods:: all
-Value type:: boolean()
-Default value:: false
+[source,erlang]
+----
+forbidden(Req, State) -> {Result, Req, State}
+
+Result  :: boolean()
+Default :: false
+----
 
 
 Return whether access to the resource is forbidden.
 Return whether access to the resource is forbidden.
 
 
-A `403 Forbidden` response will be sent if this
+A '403 Forbidden' response will be sent if this
 function returns `true`. This status code means that
 function returns `true`. This status code means that
 access is forbidden regardless of authentication,
 access is forbidden regardless of authentication,
 and that the request shouldn't be repeated.
 and that the request shouldn't be repeated.
 
 
 === generate_etag
 === generate_etag
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: binary() | {weak | strong, binary()}
-Default value:: undefined
+[source,erlang]
+----
+generate_etag(Req, State) -> {Result, Req, State}
 
 
-Return the entity tag of the resource.
+Result  :: binary() | {weak | strong, binary()}
+Default  - no etag value
+----
 
 
-This value will be sent as the value of the etag header.
+Return the entity tag of the resource.
 
 
-If a binary is returned, then the value will be parsed
-to the tuple form automatically. The value must be in
-the same format as the etag header, including quotes.
+When a binary is returned, the value is automatically
+parsed to a tuple. The binary must be in the same
+format as the etag header, including quotes.
 
 
 === is_authorized
 === is_authorized
 
 
-Methods:: all
-Value type:: true | {false, AuthHeader}
-Default value:: true
+[source,erlang]
+----
+is_authorized(Req, State) -> {Result, Req, State}
 
 
-With types:
-
-* AuthHead = iodata()
+Result  :: true | {false, AuthHeader :: iodata()}
+Default  - true
+----
 
 
 Return whether the user is authorized to perform the action.
 Return whether the user is authorized to perform the action.
 
 
@@ -294,26 +370,34 @@ This function should be used to perform any necessary
 authentication of the user before attempting to perform
 authentication of the user before attempting to perform
 any action on the resource.
 any action on the resource.
 
 
-If the authentication fails, the value returned will be sent
-as the value for the www-authenticate header in the
-`401 Unauthorized` response.
+When authentication fails, the `AuthHeader` value will
+be sent in the www-authenticate header for the
+'401 Unauthorized' response.
 
 
 === is_conflict
 === is_conflict
 
 
-Methods:: PUT
-Value type:: boolean()
-Default value:: false
+[source,erlang]
+----
+is_conflict(Req, State) -> {Result, Req, State}
+
+Result  :: boolean()
+Default :: false
+----
 
 
-Return whether the put action results in a conflict.
+Return whether the PUT request results in a conflict.
 
 
-A `409 Conflict` response will be sent if this function
-returns `true`.
+A '409 Conflict' response is sent when `true`.
 
 
 === known_methods
 === known_methods
 
 
-Methods:: all
-Value type:: [binary()]
-Default value:: `[<<"GET">>, <<"HEAD">>, <<"POST">>, <<"PUT">>, <<"PATCH">>, <<"DELETE">>, <<"OPTIONS">>]`
+[source,erlang]
+----
+known_methods(Req, State) -> {Result, Req, State}
+
+Result  :: [binary()]  %% case sensitive
+Default :: [<<"GET">>, <<"HEAD">>, <<"POST">>, <<"PUT">>,
+            <<"PATCH">>, <<"DELETE">>, <<"OPTIONS">>]
+----
 
 
 Return the list of known methods.
 Return the list of known methods.
 
 
@@ -323,208 +407,263 @@ returned, regardless of their use in the resource.
 The default value lists the methods Cowboy knows and
 The default value lists the methods Cowboy knows and
 implement in `cowboy_rest`.
 implement in `cowboy_rest`.
 
 
-Methods are case sensitive. Standard methods are always uppercase.
-
 === languages_provided
 === languages_provided
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: [binary()]
-Default behavior:: Skip to the next step if undefined.
+[source,erlang]
+----
+languages_provided(Req, State) -> {Result, Req, State}
+
+Result  :: [binary()]  %% lowercase; case insensitive
+Default  - skip this step
+----
 
 
-Return the list of languages the resource provides.
+Return the list of languages the resource provides in order
+of preference.
 
 
-The list must be ordered in order of preference.
+During content negotiation Cowboy will pick the most
+appropriate language for the client. The client advertises
+languages it prefers with the accept-language header. When
+that header is missing, Cowboy picks the first language
+from the resource.
 
 
-If the accept-language header was not sent, the first language
-in the list will be selected. Otherwise Cowboy will select
-the most appropriate language from the list.
+// @todo We should explain precisely how languages are picked.
 
 
-The chosen language will be set in the `Req` object as the meta
-value `language`.
+Cowboy will add the negotiated `language` to the Req object
+after this step completes:
 
 
-While languages are case insensitive, this callback is expected
-to return them as lowercase binary.
+[source,erlang]
+----
+req() :: #{
+    language => binary()  %% lowercase; case insensitive
+}
+----
 
 
 === last_modified
 === last_modified
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: calendar:datetime()
-Default value:: undefined
+[source,erlang]
+----
+last_modified(Req, State) -> {Result, Req, State}
 
 
-Return the date of last modification of the resource.
+Result  :: calendar:datetime()
+Default  - no last modified value
+----
+
+Return the resource's last modification date.
 
 
 This date will be used to test against the if-modified-since
 This date will be used to test against the if-modified-since
 and if-unmodified-since headers, and sent as the last-modified
 and if-unmodified-since headers, and sent as the last-modified
-header in the response of GET and HEAD requests.
+header in the response to GET and HEAD requests.
 
 
 === malformed_request
 === malformed_request
 
 
-Methods:: all
-Value type:: boolean()
-Default value:: false
+[source,erlang]
+----
+malformed_request(Req, State) -> {Result, Req, State}
 
 
-Return whether the request is malformed.
+Result  :: boolean()
+Default :: false
+----
 
 
-Cowboy has already performed all the necessary checks
-by the time this function is called, so few resources
-are expected to implement it.
+Return whether the request is malformed.
 
 
-The check is to be done on the request itself, not on
-the request body, which is processed later.
+A request is malformed when a component required by the
+resource is invalid. This may include the query string
+or individual headers. They should be parsed and validated
+in this function. The body should not be read at this point.
 
 
 === moved_permanently
 === moved_permanently
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: {true, URL} | false
-Default value:: false
-
-With types:
+[source,erlang]
+----
+moved_permanently(Req, State) -> {Result, Req, State}
 
 
-* URL = iodata()
+Result  :: {true, URI :: iodata()} | false
+Default :: false
+----
 
 
-Return whether the resource was permanently moved.
-
-If it was, its new URL is also returned and sent in the
-location header in the response.
+Return whether the resource was permanently moved, and
+what its new location is.
 
 
 === moved_temporarily
 === moved_temporarily
 
 
-Methods:: GET, HEAD, POST, PATCH, DELETE
-Value type:: {true, URL} | false
-Default value:: false
+[source,erlang]
+----
+moved_temporarily(Req, State) -> {Result, Req, State}
 
 
-With types:
+Result  :: {true, URI :: iodata()} | false
+Default :: false
+----
 
 
-* URL = iodata()
+Return whether the resource was temporarily moved, and
+what its new location is.
 
 
-Return whether the resource was temporarily moved.
+=== multiple_choices
 
 
-If it was, its new URL is also returned and sent in the
-location header in the response.
+[source,erlang]
+----
+multiple_choices(Req, State) -> {Result, Req, State}
 
 
-=== multiple_choices
+Result  :: boolean()
+Default :: false
+----
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: boolean()
-Default value:: false
+Return whether the client should engage in reactive
+negotiation.
 
 
-Return whether there are multiple representations of the resource.
+Return `true` when the server has multiple representations
+of a resource, each with their specific identifier, but is
+unable to determine which is best for the client. For
+example an image might have different sizes and the server
+is unable to determine the capabilities of the client.
 
 
-This function should be used to inform the client if there
-are different representations of the resource, for example
-different content-type. If this function returns `true`,
-the response body should include information about these
-different representations using `cowboy_req:set_resp_body/2`.
-The content-type of the response should be the one previously
-negociated and that can be obtained by calling
-`cowboy_req:meta(media_type, Req)`.
+When returning `true` the server should send a body with
+links to the different representations. If the server has
+a preferred representation it can send its link inside a
+location header.
 
 
 === options
 === options
 
 
-Methods:: OPTIONS
-Value type:: ok
-Default value:: ok
+[source,erlang]
+----
+options(Req, State) -> {ok, Req, State}
+----
 
 
-Handle a request for information.
+Respond to an OPTIONS request.
 
 
 The response should inform the client the communication
 The response should inform the client the communication
-options available for this resource.
-
-By default, Cowboy will send a `200 OK` response with the
-allow header set.
+options available for this resource. By default Cowboy
+will send a '200 OK' response with the allow header set.
 
 
 === previously_existed
 === previously_existed
 
 
-Methods:: GET, HEAD, POST, PATCH, DELETE
-Value type:: boolean()
-Default value:: false
+[source,erlang]
+----
+previously_existed(Req, State) -> {Result, Req, State}
+
+Result  :: boolean()
+Default :: false
+----
 
 
 Return whether the resource existed previously.
 Return whether the resource existed previously.
 
 
+=== ProvideCallback
+
+[source,erlang]
+----
+ProvideCallback(Req, State) -> {Result, Req, State}
+
+Result  :: cowboy_req:resp_body()
+Default  - crash
+----
+
+Return the response body.
+
+The response body can be provided either as the actual data
+to be sent or a tuple indicating which file to send.
+
+This function is called for both GET and HEAD requests. For
+the latter the body is not sent, however.
+
+// @todo Perhaps we can optimize HEAD requests and just
+// allow calculating the length instead of returning the
+// whole thing.
+
+Note that there used to be a way to stream the response body.
+It was temporarily removed and will be added back in a later
+release.
+
+// @todo Add a way to switch to loop handler for streaming the body.
+
 === resource_exists
 === resource_exists
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: boolean()
-Default value:: true
+[source,erlang]
+----
+resource_exists(Req, State) -> {Result, Req, State}
 
 
-Return whether the resource exists.
+Result  :: boolean()
+Default :: true
+----
 
 
-If it exists, conditional headers will be tested before
-attempting to perform the action. Otherwise, Cowboy will
-check if the resource previously existed first.
+Return whether the resource exists.
 
 
 === service_available
 === service_available
 
 
-Methods:: all
-Value type:: boolean()
-Default value:: true
+[source,erlang]
+----
+service_available(Req, State) -> {Result, Req, State}
 
 
-Return whether the service is available.
+Result  :: boolean()
+Default :: true
+----
 
 
-This function can be used to test that all relevant backend
-systems are up and able to handle requests.
+Return whether the service is available.
 
 
-A `503 Service Unavailable` response will be sent if this
+A '503 Service Unavailable' response will be sent when this
 function returns `false`.
 function returns `false`.
 
 
 === uri_too_long
 === uri_too_long
 
 
-Methods:: all
-Value type:: boolean()
-Default value:: false
+[source,erlang]
+----
+uri_too_long(Req, State) -> {Result, Req, State}
 
 
-Return whether the requested URI is too long.
+Result  :: boolean()
+Default :: false
+----
 
 
-Cowboy has already performed all the necessary checks
-by the time this function is called, so few resources
-are expected to implement it.
+Return whether the requested URI is too long.
 
 
-A `414 Request-URI Too Long` response will be sent if this
-function returns `true`.
+This function can be used to further restrict the length
+of the URI for this specific resource.
 
 
 === valid_content_headers
 === valid_content_headers
 
 
-Methods:: all
-Value type:: boolean()
-Default value:: true
+[source,erlang]
+----
+valid_content_headers(Req, State) -> {Result, Req, State}
 
 
-Return whether the content-* headers are valid.
+Result  :: boolean()
+Default :: true
+----
 
 
-This also applies to the transfer-encoding header. This
-function must return `false` for any unknown content-*
-headers, or if the headers can't be understood. The
-function `cowboy_req:parse_header/2` can be used to
-quickly check the headers can be parsed.
+Return whether the content headers are valid.
 
 
-A `501 Not Implemented` response will be sent if this
-function returns `false`.
+This callback can be used to reject requests that have
+invalid content header values, for example an unsupported
+content-encoding.
 
 
 === valid_entity_length
 === valid_entity_length
 
 
-Methods:: all
-Value type:: boolean()
-Default value:: true
+[source,erlang]
+----
+valid_entity_length(Req, State) -> {Result, Req, State}
+
+Result  :: boolean()
+Default :: true
+----
 
 
 Return whether the request body length is within acceptable boundaries.
 Return whether the request body length is within acceptable boundaries.
 
 
-A `413 Request Entity Too Large` response will be sent if this
+A '413 Request Entity Too Large' response will be sent if this
 function returns `false`.
 function returns `false`.
 
 
 === variances
 === variances
 
 
-Methods:: GET, HEAD, POST, PUT, PATCH, DELETE
-Value type:: [binary()]
-Default value:: []
+[source,erlang]
+----
+variances(Req, State) -> {Result, Req, State}
+
+Result  :: [binary()]  %% case insensitive
+Default :: []
+----
 
 
-Return the list of headers that affect the representation of the resource.
+Return the list of request headers that affect the
+representation of the resource.
 
 
-These request headers return the same resource but with different
-parameters, like another language or a different content-type.
+Cowboy automatically adds the accept, accept-charset and
+accept-language headers when necessary.
 
 
-Cowboy will automatically add the accept, accept-language and
-accept-charset headers to the list if the respective functions
-were defined in the resource.
+== See also
 
 
-This operation is performed right before the `resource_exists/2`
-callback. All responses past that point will contain the vary
-header which holds this list.
+link:man:cowboy(7)[cowboy(7)],
+link:man:cowboy_handler(3)[cowboy_handler(3)]

+ 2 - 0
doc/src/manual/cowboy_static.asciidoc

@@ -100,6 +100,8 @@ ParsedMime :: {Type :: binary(), SubType :: binary(), Params}
 Params     :: [{Key :: binary(), Value :: binary()}]
 Params     :: [{Key :: binary(), Value :: binary()}]
 ----
 ----
 
 
+// @todo Case sensitivity of parsed mime content?
+
 Cowboy comes with two such functions; the default function
 Cowboy comes with two such functions; the default function
 `cow_mimetypes:web/1`, and a second function generated from
 `cow_mimetypes:web/1`, and a second function generated from
 the Apache 'mime.types' file, `cow_mimetypes:all/1`.
 the Apache 'mime.types' file, `cow_mimetypes:all/1`.