a few enhancements to request.php

- added "secure" parameter to avoid boilerplate "if https && https != 'off'"
- added "accept" parameter containing request's HTTP_ACCEPT value if any
- Changed IP to always be REMOTE_ADDR, as this is the only "real" ip of the request.
- Added 'proxy' parameter containing any proxy-forwarded IP
- Changed getIpAddress to getProxyIpAddress
- renamed $vars to $forwarded to be a bit more explicit
- Removed REMOTE_ADDR from proxy forwarded addresses to detect
- change explode() to sscanf, will explain this later.
- added flags to the filter_var, will also explain later
- added getMethodOverride function to detect request method overrides

I did some research because I was wondering why it would be necessary to check
for a comma, and apparently some proxies do send a comma separated list of IP
addresses, with the originating client IP as the first one. It had a feeling
that instead of using explode() where the first value would always be returned,
there must be another way to get the first value of a token-delimited string,
or just the whole string if there was no token, and I bumped in to my old
friend sscanf. So the loop is now 3 levels.

As far as the flags, see: http://php.net/manual/en/filter.filters.flags.php

These ensure that any IP detected is not a useless IP behind a remote NAT.
For example, a corporate proxy might send HTTP_X_FORWARDED_FOR using the
internal IP of the user, but the only useful IP in this case is that of
the proxy, which PHP gets as REMOTE_ADDR.

If you find any of these changes acceptable but don't want to merge them
all, do feel free to implement whichever you like.

I was thinking of adding a getRequestMethod() function to check for
`$_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']` or `$_POST['_method']`
to allow clients to negotiate PUT/DELETE requests,
but personally I am indifferent to these, as I never use
methods beyond GET and POST (I'm not very RESTful I guess),
and it's not really my place to be writing an implementation
of either. Other frameworks seem to just overwrite the method
parameter so that it appears to be the overridden one.
pull/22/head
kafene 12 years ago
parent 7c00cb3eaa
commit 5270c6b23a

@ -46,7 +46,7 @@ class Request {
'base' => str_replace('\\', '/', dirname(getenv('SCRIPT_NAME'))),
'method' => getenv('REQUEST_METHOD') ?: 'GET',
'referrer' => getenv('HTTP_REFERER') ?: '',
'ip' => $this->getIpAddress(),
'ip' => getenv('REMOTE_ADDR'),
'ajax' => getenv('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest',
'scheme' => getenv('SERVER_PROTOCOL') ?: 'HTTP/1.1',
'user_agent' => getenv('HTTP_USER_AGENT') ?: '',
@ -56,7 +56,10 @@ class Request {
'query' => new Collection($_GET),
'data' => new Collection($_POST),
'cookies' => new Collection($_COOKIE),
'files' => new Collection($_FILES)
'files' => new Collection($_FILES),
'secure' => getenv('HTTPS') && getenv('HTTPS') != 'off',
'accept' => getenv('HTTP_ACCEPT'),
'proxy' => $this->getProxyIpAddress()
);
}
@ -109,28 +112,25 @@ class Request {
*
* @return string IP address
*/
private function getIpAddress() {
static $vars = array(
private function getProxyIpAddress() {
static $forwarded = array(
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'REMOTE_ADDR'
'HTTP_FORWARDED'
);
$flags = \FILTER_FLAG_NO_PRIV_RANGE | \FILTER_FLAG_NO_RES_RANGE;
foreach ($vars as $key) {
if (array_key_exists($key, $_SERVER) === true) {
foreach (explode(',', $_SERVER[$key]) as $ip) {
if (filter_var($ip, FILTER_VALIDATE_IP) !== false) {
return $ip;
foreach ($forwarded as $key) {
if (array_key_exists($key, $_SERVER)) {
sscanf($_SERVER[$key], '%[^,]', $ip);
if(filter_var($ip, FILTER_VALIDATE_IP, $flags) !== false) {
$this->proxy = $ip;
}
}
}
}
return '';
}
}
?>

Loading…
Cancel
Save