1
+ <?php
2
+
3
+ namespace Kevinrob \GuzzleCache \Tests ;
4
+
5
+ use GuzzleHttp \Psr7 \Request ;
6
+ use GuzzleHttp \Psr7 \Response ;
7
+ use Kevinrob \GuzzleCache \Storage \VolatileRuntimeStorage ;
8
+ use Kevinrob \GuzzleCache \Strategy \PrivateCacheStrategy ;
9
+ use Kevinrob \GuzzleCache \Strategy \PublicCacheStrategy ;
10
+ use PHPUnit \Framework \TestCase ;
11
+
12
+ class AuthorizationCacheTest extends TestCase
13
+ {
14
+ /**
15
+ * Test that requests with Authorization header are NOT cached when response only has max-age
16
+ */
17
+ public function testAuthorizationHeaderNotCachedWithMaxAge ()
18
+ {
19
+ $ storage = new VolatileRuntimeStorage ();
20
+ $ strategy = new PublicCacheStrategy ($ storage );
21
+
22
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
23
+ 'Authorization ' => 'Bearer secret-token '
24
+ ]);
25
+
26
+ $ response = new Response (200 , [
27
+ 'Cache-Control ' => 'max-age=3600 '
28
+ ], 'Private data ' );
29
+
30
+ $ result = $ strategy ->cache ($ request , $ response );
31
+ $ this ->assertFalse ($ result , 'Request with Authorization header should not be cached with only max-age ' );
32
+
33
+ $ cached = $ strategy ->fetch ($ request );
34
+ $ this ->assertNull ($ cached , 'No cache entry should exist for authorized request with only max-age ' );
35
+ }
36
+
37
+ /**
38
+ * Test that requests with Authorization header ARE cached when response has Cache-Control: public
39
+ */
40
+ public function testAuthorizationHeaderCachedWithPublic ()
41
+ {
42
+ $ storage = new VolatileRuntimeStorage ();
43
+ $ strategy = new PublicCacheStrategy ($ storage );
44
+
45
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
46
+ 'Authorization ' => 'Bearer secret-token '
47
+ ]);
48
+
49
+ $ response = new Response (200 , [
50
+ 'Cache-Control ' => 'public, max-age=3600 '
51
+ ], 'Public data ' );
52
+
53
+ $ result = $ strategy ->cache ($ request , $ response );
54
+ $ this ->assertTrue ($ result , 'Request with Authorization header should be cached with public directive ' );
55
+
56
+ $ cached = $ strategy ->fetch ($ request );
57
+ $ this ->assertNotNull ($ cached , 'Cache entry should exist for authorized request with public directive ' );
58
+ $ this ->assertEquals ('Public data ' , (string ) $ cached ->getResponse ()->getBody ());
59
+ }
60
+
61
+ /**
62
+ * Test that requests with Authorization header ARE cached when response has Cache-Control: must-revalidate
63
+ */
64
+ public function testAuthorizationHeaderCachedWithMustRevalidate ()
65
+ {
66
+ $ storage = new VolatileRuntimeStorage ();
67
+ $ strategy = new PublicCacheStrategy ($ storage );
68
+
69
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
70
+ 'Authorization ' => 'Bearer secret-token '
71
+ ]);
72
+
73
+ $ response = new Response (200 , [
74
+ 'Cache-Control ' => 'must-revalidate, max-age=3600 '
75
+ ], 'Revalidate data ' );
76
+
77
+ $ result = $ strategy ->cache ($ request , $ response );
78
+ $ this ->assertTrue ($ result , 'Request with Authorization header should be cached with must-revalidate directive ' );
79
+
80
+ $ cached = $ strategy ->fetch ($ request );
81
+ $ this ->assertNotNull ($ cached , 'Cache entry should exist for authorized request with must-revalidate directive ' );
82
+ $ this ->assertEquals ('Revalidate data ' , (string ) $ cached ->getResponse ()->getBody ());
83
+ }
84
+
85
+ /**
86
+ * Test that requests with Authorization header ARE cached when response has Cache-Control: s-maxage
87
+ */
88
+ public function testAuthorizationHeaderCachedWithSMaxage ()
89
+ {
90
+ $ storage = new VolatileRuntimeStorage ();
91
+ $ strategy = new PublicCacheStrategy ($ storage );
92
+
93
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
94
+ 'Authorization ' => 'Bearer secret-token '
95
+ ]);
96
+
97
+ $ response = new Response (200 , [
98
+ 'Cache-Control ' => 's-maxage=1800, max-age=3600 '
99
+ ], 'Shared cache data ' );
100
+
101
+ $ result = $ strategy ->cache ($ request , $ response );
102
+ $ this ->assertTrue ($ result , 'Request with Authorization header should be cached with s-maxage directive ' );
103
+
104
+ $ cached = $ strategy ->fetch ($ request );
105
+ $ this ->assertNotNull ($ cached , 'Cache entry should exist for authorized request with s-maxage directive ' );
106
+ $ this ->assertEquals ('Shared cache data ' , (string ) $ cached ->getResponse ()->getBody ());
107
+ }
108
+
109
+ /**
110
+ * Test that requests WITHOUT Authorization header are cached normally with max-age
111
+ */
112
+ public function testNoAuthorizationHeaderCachedWithMaxAge ()
113
+ {
114
+ $ storage = new VolatileRuntimeStorage ();
115
+ $ strategy = new PrivateCacheStrategy ($ storage );
116
+
117
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' );
118
+
119
+ $ response = new Response (200 , [
120
+ 'Cache-Control ' => 'max-age=3600 '
121
+ ], 'Public data ' );
122
+
123
+ $ result = $ strategy ->cache ($ request , $ response );
124
+ $ this ->assertTrue ($ result , 'Request without Authorization header should be cached normally ' );
125
+
126
+ $ cached = $ strategy ->fetch ($ request );
127
+ $ this ->assertNotNull ($ cached , 'Cache entry should exist for non-authorized request ' );
128
+ $ this ->assertEquals ('Public data ' , (string ) $ cached ->getResponse ()->getBody ());
129
+ }
130
+
131
+ /**
132
+ * Test PublicCacheStrategy behavior with Authorization headers
133
+ */
134
+ public function testPublicCacheStrategyWithAuthorization ()
135
+ {
136
+ $ storage = new VolatileRuntimeStorage ();
137
+ $ strategy = new PublicCacheStrategy ($ storage );
138
+
139
+ // Test that private cache with authorization is not cached in public strategy
140
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
141
+ 'Authorization ' => 'Bearer secret-token '
142
+ ]);
143
+
144
+ $ response = new Response (200 , [
145
+ 'Cache-Control ' => 'private, max-age=3600 '
146
+ ], 'Private data ' );
147
+
148
+ $ result = $ strategy ->cache ($ request , $ response );
149
+ $ this ->assertFalse ($ result , 'Private response should not be cached in public strategy ' );
150
+
151
+ // Test that public response with authorization is cached
152
+ $ response2 = new Response (200 , [
153
+ 'Cache-Control ' => 'public, max-age=3600 '
154
+ ], 'Public data ' );
155
+
156
+ $ result2 = $ strategy ->cache ($ request , $ response2 );
157
+ $ this ->assertTrue ($ result2 , 'Public response with authorization should be cached in public strategy ' );
158
+
159
+ $ cached = $ strategy ->fetch ($ request );
160
+ $ this ->assertNotNull ($ cached , 'Cache entry should exist for public authorized request ' );
161
+ $ this ->assertEquals ('Public data ' , (string ) $ cached ->getResponse ()->getBody ());
162
+ }
163
+
164
+ /**
165
+ * Test multiple allowed directives together
166
+ */
167
+ public function testMultipleAllowedDirectives ()
168
+ {
169
+ $ storage = new VolatileRuntimeStorage ();
170
+ $ strategy = new PublicCacheStrategy ($ storage );
171
+
172
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
173
+ 'Authorization ' => 'Bearer secret-token '
174
+ ]);
175
+
176
+ $ response = new Response (200 , [
177
+ 'Cache-Control ' => 'public, must-revalidate, s-maxage=1800, max-age=3600 '
178
+ ], 'Multi directive data ' );
179
+
180
+ $ result = $ strategy ->cache ($ request , $ response );
181
+ $ this ->assertTrue ($ result , 'Request with Authorization header should be cached with multiple allowed directives ' );
182
+
183
+ $ cached = $ strategy ->fetch ($ request );
184
+ $ this ->assertNotNull ($ cached , 'Cache entry should exist for authorized request with multiple allowed directives ' );
185
+ $ this ->assertEquals ('Multi directive data ' , (string ) $ cached ->getResponse ()->getBody ());
186
+ }
187
+
188
+ /**
189
+ * Test case sensitivity of Authorization header
190
+ */
191
+ public function testAuthorizationHeaderCaseSensitivity ()
192
+ {
193
+ $ storage = new VolatileRuntimeStorage ();
194
+ $ strategy = new PublicCacheStrategy ($ storage );
195
+
196
+ $ requests = [
197
+ new Request ('GET ' , 'https://api.example.com/data ' , ['Authorization ' => 'Bearer token ' ]),
198
+ new Request ('GET ' , 'https://api.example.com/data ' , ['authorization ' => 'Bearer token ' ]),
199
+ new Request ('GET ' , 'https://api.example.com/data ' , ['AUTHORIZATION ' => 'Bearer token ' ]),
200
+ ];
201
+
202
+ $ response = new Response (200 , [
203
+ 'Cache-Control ' => 'max-age=3600 '
204
+ ], 'Test data ' );
205
+
206
+ foreach ($ requests as $ request ) {
207
+ $ result = $ strategy ->cache ($ request , $ response );
208
+ $ this ->assertFalse ($ result , 'Authorization header should be detected regardless of case ' );
209
+
210
+ $ cached = $ strategy ->fetch ($ request );
211
+ $ this ->assertNull ($ cached , 'No cache entry should exist for any case variation of Authorization header ' );
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Test that other cache control directives still work as expected
217
+ */
218
+ public function testOtherCacheControlDirectivesStillWork ()
219
+ {
220
+ $ storage = new VolatileRuntimeStorage ();
221
+ $ strategy = new PublicCacheStrategy ($ storage );
222
+
223
+ // Test no-store still prevents caching even with authorization allowances
224
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
225
+ 'Authorization ' => 'Bearer secret-token '
226
+ ]);
227
+
228
+ $ response = new Response (200 , [
229
+ 'Cache-Control ' => 'public, no-store, max-age=3600 '
230
+ ], 'No store data ' );
231
+
232
+ $ result = $ strategy ->cache ($ request , $ response );
233
+ $ this ->assertFalse ($ result , 'no-store should still prevent caching even with public directive ' );
234
+
235
+ $ cached = $ strategy ->fetch ($ request );
236
+ $ this ->assertNull ($ cached , 'No cache entry should exist when no-store is present ' );
237
+ }
238
+
239
+ /**
240
+ * Test that PrivateCacheStrategy still caches requests with Authorization header normally
241
+ */
242
+ public function testPrivateCacheStrategyAllowsAuthorizationCaching ()
243
+ {
244
+ $ storage = new VolatileRuntimeStorage ();
245
+ $ strategy = new PrivateCacheStrategy ($ storage );
246
+
247
+ $ request = new Request ('GET ' , 'https://api.example.com/data ' , [
248
+ 'Authorization ' => 'Bearer secret-token '
249
+ ]);
250
+
251
+ // Private cache should cache this even with just max-age
252
+ $ response = new Response (200 , [
253
+ 'Cache-Control ' => 'max-age=3600 '
254
+ ], 'Private cache data ' );
255
+
256
+ $ result = $ strategy ->cache ($ request , $ response );
257
+ $ this ->assertTrue ($ result , 'Private cache should allow caching of authenticated requests ' );
258
+
259
+ $ cached = $ strategy ->fetch ($ request );
260
+ $ this ->assertNotNull ($ cached , 'Cache entry should exist in private cache for authenticated request ' );
261
+ $ this ->assertEquals ('Private cache data ' , (string ) $ cached ->getResponse ()->getBody ());
262
+ }
263
+ }
0 commit comments