1 <?php
2 /**
3 * Request.php
4 *
5 * @author Elvyrra SAS
6 * @license http://rem.mit-license.org/ MIT
7 */
8
9 namespace Hawk;
10
11 /**
12 * This class define methods to get HTTP request information
13 *
14 * @package Core
15 */
16 final class Request extends Singleton{
17 /**
18 * The clientIp, registered as static variable, to avoid to calculate it each time
19 *
20 * @static
21 */
22 public $clientIp,
23
24 /**
25 * The request URI
26 *
27 * @var string
28 */
29 $uri,
30
31 /**
32 * The request method (GET, POST, PATCH, DELETE, PUT)
33 *
34 * @var string
35 */
36 $method,
37
38 /**
39 * The request parameters
40 *
41 * @var array
42 */
43 $params,
44
45 /**
46 * The request headers
47 *
48 * @var array
49 */
50 $headers,
51
52 /**
53 * The request body
54 *
55 * @var mixed
56 */
57 $body,
58
59 /**
60 * The uploaded files
61 *
62 * @var array
63 */
64 $files = array(),
65
66 /**
67 * The request sent cookies
68 *
69 * @var array
70 */
71 $cookies = array();
72
73 /**
74 * The request instance
75 *
76 * @var Request
77 */
78 protected static $instance;
79
80
81 /**
82 * Constrcutor, initialize the instance with the HTTP request data
83 */
84 protected function __construct(){
85 // Get the request method
86 $this->method = strtolower(getenv('REQUEST_METHOD'));
87
88 // Get the request uri
89 $this->uri = getenv('REQUEST_URI');
90
91 // Get the request headers
92 $this->headers = getallheaders();
93
94 // Get the request parameters
95 $this->params = $_GET;
96
97 // Retrive the body
98 if($this->getHeaders('Content-Type') === 'application/json') {
99 $this->body = json_decode(file_get_contents('php://input'), true);
100 }
101 else{
102 $this->body = $_POST;
103 }
104
105 // Retreive the client IP
106 if ($this->getHeaders('X-Forwarded-For')) {
107 // The user is behind a proxy that transmit HTTP_X_FORWARDED_FOR header
108 if (! preg_match('![0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}!', $this->getHeaders('X-Forwarded-For'))) {
109 // The format of HTTP_X_FORWARDED_FOR header is not correct
110 $this->clientIp = getenv('REMOTE_ADDR');
111 }
112 else{
113 // Get the last public IP in HTTP_X_FORWARDED_FOR header
114 $chain = explode(',', preg_replace('/[^0-9,.]/', '', self::getHeaders('X-Forwarded-For')));
115 for($i = 0 ; $i <= count($chain); $i ++){
116 $ip = $chain[$i];
117
118 if((!preg_match("!^(192\.168|10\.0\.0)!", $ip) && $ip != "127.0.0.1") || $i == count($chain) - 1) {
119 $this->clientIp = $ip;
120 break;
121 }
122 }
123 }
124 }
125 else{
126 // X-Forwarded-For header has not been transmitted, get the REMOTE_ADDR header
127 $this->clientIp = getenv('REMOTE_ADDR');
128 }
129
130 // Get the request uploaded files
131 $this->files = $_FILES;
132
133 // Get the request cookies
134 $this->cookies = $_COOKIE;
135 }
136
137
138 /**
139 * Get the HTTP request method
140 *
141 * @return string the HTTP request method
142 */
143 public function getMethod(){
144 return $this->method;
145 }
146
147
148 /**
149 * Get the HTTP request URI
150 *
151 * @return string The HTTP request URI
152 */
153 public function getUri(){
154 return $this->uri;
155 }
156
157
158 /**
159 * Check if the request is an AJAX request
160 *
161 * @return true if the request is an AJAX request else false
162 */
163 public function isAjax(){
164 return strtolower($this->getHeaders('X-Requested-With')) === 'xmlhttprequest';
165 }
166
167
168 /**
169 * Get the client IP address.
170 *
171 * @return string The IPV4 address of the client that performed the HTTP request
172 */
173 public function clientIp(){
174 return $this->clientIp;
175 }
176
177
178 /**
179 * This function returns the value of the variable $name in the request body, or all the body if $name is not provided
180 *
181 * @param string $name The variable name
182 *
183 * @return string|array The parameter value or all the body
184 */
185 public function getBody($name = ""){
186 if($name) {
187 return isset($this->body[$name]) ? $this->body[$name] : null;
188 }
189 else{
190 return $this->body;
191 }
192 }
193
194 /**
195 * Get the request uploaded files for the given name, or all files if $name is not provided
196 *
197 * @param string $name The key in $_FILES to get
198 *
199 * @return string|array The file or all files
200 */
201 public function getFiles($name = ''){
202 if($name) {
203 return isset($this->files[$name]) ? $this->files[$name] : array();
204 }
205 else{
206 return $this->files;
207 }
208 }
209
210 /**
211 * This function returns the value of the parameter $name, or all the parameters if $name is not provided
212 *
213 * @param string $name The parameter name
214 *
215 * @return string|array The parameter value or all the parameters
216 */
217 public function getParams($name = ""){
218 if($name) {
219 return isset($this->params[$name]) ? $this->params[$name] : null;
220 }
221 else{
222 return $this->params;
223 }
224 }
225
226 /**
227 * This function returns the header value for the key $name, of all the headers if $name is not provided
228 *
229 * @param string $name The header key
230 *
231 * @return string|array The header value or all the headers
232 */
233 public function getHeaders($name = ""){
234 if($name) {
235 return isset($this->headers[$name]) ? $this->headers[$name] : null;
236 }
237 else{
238 return $this->headers;
239 }
240 }
241
242 /**
243 * This function returns the value of the cookie named $name, or all cookies if $name is not provided
244 *
245 * @param string $name The cookie name
246 *
247 * @return string|array The cookie value or all the cookies
248 */
249 public function getCookies($name = ""){
250 if($name) {
251 return isset($this->cookies[$name]) ? $this->cookies[$name] : null;
252 }
253 else{
254 return $this->cookies;
255 }
256 }
257 }
258