germania-kg / ipstack-client
支持 PSR-6 缓存和 Slim3 中间件的 ipstack API PHP 客户端
Requires
- php: ^7.0|^8.0
- guzzlehttp/guzzle: ^6.3|^7.0
- psr/cache: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- php-coveralls/php-coveralls: ^2.0
- phpspec/prophecy-phpunit: ^2.0
- phpunit/phpunit: ^9.0
- symfony/cache: ^5.0
README
支持缓存和中间件的 ipstack API PHP 客户端
安装
$ composer require germania-kg/ipstack
使用 ipstack
<?php use Germania\IpstackClient\IpstackClient; // Setup the Client $endpoint = "http://api.ipstack.com/"; $api_key = "your_api_key"; $ipstack = new IpstackClient( $endpoint, $api_key); // Ask ipstack $client_ip = "8.8.8.8"; $response = $ipstack->get( $client_ip );
响应示例
IpstackClient 内部使用数组,因此要求 ipstack 返回 JSON。以下是一个简化的示例;完整示例请参见 ipstack 的 标准 IP 查询 文档
Array ()
[ip] => 8.8.8.8
[type] => ipv4
[continent_code] => EU
[continent_name] => Europe
[country_code] => DE
[country_name] => Germany
[region_code] => SH
[region_name] => Schleswig-Holstein
[latitude] => 54.3667
[longitude] => 10.2
...
)
自定义响应
您可以通过在底层请求中添加某些字段来自定义 ipstack 响应,具体请参见 ipstack 在 “指定响应字段” 上的文档。只需传递一个包含查询字段的数组,这些字段将被添加到 GET 请求中
$response = $ipstack->get( "8.8.8.8", array( 'language' => "de", 'fields' => "ip,country_code,country_name,latitude,longitude,region_name" ));
缓存 ipstack 响应
如果您正在使用每月限制为 10,000 次请求的 ipstack 免费计划,您可能希望通过将查找结果保存到 PSR-6 缓存来节省请求。 IpstackClientPsr6CacheDecorator 也将实现 IpstackClientInterface,因此可以透明地替换 IpstackClient。
其构造函数接受您的 IpstackClient 实例和一个 PSR-6 CacheItemPool 实例。此示例使用来自 Stash 的缓存实现
<?php use Germania\IpstackClient\IpstackClientPsr6CacheDecorator; use Germania\IpstackClient\IpstackClient; use Stash\Pool as CacheItemPool; // Setup your client as shown above $ipstack = new IpstackClient( $endpoint, $api_key); // Example cache $cache = new \Stash\Pool( new \Stash\Driver\Sqlite( array('path' => "/tmp" )) ); // Setup the decorator $caching_ipstack = new IpstackClientPsr6CacheDecorator($ipstack, $cache); // Optional: Set lifetime in seconds (or null) $caching_ipstack->setCacheLifeTime( 3600 ); // Use as usual $response = $caching_ipstack->get( "8.8.8.8" );
中间件
IpstackMiddleware 可以用作 PSR-15 中间件以及传统的 Slim3-style “双遍历”中间件。它需要一个 IpstackClient 实例,并将携带 IpstackClient 的响应的 ipstack 属性注入到 Request 对象中。此示例显示了“双遍历”方法
<?php use Germania\IpstackClient\IpstackMiddleware; // Setup your client as shown above $ipstack = new IpstackClient( $endpoint, $api_key); // The middleware: $ipstack_middleware = new IpstackMiddleware( $ipstack ); // Setup Slim app $app = new \Slim\App; $app->add( $ipstack_middleware );
然后在您的控制器中,您只需从 Request 对象中获取 ipsatck 信息即可
$ipstack_attr = $request->getAttribute( "ipstack" ); echo $ipstack_attr['ip']; echo $ipstack_attr['country_code']; echo $ipstack_attr['country_name'];
关于 IP 地址的说明
默认情况下,用于 ipstack 请求的 IP 地址由 $_SERVER['REMOTE_ADDR']
确定。建议使用 Rob Allen(别称 akrabat)的 客户端 IP 地址中间件 来更安全地确定 IP 地址。
陷阱 1:Akrabats 中间件必须在 IpstackMiddleware 之前使用。它必须作为 Slim 应用程序中的第二个中间件添加。
陷阱 2:Akrabats 中间件允许自定义客户端 IP 地址的请求属性名称。根据文档
默认情况下,属性名称为 '
ip_address
'。可以通过第三个构造函数参数进行更改。
这意味着 IP 地址可能存储在自定义请求属性中。因此,IpstackMiddleware 必须知道此属性名称。
只需将 IP 地址属性名称作为第二个构造函数参数传递即可,无论是默认值还是自定义值。请记住,如果您省略此参数,则将使用 $_SERVER['REMOTE_ADDR']
作为后备。
<?php use RKA\Middleware\IpAddress as IpAddressMiddleware; use Germania\IpstackClient\IpstackMiddleware; // Setup Slim app $app = new \Slim\App; // Executed second $ipstack_middleware = new IpstackMiddleware( $ipstack, "ip_address" ); $app->add( $ipstack_middleware ); // Executed first $checkProxyHeaders = true; // Note: Never trust the IP address for security processes! $trustedProxies = ['10.0.0.1', '10.0.0.2']; // example $akrabats_middleware = new IpAddressMiddleware($checkProxyHeaders, $trustedProxies); $app->add( $akrabats_middleware );
异常
IpstackClient 在请求期间检查 Guzzle 异常 并评估 ipstack 错误响应。两者都将被抽象为 IpstackRequestException 或 IpstackResponseException,分别实现 IpstackExceptionInterface。
<?php use Germania\IpstackClient\IpstackExceptionInterface; use Germania\IpstackClient\IpstackRequestException; use Germania\IpstackClient\IpstackResponseException; try { $ipstack = new IpstackClient( $endpoint, $api_key); $response = $ipstack->get( $client_ip ); } catch( IpstackExceptionInterface $e ) { // a) IpstackResponseException // b) IpstackRequestException echo $e->getMessage(); echo $e->getCode(); // to get Guzzle's original exception: $original_guzzle_exception = $e->getPrevious(); }
开发
$ git clone https://github.com/GermaniaKG/ipstack.git
$ cd ipstack
$ composer install
单元测试
将 phpunit.xml.dist 复制到 phunit.xml,并调整与 ipstack 相关的全局变量。端点和 API 密钥是自解释的;虚拟的 IP4 和 IP6 是在测试运行期间需要检查的 IP 地址。这里使用的 IP 示例是 Google 的 DNS 服务器。
<php> <var name="IPSTACK_ENDPOINT" value="http://api.ipstack.com/" /> <var name="IPSTACK_APIKEY" value="your_api_key" /> <var name="IPSTACK_DUMMY_IP4" value="8.8.4.4" /> <var name="IPSTACK_DUMMY_IP6" value="2001:4860:4860::8888" /> </php>
使用供应商二进制文件或 composer 的 test 脚本运行 phpunit
$ vendor/bin/phpunit # or $ composer test