From 427a276ef2f2042ad312e0260535cbb4696f9072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Tue, 23 Jan 2024 13:15:55 +0100 Subject: Update the guide with range requests support Also update the list of headers cowboy_rest might set and tweak a small number of other items. --- doc/src/guide/resource_design.asciidoc | 17 +- doc/src/guide/rest_conneg.png | Bin 78133 -> 75587 bytes doc/src/guide/rest_conneg.svg | 277 +++--- doc/src/guide/rest_flowcharts.asciidoc | 18 +- doc/src/guide/rest_get_head.png | Bin 94321 -> 171818 bytes doc/src/guide/rest_get_head.svg | 1455 ++++++++++++++++++++++++++------ doc/src/guide/rest_handlers.asciidoc | 19 +- 7 files changed, 1405 insertions(+), 381 deletions(-) (limited to 'doc') diff --git a/doc/src/guide/resource_design.asciidoc b/doc/src/guide/resource_design.asciidoc index 954d87d..125b437 100644 --- a/doc/src/guide/resource_design.asciidoc +++ b/doc/src/guide/resource_design.asciidoc @@ -144,6 +144,16 @@ never be called. Implement the `languages_provided` or `charsets_provided` callbacks if applicable. +Does the resource accept ranged requests? If it does, +implement the `ranges_provided` callback. Resources that +only accept `bytes` units can use the callback name +`auto` and let Cowboy automatically do ranged responses. +Other callbacks should have a name prefix of `ranged_` +for clarity. For example, `ranged_bytes` or `ranged_pages`. +If the resource needs to perform additional checks before +accepting to do a ranged responses, implement the +`range_satisfiable` callback. + Is there any other header that may make the representation of the resource vary? Implement the `variances` callback. @@ -191,10 +201,15 @@ the `options` method. === GET and HEAD methods If you implement the methods GET and/or HEAD, you must -implement one `ProvideResource` callback for each +implement one `ProvideCallback` callback for each content-type returned by the `content_types_provided` callback. +When range requests are accepted, you must implement one +`RangeCallback` for each range unit returned by +`ranges_provided` (unless `auto` was used). This is +in addition to the `ProvideCallback` callback. + === PUT, POST and PATCH methods If you implement the methods PUT, POST and/or PATCH, diff --git a/doc/src/guide/rest_conneg.png b/doc/src/guide/rest_conneg.png index 65ecdcf..79aa69b 100644 Binary files a/doc/src/guide/rest_conneg.png and b/doc/src/guide/rest_conneg.png differ diff --git a/doc/src/guide/rest_conneg.svg b/doc/src/guide/rest_conneg.svg index 247567a..97bba6a 100644 --- a/doc/src/guide/rest_conneg.svg +++ b/doc/src/guide/rest_conneg.svg @@ -2,24 +2,23 @@ + inkscape:export-ydpi="90" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + inkscape:swatch="solid"> + showguides="true" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1"> + snapvisiblegridlinesonly="true" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" /> @@ -93,7 +100,7 @@ image/svg+xml - + @@ -112,7 +119,7 @@ some text + y="114.39204" + style="font-size:16px;line-height:1.25;font-family:sans-serif">some text some text + y="53.112247" + style="font-size:16px;line-height:1.25;font-family:sans-serif">some text has accept-language? + y="310.19913" + style="font-size:16px;line-height:1.25;font-family:sans-serif">has accept-language? has accept-charset? + y="477.47531" + style="font-size:16px;line-height:1.25;font-family:sans-serif">has accept-charset? some text + y="236.95154" + style="font-size:16px;line-height:1.25;font-family:sans-serif">some text start + id="tspan17171" + style="font-size:16px;line-height:1.25;font-family:sans-serif">start charsets_provided + y="561.14258" + style="font-size:16px;line-height:1.25;font-family:sans-serif">charsets_provided variances + y="646.58331" + style="font-size:16px;line-height:1.25;font-family:sans-serif">ranges_provided has accept? + y="142.80627" + style="font-size:16px;line-height:1.25;font-family:sans-serif">has accept? content_types_provided + y="226.4736" + style="font-size:16px;line-height:1.25;font-family:sans-serif">content_types_provided languages_provided + y="393.80801" + style="font-size:16px;line-height:1.25;font-family:sans-serif">languages_provided true + y="185.95248" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true provided* + y="269.61978" + style="font-size:16px;line-height:1.25;font-family:sans-serif">provided* true + y="353.28702" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true provided* + y="436.95425" + style="font-size:16px;line-height:1.25;font-family:sans-serif">provided* true + y="520.62152" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true provided* + y="604.28876" + style="font-size:16px;line-height:1.25;font-family:sans-serif">provided* @@ -820,75 +827,75 @@ false + y="227.88033" + style="font-size:16px;line-height:1.25;font-family:sans-serif">false false + y="395.20209" + style="font-size:16px;line-height:1.25;font-family:sans-serif">false not provided* + y="374.19577" + style="font-size:16px;line-height:1.25;font-family:sans-serif">not provided* false + y="562.52386" + style="font-size:16px;line-height:1.25;font-family:sans-serif">false not provided* + y="663.24762" + style="font-size:16px;line-height:1.25;font-family:sans-serif">not provided* 406 not acceptable + y="394.09869" + style="font-size:16px;line-height:1.25;font-family:sans-serif">406 not acceptable middlewares + y="-354.17184" + style="font-size:16px;line-height:1.25;font-family:sans-serif">middlewares not provided* + y="-106.16136" + style="font-size:16px;line-height:1.25;font-family:sans-serif">not provided* + + + + ... + y="730.10156" + style="font-size:16px;line-height:1.25;font-family:sans-serif">variances + + ... diff --git a/doc/src/guide/rest_flowcharts.asciidoc b/doc/src/guide/rest_flowcharts.asciidoc index 308a919..b8d0e0d 100644 --- a/doc/src/guide/rest_flowcharts.asciidoc +++ b/doc/src/guide/rest_flowcharts.asciidoc @@ -95,6 +95,11 @@ callback will only be called at the end of the "GET and HEAD methods" diagram, when all conditions have been met. +Optionally, the `ranges_provided` also returns the +name of a callback for every range unit it accepts. This +will be called at the end of the "GET and HEAD methods" +diagram in the case of ranged requests. + The selected content-type, language and charset are saved as meta values in the Req object. You *should* use the appropriate representation if you set a @@ -121,11 +126,18 @@ succeed, the resource can be retrieved. Cowboy prepares the response by first retrieving metadata about the representation, then by calling -the `ProvideResource` callback. This is the callback +the `ProvideCallback` callback. This is the callback you defined for each content-types you returned from `content_types_provided`. This callback returns the body -that will be sent back to the client, or a fun if the -body must be streamed. +that will be sent back to the client. + +For ranged requests, but only when the `ranges_provided` +callback was defined earlier, Cowboy will add the selected +`range` information to the Req object and call the +`range_satisfiable` callback. After confirming that the +range can be provided, Cowboy calls the `RangeResource` +callback and produces a ranged response using the +ranged data from the callback. When the resource does not exist, Cowboy will figure out whether the resource existed previously, and if so whether diff --git a/doc/src/guide/rest_get_head.png b/doc/src/guide/rest_get_head.png index 211ab60..24f8de4 100644 Binary files a/doc/src/guide/rest_get_head.png and b/doc/src/guide/rest_get_head.png differ diff --git a/doc/src/guide/rest_get_head.svg b/doc/src/guide/rest_get_head.svg index 92030cf..cf66089 100644 --- a/doc/src/guide/rest_get_head.svg +++ b/doc/src/guide/rest_get_head.svg @@ -2,24 +2,23 @@ + inkscape:export-ydpi="90" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + inkscape:swatch="solid"> + showguides="true" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1"> + snapvisiblegridlinesonly="true" + originx="0" + originy="0" + spacingy="1" + spacingx="1" + units="px" /> @@ -101,6 +108,223 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + transform="rotate(90,-13.918835,262.77429)" /> + d="m -57.78256,343.20394 v 61.59661" + style="opacity:0.8;fill:none;stroke:#9b3b1c;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> last_modified + ProvideCallback + + ProvideCallback + some text + conneg + multiple_choices + resource_exists + generate_etag + expires + + + + + + has range? + + + + + + resource provides ranges? + + + + + + has if-range? + + + + + + requested range provided? + + + + + + range_satisfiable + + + + + + + + + + last_modified + id="tspan5373-6-18-0-7-7-9-9-8" + x="470.94278" + y="957.45563" + style="font-size:16px;line-height:1.25;font-family:sans-serif">automatic range? + ProvideCallback + id="tspan5373-6-63" + x="509.83722" + y="175.92931" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true some text + id="tspan5373-6-63-9" + x="336.74399" + y="1000.7801" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true conneg + id="tspan5373-6-63-9-8" + x="484.61441" + y="669.48737" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true multiple_choices + id="tspan5373-6-63-9-2" + x="484.61441" + y="587.08673" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true resource_exists + id="tspan5373-6-63-9-4" + x="397.49249" + y="751.30035" + style="font-size:16px;line-height:1.25;font-family:sans-serif">false, or generate_etag + id="tspan5373-6-63-9-0" + x="484.61441" + y="834.89026" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true expires - + id="tspan5373-6-63-9-87" + x="484.61441" + y="917.41119" + style="font-size:16px;line-height:1.25;font-family:sans-serif">true true + id="tspan5373-6-63-0" + x="570.74402" + y="1000.7801" + style="font-size:16px;line-height:1.25;font-family:sans-serif">false false false + false + false + false + false + no match + error producingautomaticranged response + d="m -57.78256,343.20394 v 61.59661" + style="opacity:0.8;fill:none;stroke:#9b3b1c;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> true true + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> cond 300 multiple choices 200 OK + automaticranged response + strong etag match + + 206 partial content + + RangeCallback + + 206 partial content + transform="rotate(90,-13.918835,262.77429)" /> has if-match? false + d="m -57.78256,351.41962 v 52.3259" + style="opacity:0.8;fill:none;stroke:#6d8e41;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + transform="rotate(90,-13.918835,262.77429)" /> previously_existed 404 not found false + d="m -57.78256,343.20394 v 61.59661" + style="opacity:0.8;fill:none;stroke:#9b3b1c;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + transform="rotate(90,-13.918835,262.77429)" /> moved_permanently 412 precondition failed true true* false 301 moved permanently + d="m -57.78256,343.20394 v 61.59661" + style="opacity:0.8;fill:none;stroke:#9b3b1c;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + transform="rotate(90,-13.918835,262.77429)" /> moved_temporarily true* false 307 moved temporarily 410 gone + + 416 not satisfiable diff --git a/doc/src/guide/rest_handlers.asciidoc b/doc/src/guide/rest_handlers.asciidoc index baf8e6a..19a9859 100644 --- a/doc/src/guide/rest_handlers.asciidoc +++ b/doc/src/guide/rest_handlers.asciidoc @@ -84,6 +84,8 @@ if it is undefined, moving directly to the next step. Similarly, | multiple_choices | `false` | options | `ok` | previously_existed | `false` +| ranges_provided | skip +| range_satisfiable | `true` | rate_limited | `false` | resource_exists | `true` | service_available | `true` @@ -97,8 +99,9 @@ As you can see, Cowboy tries to move on with the request whenever possible by using well thought out default values. In addition to these, there can be any number of user-defined -callbacks that are specified through `content_types_accepted/2` -and `content_types_provided/2`. They can take any name, however +callbacks that are specified through `content_types_accepted/2`, +`content_types_provided/2` or `ranges_provided/2`. They can take +any name (except `auto` for range callbacks), however it is recommended to use a separate prefix for the callbacks of each function. For example, `from_html` and `to_html` indicate in the first case that we're accepting a resource given as HTML, @@ -113,9 +116,10 @@ Req object directly. The values are defined in the following table: [cols="<,<",options="header"] |=== | Key | Details -| media_type | The content-type negotiated for the response entity. -| language | The language negotiated for the response entity. -| charset | The charset negotiated for the response entity. +| media_type | The content-type negotiated for the response entity +| language | The language negotiated for the response entity +| charset | The charset negotiated for the response entity +| range | The range selected for the ranged response |=== They can be used to send a proper body with the response to a @@ -129,11 +133,16 @@ of the REST code. They are listed in the following table. [cols="<,<",options="header"] |=== | Header name | Details +| accept-ranges | Range units accepted by the resource +| allow | HTTP methods allowed by the resource | content-language | Language used in the response body +| content-range | Range of the content found in the response | content-type | Media type and charset of the response body | etag | Etag of the resource | expires | Expiration date of the resource | last-modified | Last modification date for the resource | location | Relative or absolute URI to the requested resource +| retry-after | Delay or time the client should wait before accessing the resource | vary | List of headers that may change the representation of the resource +| www-authenticate | Authentication information to access the resource |=== -- cgit v1.2.3