@@ -22,69 +22,267 @@ For a definition of Universal HTTP middleware, see the
2222## Usage
2323
2424To evaluate precondition, you need to provide a function to retrieve the
25- selected representation.
25+ [ selected representation] ( https://www.rfc-editor.org/rfc/rfc9110#selected.representation ) .
2626
27- The following example evaluates the ` If-None-Match ` precondition and controls
28- the handler .
27+ The following example evaluates the ` If-None-Match ` precondition and handle
28+ response .
2929
3030``` ts
31- import { conditionalRequest } from " https://deno.land/x/conditional_request_middleware@$VERSION/mod.ts" ;
32- import { assertEquals } from " https://deno.land/std/testing/asserts.ts" ;
31+ import {
32+ conditionalRequest ,
33+ type Handler ,
34+ } from " https://deno.land/x/conditional_request_middleware@$VERSION/mod.ts" ;
35+ import {
36+ assertEquals ,
37+ assertFalse ,
38+ } from " https://deno.land/std/testing/asserts.ts" ;
3339import { assertSpyCalls , spy } from " https://deno.land/std/testing/mock.ts" ;
3440
35- const selectedRepresentation = new Response ( " <body> " , {
36- headers: { etag: " <etag>" },
41+ const selectRepresentation = spy (( request : Request ) => {
42+ return new Response ( " <body> " , { headers: { etag: " <etag>" } });
3743});
38- const selectRepresentation = spy (() => selectedRepresentation );
3944const middleware = conditionalRequest (selectRepresentation );
4045const request = new Request (" <uri>" , {
4146 headers: { " if-none-match" : " <etag>" },
4247});
43- const handler = spy (() => selectedRepresentation );
48+ declare const _handler: Handler ;
49+ const handler = spy (_handler );
4450
4551const response = await middleware (request , handler );
4652
4753assertSpyCalls (handler , 0 );
4854assertSpyCalls (selectRepresentation , 1 );
4955assertEquals (response .status , 304 );
56+ assertFalse (response .body );
5057```
5158
52- ## Preconditions
59+ ## Precondition
5360
5461[ RFC 9110, 13.1. Preconditions] ( https://www.rfc-editor.org/rfc/rfc9110#section-13.1 )
5562compliant and supports the following precondition:
5663
57- - If-Match
58- - If-None-Match
59- - If-Modified-Since
60- - If-Unmodified-Since
61- - If-Range
64+ - [ If-Match] ( #ifmatch )
65+ - [ If-None-Match] ( #ifnonematch )
66+ - [ If-Modified-Since] ( #ifmodifiedsince )
67+ - [ If-Unmodified-Since] ( #ifunmodifiedsince )
68+ - [ If-Range] ( #ifrange )
6269
6370If multiple precondition headers are present, precondition is processed
6471according to
6572[ precedence] ( https://www.rfc-editor.org/rfc/rfc9110.html#section-13.2.2 ) .
6673
67- ## Effects
74+ ### IfMatch
75+
76+ ` If-Match ` header field precondition.
77+
78+ ``` ts
79+ import { IfMatch } from " https://deno.land/x/conditional_request_middleware@$VERSION/mod.ts" ;
80+ import { assertEquals } from " https://deno.land/std/testing/asserts.ts" ;
81+
82+ const precondition = new IfMatch ();
83+ const request = new Request (" <uri>" , {
84+ headers: { " if-match" : " <strong:etag>" },
85+ });
86+ const selectedRepresentation = new Response (" <content>" , {
87+ headers: { etag: " <weak:etag>" },
88+ });
89+ declare const evalResult: false ;
90+
91+ assertEquals (precondition .field , " if-match" );
92+ assertEquals (
93+ precondition .evaluate (request , selectedRepresentation ),
94+ evalResult ,
95+ );
96+ assertEquals (
97+ precondition .respond (request , selectedRepresentation , evalResult )?.status ,
98+ 412 ,
99+ );
100+ ```
101+
102+ #### Effects
103+
104+ Precondition will effect following:
105+
106+ If evaluation is ` false ` :
107+
108+ - HTTP content
109+ - HTTP response status
110+ - [ 412 (Precondition Failed)] ( https://www.rfc-editor.org/rfc/rfc9110#section-15.5.13 )
111+ - HTTP headers
112+ - [ Representation headers] ( https://www.rfc-editor.org/rfc/rfc9110.html#section-8 )
113+
114+ ### IfNoneMatch
115+
116+ ` If-None-Match ` header field precondition.
117+
118+ ``` ts
119+ import { IfNoneMatch } from " https://deno.land/x/conditional_request_middleware@$VERSION/mod.ts" ;
120+ import { assertEquals } from " https://deno.land/std/testing/asserts.ts" ;
121+
122+ const precondition = new IfNoneMatch ();
123+ const request = new Request (" <uri>" , {
124+ headers: { " if-none-match" : " <weak:etag>" },
125+ });
126+ const selectedRepresentation = new Response (" <content>" , {
127+ headers: { etag: " <weak:etag>" },
128+ });
129+ declare const evalResult: false ;
130+
131+ assertEquals (precondition .field , " if-none-match" );
132+ assertEquals (
133+ precondition .evaluate (request , selectedRepresentation ),
134+ evalResult ,
135+ );
136+ assertEquals (
137+ precondition .respond (request , selectedRepresentation , evalResult )?.status ,
138+ 304 ,
139+ );
140+ ```
141+
142+ #### Effects
143+
144+ Precondition will effect following:
145+
146+ If evaluation is ` false ` :
147+
148+ - HTTP content
149+ - HTTP response status
150+ - [ 304 (Not Modified)] ( https://www.rfc-editor.org/rfc/rfc9110#section-15.4.5 )
151+ - [ 412 (Precondition Failed)] ( https://www.rfc-editor.org/rfc/rfc9110#section-15.5.13 )
152+ - HTTP headers
153+ - [ Representation headers] ( https://www.rfc-editor.org/rfc/rfc9110.html#section-8 )
154+
155+ ### IfModifiedSince
156+
157+ ` If-Modified-Since ` header field precondition.
158+
159+ ``` ts
160+ import { IfModifiedSince } from " https://deno.land/x/conditional_request_middleware@$VERSION/mod.ts" ;
161+ import { assertEquals } from " https://deno.land/std/testing/asserts.ts" ;
162+
163+ const precondition = new IfModifiedSince ();
164+ const request = new Request (" <uri>" , {
165+ headers: { " if-modified-since" : " <after:HTTP-date>" },
166+ });
167+ const selectedRepresentation = new Response (" <content>" , {
168+ headers: { " last-modified" : " <before:HTTP-date>" },
169+ });
170+ declare const evalResult: false ;
171+
172+ assertEquals (precondition .field , " if-modified-since" );
173+ assertEquals (
174+ precondition .evaluate (request , selectedRepresentation ),
175+ evalResult ,
176+ );
177+ assertEquals (
178+ precondition .respond (request , selectedRepresentation , evalResult )?.status ,
179+ 304 ,
180+ );
181+ ```
182+
183+ #### Effects
184+
185+ Precondition will effect following:
68186
69- Middleware will effect following :
187+ If evaluation is ` false ` :
70188
189+ - HTTP content
71190- HTTP response status
72191 - [ 304 (Not Modified)] ( https://www.rfc-editor.org/rfc/rfc9110#section-15.4.5 )
192+ - HTTP headers
193+ - Content-Type
194+ - Content-Encoding
195+ - Content-Length
196+ - Content-Language
197+
198+ ### IfUnmodifiedSince
199+
200+ ` If-Unmodified-Since ` header field precondition.
201+
202+ ``` ts
203+ import { IfUnmodifiedSince } from " https://deno.land/x/conditional_request_middleware@$VERSION/mod.ts" ;
204+ import { assertEquals } from " https://deno.land/std/testing/asserts.ts" ;
205+
206+ const precondition = new IfUnmodifiedSince ();
207+ const request = new Request (" <uri>" , {
208+ headers: { " if-unmodified-since" : " <before:HTTP-date>" },
209+ });
210+ const selectedRepresentation = new Response (" <content>" , {
211+ headers: { " last-modified" : " <after:HTTP-date>" },
212+ });
213+ declare const evalResult: false ;
214+
215+ assertEquals (precondition .field , " if-unmodified-since" );
216+ assertEquals (
217+ precondition .evaluate (request , selectedRepresentation ),
218+ evalResult ,
219+ );
220+ assertEquals (
221+ precondition .respond (request , selectedRepresentation , evalResult )?.status ,
222+ 412 ,
223+ );
224+ ```
225+
226+ #### Effects
227+
228+ Precondition will effect following:
229+
230+ If evaluation is ` false ` :
231+
232+ - HTTP content
233+ - HTTP response status
73234 - [ 412 (Precondition Failed)] ( https://www.rfc-editor.org/rfc/rfc9110#section-15.5.13 )
235+ - HTTP headers
236+ - [ Representation headers] ( https://www.rfc-editor.org/rfc/rfc9110.html#section-8 )
237+
238+ ### IfRange
239+
240+ ` If-Range ` header field precondition.
241+
242+ ``` ts
243+ import { IfRange } from " https://deno.land/x/conditional_request_middleware@$VERSION/mod.ts" ;
244+ import { assertEquals } from " https://deno.land/std/testing/asserts.ts" ;
245+
246+ const precondition = new IfRange ();
247+ const request = new Request (" <uri>" , {
248+ headers: { " if-range" : " <strong:etag>" , range: " <range-unit>=<range-set>" },
249+ });
250+ const selectedRepresentation = new Response (" <content>" , {
251+ headers: { etag: " <strong:etag>" },
252+ });
253+ declare const evalResult: false ;
254+
255+ assertEquals (precondition .field , " if-range" );
256+ assertEquals (
257+ precondition .evaluate (request , selectedRepresentation ),
258+ evalResult ,
259+ );
260+ assertEquals (
261+ (await precondition .respond (request , selectedRepresentation , evalResult ))
262+ ?.status ,
263+ 206 ,
264+ );
265+ ```
266+
267+ #### Effects
268+
269+ Precondition will effect following:
270+
271+ If evaluation is ` true ` :
272+
273+ - HTTP content
274+ - HTTP response status
275+ - [ 206 (Precondition Failed)] ( https://www.rfc-editor.org/rfc/rfc9110#section-15.3.7 )
276+ - HTTP headers
277+ - Content-Range
74278
75279## Conditions
76280
77281Middleware will execute only if the following conditions are met:
78282
79- - The precondition header exists
80- - ` If-Match `
81- - The ` ETag ` header exist
82- - ` If-None-Match `
83- - The ` ETag ` header exist
84- - ` If-Modified-Since `
85- - The ` Last-Modified ` header exist
86- - ` If-Unmodified-Since `
87- - The ` Last-Modified ` header exist
283+ - Request is conditional request
284+ - Request method is not ` CONNECT ` , ` OPTIONS ` or ` TRACE `
285+ - Select representation status is ` 2xx ` or ` 412 `
88286
89287## License
90288
0 commit comments