39
39
* - delete()
40
40
* - patch()
41
41
*
42
+ * ### Cookie management
43
+ *
44
+ * Client will maintain cookies from the responses done with
45
+ * a client instance. These cookies will be automatically added
46
+ * to future requests to matching hosts. Cookies will respect the
47
+ * `Expires` and `Domain` attributes. You can get the list of
48
+ * currently stored cookies using the cookies() method.
49
+ *
42
50
* ### Sending request bodies
43
51
*
44
52
* By default any POST/PUT/PATCH/DELETE request with $data will
67
75
* ### Using proxies
68
76
*
69
77
* By using the `proxy` key you can set authentication credentials for
70
- * a proxy if you need to use one.. The type sub option can be used to
78
+ * a proxy if you need to use one.. The type sub option can be used to
71
79
* specify which authentication strategy you want to use.
72
- * CakePHP comes with a few built-in strategies:
73
- *
74
- * - Basic
75
- * - Digest
80
+ * CakePHP comes with built-in support for basic authentication.
76
81
*
77
82
*/
78
83
class Client {
@@ -93,6 +98,16 @@ class Client {
93
98
'redirect ' => false ,
94
99
];
95
100
101
+ /**
102
+ * List of cookies from responses made with this client.
103
+ *
104
+ * Cookies are indexed by the cookie's domain or
105
+ * request host name.
106
+ *
107
+ * @var array
108
+ */
109
+ protected $ _cookies = [];
110
+
96
111
/**
97
112
* Adapter for sending requests. Defaults to
98
113
* Cake\Network\Http\Stream
@@ -153,6 +168,15 @@ public function config($config = null) {
153
168
return $ this ;
154
169
}
155
170
171
+ /**
172
+ * Get the cookies stored in the Client.
173
+ *
174
+ * @return array
175
+ */
176
+ public function cookies () {
177
+ return $ this ->_cookies ;
178
+ }
179
+
156
180
/**
157
181
* Do a GET request.
158
182
*
@@ -275,13 +299,60 @@ protected function _mergeOptions($options) {
275
299
* @return Cake\Network\Http\Response
276
300
*/
277
301
public function send (Request $ request , $ options = []) {
278
- // TODO possibly implment support for
279
- // holding onto cookies so subsequent requests
280
- // can share cookies.
281
302
$ responses = $ this ->_adapter ->send ($ request , $ options );
303
+ $ host = parse_url ($ request ->url (), PHP_URL_HOST );
304
+ foreach ($ responses as $ response ) {
305
+ $ this ->_storeCookies ($ response , $ host );
306
+ }
282
307
return array_pop ($ responses );
283
308
}
284
309
310
+ /**
311
+ * Store cookies in a response to be used in future requests.
312
+ *
313
+ * Non-expired cookies will be stored for use in future requests
314
+ * made with the same Client instance. Cookies are not saved
315
+ * between instances.
316
+ *
317
+ * @param Response $response The response to read cookies from
318
+ * @param string $host The request host, used for getting host names
319
+ * in case the cookies didn't set a domain.
320
+ * @return void
321
+ */
322
+ protected function _storeCookies (Response $ response , $ host ) {
323
+ $ cookies = $ response ->cookies ();
324
+ foreach ($ cookies as $ name => $ cookie ) {
325
+ $ expires = isset ($ cookie ['expires ' ]) ? $ cookie ['expires ' ] : false ;
326
+ $ domain = isset ($ cookie ['domain ' ]) ? $ cookie ['domain ' ] : $ host ;
327
+ $ domain = trim ($ domain , '. ' );
328
+ if ($ expires ) {
329
+ $ expires = \DateTime::createFromFormat ('D, j-M-Y H:i:s e ' , $ expires );
330
+ }
331
+ if ($ expires && $ expires ->getTimestamp () <= time ()) {
332
+ continue ;
333
+ }
334
+ if (empty ($ this ->_cookies [$ domain ])) {
335
+ $ this ->_cookies [$ domain ] = [];
336
+ }
337
+ $ this ->_cookies [$ domain ][$ name ] = $ cookie ['value ' ];
338
+ }
339
+ }
340
+
341
+ /**
342
+ * Adds cookies stored in the client to the request.
343
+ *
344
+ * Uses the request's host to find matching cookies.
345
+ *
346
+ * @param Request $request
347
+ * @return void
348
+ */
349
+ protected function _addCookies (Request $ request ) {
350
+ $ host = parse_url ($ request ->url (), PHP_URL_HOST );
351
+ if (isset ($ this ->_cookies [$ host ])) {
352
+ $ request ->cookie ($ this ->_cookies [$ host ]);
353
+ }
354
+ }
355
+
285
356
/**
286
357
* Generate a URL based on the scoped client options.
287
358
*
@@ -339,6 +410,7 @@ protected function _createRequest($method, $url, $data, $options) {
339
410
if (isset ($ options ['headers ' ])) {
340
411
$ request ->header ($ options ['headers ' ]);
341
412
}
413
+ $ this ->_addCookies ($ request );
342
414
if (isset ($ options ['cookies ' ])) {
343
415
$ request ->cookie ($ options ['cookies ' ]);
344
416
}
0 commit comments