1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * Redistributions of files must retain the above copyright notice.
8: *
9: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
10: * @link https://cakephp.org CakePHP(tm) Project
11: * @since 3.0.0
12: * @license https://opensource.org/licenses/mit-license.php MIT License
13: */
14: namespace Cake\Http\Client;
15:
16: use Cake\Core\Exception\Exception;
17: use Psr\Http\Message\RequestInterface;
18: use Zend\Diactoros\RequestTrait;
19: use Zend\Diactoros\Stream;
20:
21: /**
22: * Implements methods for HTTP requests.
23: *
24: * Used by Cake\Http\Client to contain request information
25: * for making requests.
26: */
27: class Request extends Message implements RequestInterface
28: {
29: use RequestTrait;
30:
31: /**
32: * Constructor
33: *
34: * Provides backwards compatible defaults for some properties.
35: *
36: * @param string $url The request URL
37: * @param string $method The HTTP method to use.
38: * @param array $headers The HTTP headers to set.
39: * @param array|string|null $data The request body to use.
40: */
41: public function __construct($url = '', $method = self::METHOD_GET, array $headers = [], $data = null)
42: {
43: $this->validateMethod($method);
44: $this->method = $method;
45: $this->uri = $this->createUri($url);
46: $headers += [
47: 'Connection' => 'close',
48: 'User-Agent' => 'CakePHP'
49: ];
50: $this->addHeaders($headers);
51: $this->body($data);
52: }
53:
54: /**
55: * Get/Set the HTTP method.
56: *
57: * *Warning* This method mutates the request in-place for backwards
58: * compatibility reasons, and is not part of the PSR7 interface.
59: *
60: * @param string|null $method The method for the request.
61: * @return $this|string Either this or the current method.
62: * @throws \Cake\Core\Exception\Exception On invalid methods.
63: * @deprecated 3.3.0 Use getMethod() and withMethod() instead.
64: */
65: public function method($method = null)
66: {
67: deprecationWarning(
68: 'Request::method() is deprecated. ' .
69: 'Use getMethod() and withMethod() instead.'
70: );
71:
72: if ($method === null) {
73: return $this->method;
74: }
75: $name = get_called_class() . '::METHOD_' . strtoupper($method);
76: if (!defined($name)) {
77: throw new Exception('Invalid method type');
78: }
79: $this->method = $method;
80:
81: return $this;
82: }
83:
84: /**
85: * Get/Set the url for the request.
86: *
87: * *Warning* This method mutates the request in-place for backwards
88: * compatibility reasons, and is not part of the PSR7 interface.
89: *
90: * @param string|null $url The url for the request. Leave null for get
91: * @return $this|string Either $this or the url value.
92: * @deprecated 3.3.0 Use getUri() and withUri() instead.
93: */
94: public function url($url = null)
95: {
96: deprecationWarning(
97: 'Request::url() is deprecated. ' .
98: 'Use getUri() and withUri() instead.'
99: );
100:
101: if ($url === null) {
102: return '' . $this->getUri();
103: }
104: $this->uri = $this->createUri($url);
105:
106: return $this;
107: }
108:
109: /**
110: * Get/Set headers into the request.
111: *
112: * You can get the value of a header, or set one/many headers.
113: * Headers are set / fetched in a case insensitive way.
114: *
115: * ### Getting headers
116: *
117: * ```
118: * $request->header('Content-Type');
119: * ```
120: *
121: * ### Setting one header
122: *
123: * ```
124: * $request->header('Content-Type', 'application/json');
125: * ```
126: *
127: * ### Setting multiple headers
128: *
129: * ```
130: * $request->header(['Connection' => 'close', 'User-Agent' => 'CakePHP']);
131: * ```
132: *
133: * *Warning* This method mutates the request in-place for backwards
134: * compatibility reasons, and is not part of the PSR7 interface.
135: *
136: * @param string|array|null $name The name to get, or array of multiple values to set.
137: * @param string|null $value The value to set for the header.
138: * @return mixed Either $this when setting or header value when getting.
139: * @deprecated 3.3.0 Use withHeader() and getHeaderLine() instead.
140: */
141: public function header($name = null, $value = null)
142: {
143: deprecationWarning(
144: 'Request::header() is deprecated. ' .
145: 'Use withHeader() and getHeaderLine() instead.'
146: );
147:
148: if ($value === null && is_string($name)) {
149: $val = $this->getHeaderLine($name);
150: if ($val === '') {
151: return null;
152: }
153:
154: return $val;
155: }
156:
157: if ($value !== null && !is_array($name)) {
158: $name = [$name => $value];
159: }
160: $this->addHeaders($name);
161:
162: return $this;
163: }
164:
165: /**
166: * Add an array of headers to the request.
167: *
168: * @param array $headers The headers to add.
169: * @return void
170: */
171: protected function addHeaders(array $headers)
172: {
173: foreach ($headers as $key => $val) {
174: $normalized = strtolower($key);
175: $this->headers[$key] = (array)$val;
176: $this->headerNames[$normalized] = $key;
177: }
178: }
179:
180: /**
181: * Get/Set cookie values.
182: *
183: * ### Getting a cookie
184: *
185: * ```
186: * $request->cookie('session');
187: * ```
188: *
189: * ### Setting one cookie
190: *
191: * ```
192: * $request->cookie('session', '123456');
193: * ```
194: *
195: * ### Setting multiple headers
196: *
197: * ```
198: * $request->cookie(['test' => 'value', 'split' => 'banana']);
199: * ```
200: *
201: * @param string $name The name of the cookie to get/set
202: * @param string|null $value Either the value or null when getting values.
203: * @return mixed Either $this or the cookie value.
204: * @deprecated 3.5.0 No longer used. CookieCollections now add `Cookie` header to the request
205: * before sending. Use Cake\Http\Cookie\CookieCollection::addToRequest() to make adding cookies
206: * to a request easier.
207: */
208: public function cookie($name, $value = null)
209: {
210: deprecationWarning(
211: 'Request::cookie() is deprecated. ' .
212: 'The Client internals now add the required `Cookie` header to the ' .
213: 'request before sending. Use Cake\Http\Cookie\CookieCollection::addToRequest() ' .
214: 'to make adding cookies to a request easier.'
215: );
216:
217: if ($value === null && is_string($name)) {
218: return isset($this->_cookies[$name]) ? $this->_cookies[$name] : null;
219: }
220: if (is_string($name) && is_string($value)) {
221: $name = [$name => $value];
222: }
223: foreach ($name as $key => $val) {
224: $this->_cookies[$key] = $val;
225: }
226:
227: return $this;
228: }
229:
230: /**
231: * Get/Set HTTP version.
232: *
233: * *Warning* This method mutates the request in-place for backwards
234: * compatibility reasons, and is not part of the PSR7 interface.
235: *
236: * @param string|null $version The HTTP version.
237: * @return $this|string Either $this or the HTTP version.
238: * @deprecated 3.3.0 Use getProtocolVersion() and withProtocolVersion() instead.
239: */
240: public function version($version = null)
241: {
242: deprecationWarning(
243: 'Request::version() is deprecated. ' .
244: 'Use getProtocolVersion() and withProtocolVersion() instead.'
245: );
246:
247: if ($version === null) {
248: return $this->protocol;
249: }
250:
251: $this->protocol = $version;
252:
253: return $this;
254: }
255:
256: /**
257: * Get/set the body/payload for the message.
258: *
259: * Array data will be serialized with Cake\Http\FormData,
260: * and the content-type will be set.
261: *
262: * @param string|array|null $body The body for the request. Leave null for get
263: * @return mixed Either $this or the body value.
264: */
265: public function body($body = null)
266: {
267: if ($body === null) {
268: $body = $this->getBody();
269:
270: return $body ? $body->__toString() : '';
271: }
272: if (is_array($body)) {
273: $formData = new FormData();
274: $formData->addMany($body);
275: $this->addHeaders(['Content-Type' => $formData->contentType()]);
276: $body = (string)$formData;
277: }
278: $stream = new Stream('php://memory', 'rw');
279: $stream->write($body);
280: $this->stream = $stream;
281:
282: return $this;
283: }
284: }
285:
286: // @deprecated 3.4.0 Add backwards compact alias.
287: class_alias('Cake\Http\Client\Request', 'Cake\Network\Http\Request');
288: