新增maxmind数据库本地判断国家,并且将优先级调整至最高
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
class GeoIpCountryResolver
|
||||
{
|
||||
/** @var GeoIp2\Database\Reader|null */
|
||||
private static $reader = null;
|
||||
|
||||
/** @var array<string, string|null> */
|
||||
private static $requestCache = [];
|
||||
|
||||
/** @var string|null */
|
||||
private static $lastSource = null;
|
||||
|
||||
/**
|
||||
* @param string $ip
|
||||
* @return array{code:?string, source:string}
|
||||
*/
|
||||
public static function resolveWithMeta($ip)
|
||||
{
|
||||
$ip = ClientIpResolver::normalizeIp($ip);
|
||||
if ($ip === null) {
|
||||
self::$lastSource = 'invalid_ip';
|
||||
return ['code' => null, 'source' => 'invalid_ip'];
|
||||
}
|
||||
|
||||
if (array_key_exists($ip, self::$requestCache)) {
|
||||
self::$lastSource = 'request';
|
||||
return ['code' => self::$requestCache[$ip], 'source' => 'request'];
|
||||
}
|
||||
|
||||
$cached = GeoIpCountryCache::get($ip);
|
||||
if ($cached !== false) {
|
||||
self::$requestCache[$ip] = $cached;
|
||||
self::$lastSource = 'cache';
|
||||
return ['code' => $cached, 'source' => 'cache'];
|
||||
}
|
||||
|
||||
$code = self::lookupMmdb($ip);
|
||||
GeoIpCountryCache::set($ip, $code);
|
||||
self::$requestCache[$ip] = $code;
|
||||
self::$lastSource = 'mmdb';
|
||||
return ['code' => $code, 'source' => 'mmdb'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ip
|
||||
* @return string|null ISO 3166-1 alpha-2
|
||||
*/
|
||||
public static function resolve($ip)
|
||||
{
|
||||
$result = self::resolveWithMeta($ip);
|
||||
return $result['code'];
|
||||
}
|
||||
|
||||
public static function lastSource()
|
||||
{
|
||||
return self::$lastSource ?? '';
|
||||
}
|
||||
|
||||
public static function isAvailable()
|
||||
{
|
||||
return self::getReader() !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ip
|
||||
* @return string|null
|
||||
*/
|
||||
private static function lookupMmdb($ip)
|
||||
{
|
||||
$reader = self::getReader();
|
||||
if ($reader === null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$record = $reader->country($ip);
|
||||
$code = $record->country->isoCode ?? null;
|
||||
if ($code === null || $code === '') {
|
||||
return null;
|
||||
}
|
||||
return strtoupper((string) $code);
|
||||
} catch (GeoIp2\Exception\AddressNotFoundException $e) {
|
||||
return null;
|
||||
} catch (Throwable $e) {
|
||||
GeoIpCountryCache::logError('mmdb lookup failed: ' . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GeoIp2\Database\Reader|null
|
||||
*/
|
||||
private static function getReader()
|
||||
{
|
||||
if (self::$reader !== null) {
|
||||
return self::$reader;
|
||||
}
|
||||
if (!class_exists('GeoIp2\\Database\\Reader')) {
|
||||
return null;
|
||||
}
|
||||
if (!defined('CLOAK_GEOIP_DB_PATH') || !is_file(CLOAK_GEOIP_DB_PATH)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
self::$reader = new GeoIp2\Database\Reader(CLOAK_GEOIP_DB_PATH);
|
||||
return self::$reader;
|
||||
} catch (Throwable $e) {
|
||||
GeoIpCountryCache::logError('Reader init failed: ' . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user