bzr branch
http://bzr.ed.am/www/slight
1
by Tim Marston
initial commit |
1 |
<?php |
2 |
/** |
|
3 |
* Flight: An extensible micro-framework. |
|
4 |
* |
|
5 |
* @copyright Copyright (c) 2011, Mike Cao <mike@mikecao.com> |
|
6 |
* @license MIT, http://flightphp.com/license |
|
7 |
*/ |
|
8 |
||
9 |
namespace flight\net; |
|
10 |
||
11 |
use flight\util\Collection; |
|
12 |
||
13 |
/** |
|
14 |
* The Request class represents an HTTP request. Data from |
|
15 |
* all the super globals $_GET, $_POST, $_COOKIE, and $_FILES |
|
16 |
* are stored and accessible via the Request object. |
|
17 |
* |
|
18 |
* The default request properties are: |
|
19 |
* url - The URL being requested |
|
20 |
* base - The parent subdirectory of the URL |
|
21 |
* method - The request method (GET, POST, PUT, DELETE) |
|
22 |
* referrer - The referrer URL |
|
23 |
* ip - IP address of the client |
|
24 |
* ajax - Whether the request is an AJAX request |
|
25 |
* scheme - The server protocol (http, https) |
|
26 |
* user_agent - Browser information |
|
27 |
* type - The content type |
|
28 |
* length - The content length |
|
29 |
* query - Query string parameters |
|
30 |
* data - Post parameters |
|
31 |
* cookies - Cookie parameters |
|
32 |
* files - Uploaded files |
|
33 |
* secure - Connection is secure |
|
34 |
* accept - HTTP accept parameters |
|
35 |
* proxy_ip - Proxy IP address of the client |
|
36 |
*/ |
|
37 |
class Request { |
|
38 |
/** |
|
39 |
* @var string URL being requested |
|
40 |
*/ |
|
41 |
public $url; |
|
42 |
||
43 |
/** |
|
44 |
* @var string Parent subdirectory of the URL |
|
45 |
*/ |
|
46 |
public $base; |
|
47 |
||
48 |
/** |
|
49 |
* @var string Request method (GET, POST, PUT, DELETE) |
|
50 |
*/ |
|
51 |
public $method; |
|
52 |
||
53 |
/** |
|
54 |
* @var string Referrer URL |
|
55 |
*/ |
|
56 |
public $referrer; |
|
57 |
||
58 |
/** |
|
59 |
* @var string IP address of the client |
|
60 |
*/ |
|
61 |
public $ip; |
|
62 |
||
63 |
/** |
|
64 |
* @var bool Whether the request is an AJAX request |
|
65 |
*/ |
|
66 |
public $ajax; |
|
67 |
||
68 |
/** |
|
69 |
* @var string Server protocol (http, https) |
|
70 |
*/ |
|
71 |
public $scheme; |
|
72 |
||
73 |
/** |
|
74 |
* @var string Browser information |
|
75 |
*/ |
|
76 |
public $user_agent; |
|
77 |
||
78 |
/** |
|
79 |
* @var string Content type |
|
80 |
*/ |
|
81 |
public $type; |
|
82 |
||
83 |
/** |
|
84 |
* @var int Content length |
|
85 |
*/ |
|
86 |
public $length; |
|
87 |
||
88 |
/** |
|
89 |
* @var \flight\util\Collection Query string parameters |
|
90 |
*/ |
|
91 |
public $query; |
|
92 |
||
93 |
/** |
|
94 |
* @var \flight\util\Collection Post parameters |
|
95 |
*/ |
|
96 |
public $data; |
|
97 |
||
98 |
/** |
|
99 |
* @var \flight\util\Collection Cookie parameters |
|
100 |
*/ |
|
101 |
public $cookies; |
|
102 |
||
103 |
/** |
|
104 |
* @var \flight\util\Collection Uploaded files |
|
105 |
*/ |
|
106 |
public $files; |
|
107 |
||
108 |
/** |
|
109 |
* @var bool Whether the connection is secure |
|
110 |
*/ |
|
111 |
public $secure; |
|
112 |
||
113 |
/** |
|
114 |
* @var string HTTP accept parameters |
|
115 |
*/ |
|
116 |
public $accept; |
|
117 |
||
118 |
/** |
|
119 |
* @var string Proxy IP address of the client |
|
120 |
*/ |
|
121 |
public $proxy_ip; |
|
122 |
||
123 |
/** |
|
124 |
* Constructor. |
|
125 |
* |
|
126 |
* @param array $config Request configuration |
|
127 |
*/ |
|
128 |
public function __construct($config = array()) { |
|
129 |
// Default properties |
|
130 |
if (empty($config)) { |
|
131 |
$config = array( |
|
132 |
'url' => self::getVar('REQUEST_URI', '/'), |
|
133 |
'base' => str_replace(array('\\',' '), array('/','%20'), dirname(self::getVar('SCRIPT_NAME'))), |
|
134 |
'method' => self::getMethod(), |
|
135 |
'referrer' => self::getVar('HTTP_REFERER'), |
|
136 |
'ip' => self::getVar('REMOTE_ADDR'), |
|
137 |
'ajax' => self::getVar('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest', |
|
138 |
'scheme' => self::getVar('SERVER_PROTOCOL', 'HTTP/1.1'), |
|
139 |
'user_agent' => self::getVar('HTTP_USER_AGENT'), |
|
140 |
'type' => self::getVar('CONTENT_TYPE'), |
|
141 |
'length' => self::getVar('CONTENT_LENGTH', 0), |
|
142 |
'query' => new Collection($_GET), |
|
143 |
'data' => new Collection($_POST), |
|
144 |
'cookies' => new Collection($_COOKIE), |
|
145 |
'files' => new Collection($_FILES), |
|
146 |
'secure' => self::getVar('HTTPS', 'off') != 'off', |
|
147 |
'accept' => self::getVar('HTTP_ACCEPT'), |
|
148 |
'proxy_ip' => self::getProxyIpAddress() |
|
149 |
); |
|
150 |
} |
|
151 |
||
152 |
$this->init($config); |
|
153 |
} |
|
154 |
||
155 |
/** |
|
156 |
* Initialize request properties. |
|
157 |
* |
|
158 |
* @param array $properties Array of request properties |
|
159 |
*/ |
|
160 |
public function init($properties = array()) { |
|
161 |
// Set all the defined properties |
|
162 |
foreach ($properties as $name => $value) { |
|
163 |
$this->$name = $value; |
|
164 |
} |
|
165 |
||
166 |
// Get the requested URL without the base directory |
|
167 |
if ($this->base != '/' && strlen($this->base) > 0 && strpos($this->url, $this->base) === 0) { |
|
168 |
$this->url = substr($this->url, strlen($this->base)); |
|
169 |
} |
|
170 |
||
171 |
// Default url |
|
172 |
if (empty($this->url)) { |
|
173 |
$this->url = '/'; |
|
174 |
} |
|
175 |
// Merge URL query parameters with $_GET |
|
176 |
else { |
|
177 |
$_GET += self::parseQuery($this->url); |
|
178 |
||
179 |
$this->query->setData($_GET); |
|
180 |
} |
|
181 |
||
182 |
// Check for JSON input |
|
183 |
if (strpos($this->type, 'application/json') === 0) { |
|
184 |
$body = $this->getBody(); |
|
185 |
if ($body != '') { |
|
186 |
$data = json_decode($body, true); |
|
187 |
if ($data != null) { |
|
188 |
$this->data->setData($data); |
|
189 |
} |
|
190 |
} |
|
191 |
} |
|
192 |
} |
|
193 |
||
194 |
/** |
|
195 |
* Gets the body of the request. |
|
196 |
* |
|
197 |
* @return string Raw HTTP request body |
|
198 |
*/ |
|
199 |
public static function getBody() { |
|
200 |
static $body; |
|
201 |
||
202 |
if (!is_null($body)) { |
|
203 |
return $body; |
|
204 |
} |
|
205 |
||
206 |
$method = self::getMethod(); |
|
207 |
||
208 |
if ($method == 'POST' || $method == 'PUT' || $method == 'PATCH') { |
|
209 |
$body = file_get_contents('php://input'); |
|
210 |
} |
|
211 |
||
212 |
return $body; |
|
213 |
} |
|
214 |
||
215 |
/** |
|
216 |
* Gets the request method. |
|
217 |
* |
|
218 |
* @return string |
|
219 |
*/ |
|
220 |
public static function getMethod() { |
|
221 |
$method = self::getVar('REQUEST_METHOD', 'GET'); |
|
222 |
||
223 |
if (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { |
|
224 |
$method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; |
|
225 |
} |
|
226 |
elseif (isset($_REQUEST['_method'])) { |
|
227 |
$method = $_REQUEST['_method']; |
|
228 |
} |
|
229 |
||
230 |
return strtoupper($method); |
|
231 |
} |
|
232 |
||
233 |
/** |
|
234 |
* Gets the real remote IP address. |
|
235 |
* |
|
236 |
* @return string IP address |
|
237 |
*/ |
|
238 |
public static function getProxyIpAddress() { |
|
239 |
static $forwarded = array( |
|
240 |
'HTTP_CLIENT_IP', |
|
241 |
'HTTP_X_FORWARDED_FOR', |
|
242 |
'HTTP_X_FORWARDED', |
|
243 |
'HTTP_X_CLUSTER_CLIENT_IP', |
|
244 |
'HTTP_FORWARDED_FOR', |
|
245 |
'HTTP_FORWARDED' |
|
246 |
); |
|
247 |
||
248 |
$flags = \FILTER_FLAG_NO_PRIV_RANGE | \FILTER_FLAG_NO_RES_RANGE; |
|
249 |
||
250 |
foreach ($forwarded as $key) { |
|
251 |
if (array_key_exists($key, $_SERVER)) { |
|
252 |
sscanf($_SERVER[$key], '%[^,]', $ip); |
|
253 |
if (filter_var($ip, \FILTER_VALIDATE_IP, $flags) !== false) { |
|
254 |
return $ip; |
|
255 |
} |
|
256 |
} |
|
257 |
} |
|
258 |
||
259 |
return ''; |
|
260 |
} |
|
261 |
||
262 |
/** |
|
263 |
* Gets a variable from $_SERVER using $default if not provided. |
|
264 |
* |
|
265 |
* @param string $var Variable name |
|
266 |
* @param string $default Default value to substitute |
|
267 |
* @return string Server variable value |
|
268 |
*/ |
|
269 |
public static function getVar($var, $default = '') { |
|
270 |
return isset($_SERVER[$var]) ? $_SERVER[$var] : $default; |
|
271 |
} |
|
272 |
||
273 |
/** |
|
274 |
* Parse query parameters from a URL. |
|
275 |
* |
|
276 |
* @param string $url URL string |
|
277 |
* @return array Query parameters |
|
278 |
*/ |
|
279 |
public static function parseQuery($url) { |
|
280 |
$params = array(); |
|
281 |
||
282 |
$args = parse_url($url); |
|
283 |
if (isset($args['query'])) { |
|
284 |
parse_str($args['query'], $params); |
|
285 |
} |
|
286 |
||
287 |
return $params; |
|
288 |
} |
|
289 |
} |