diff --git a/README.md b/README.md index 2452c83..8c01d02 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,21 @@ of an `If-Match` or `If-None-Match` header. (Result.Error e) (IO.errorln &e)) ``` -`If-Range` is not evaluated yet. +`If-Range` gates a `Range` header on the client still holding the version it is +asking to continue (§13.1.5). A non-match means ignoring the `Range` and sending +the whole representation with a `200`, rather than splicing bytes of a changed +representation into the client's copy. + +```clojure +(if (Request.if-range-matches? &req &etag &modified) + (serve-range &req) ; no If-Range, or its validator still matches + (whole-representation)) +``` + +The validator is either an entity-tag, compared strongly — so a weak one never +matches — or an HTTP-date, which must name the very instant the representation +was last modified. §13.2.1 has the §13.2.2 preconditions evaluated first, then +`If-Range`, then the `Range` itself. ### Status codes diff --git a/docs/Precondition.html b/docs/Precondition.html index 32ab22c..ccfe454 100644 --- a/docs/Precondition.html +++ b/docs/Precondition.html @@ -158,9 +158,9 @@
If-Range is not evaluated: a range request whose condition fails is answered
-with the whole representation, which is
-ByteRange's business rather than a status.
If-Range demands no status of its own, so it is evaluated apart from the four,
+by if-range-matches?: a range request whose condition fails
+is answered with the whole representation rather than an error.
ETagList.strong-match? and
ETagList.weak-match? are public for it.
+
+ + (Fn [(Ref (Map String (Array String)) a), (Ref (Maybe ETag) b), (Ref (Maybe Datetime) c)] Bool) +
++ (if-range-matches? hdrs etag modified) ++
+
whether the Range header in hdrs is to be honored,
+given etag and modified, the entity-tag and last modification date of the
+representation the server selected — either may be Nothing.
true when the request carries no If-Range, when it carries no Range for one
+to gate, or when the If-Range validator matches (RFC 9110 §13.1.5). false
+means the Range must be ignored and the whole representation sent with a 200,
+the client holding a version other than the one it asks to continue.
The two validator forms are told apart by the first characters of the field
+value: a quote or a W/ names an entity-tag, anything else an HTTP-date. An
+entity-tag is compared strongly (§8.8.3.2), so a weak one — which §13.1.5 forbids
+a client to send and obliges a recipient to ignore — never matches. A date
+matches the modification date only when it names the very same instant, as
+§8.8.2.2's strong-validator rule demands. A field value that reads as neither
+form, and a validator the selected representation has no counterpart to, are
+non-matches.
§13.2.1 orders the three steps of a conditional range request:
+evaluate first, then this, then the Range itself.
+ (Fn [(Ref Request a), (Ref (Maybe ETag) b), (Ref (Maybe Datetime) c)] Bool) +
++ (if-range-matches? r etag modified) ++
+
whether this request's Range header is to be honored
+for a representation whose entity-tag is etag and whose last modification date
+is modified. false means the Range is to be ignored and the whole
+representation sent. See
+Precondition.if-range-matches?.
(Maybe (Result (Array ByteRangeSpec) String)). Nothing when it carries no
Range header. See ByteRange.parse, whose Error
means the header is one RFC 9110 §14.2 has the server ignore — serving the whole
-representation rather than a 416.
+representation rather than a 416. A request that also carries an If-Range
+wants if-range-matches? consulted first.