-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIpAddressParser.php
More file actions
127 lines (105 loc) · 3.15 KB
/
IpAddressParser.php
File metadata and controls
127 lines (105 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<?php
declare(strict_types=1);
namespace Lit\Middleware\IpAddress;
use Lit\Nimo\Middlewares\AbstractMiddleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class IpAddressParser extends AbstractMiddleware
{
/**
* @var array
*/
protected $trustedProxies;
/**
* @var array
*/
protected $headers;
/**
* @var ?string
*/
protected $ipAddress;
public function __construct(
array $trustedProxies = [],
array $headers = []
) {
$this->trustedProxies = $trustedProxies;
$this->headers = $headers;
}
/**
* @return string
*/
public function getIpAddress(): ?string
{
return $this->ipAddress;
}
public static function getIpAddressFromRequest(
ServerRequestInterface $request,
array $trustedProxies = [],
array $headers = []
): ?string {
$headers = $headers ?: [
'Forwarded',
'X-Forwarded-For',
'X-Forwarded',
'X-Cluster-Client-Ip',
'Client-Ip',
];
$params = $request->getServerParams();
$remoteAddr = $params['REMOTE_ADDR'] ?? '';
if (!self::isValidIpAddress($remoteAddr)) {
return null;
}
if (empty($trustedProxies) || !in_array($remoteAddr, $trustedProxies)) {
return $remoteAddr;
}
$ip = self::getIpAddressFromHeaders($request, $headers);
if (!empty($ip)) {
return $ip;
}
return $remoteAddr;
}
protected function main(): ResponseInterface
{
$this->attachToRequest();
$this->ipAddress = static::getIpAddressFromRequest($this->request, $this->trustedProxies, $this->headers);
return $this->delegate();
}
protected static function isValidIpAddress(string $ip): bool
{
return false !== filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6);
}
/**
* @param ServerRequestInterface $request
* @param string[] $headers
* @return null|string
*/
protected static function getIpAddressFromHeaders(ServerRequestInterface $request, array $headers): ?string
{
foreach ($headers as $headerName) {
$headerValue = trim(explode(',', $request->getHeaderLine($headerName))[0]);
if (empty($headerValue)) {
continue;
}
if (strtolower($headerName) == 'forwarded') {
$headerValue = static::parseForwarded($headerValue);
}
if (is_null($headerValue)) {
continue;
}
if (static::isValidIpAddress($headerValue)) {
return $headerValue;
}
}
return null;
}
protected static function parseForwarded($headerValue): ?string
{
foreach (explode(';', $headerValue) as $headerPart) {
if (strtolower(substr($headerPart, 0, 4)) == 'for=') {
$for = explode(']', $headerPart);
return trim(substr($for[0], 4), " \t\n\r\0\x0B\"[]");
}
}
return null;
}
}