{"id":23058251,"url":"https://github.com/germaniakg/ipstack","last_synced_at":"2025-09-07T02:41:01.144Z","repository":{"id":38109389,"uuid":"173081116","full_name":"GermaniaKG/ipstack","owner":"GermaniaKG","description":"PHP client for the ipstack API with PSR-6 cache support and Slim3 middleware","archived":false,"fork":false,"pushed_at":"2023-04-19T19:24:57.000Z","size":148,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-19T02:59:53.134Z","etag":null,"topics":["cache","ip","ipstack","lookup","middleware","psr-6","slim3"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GermaniaKG.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-28T09:22:44.000Z","updated_at":"2022-03-30T09:23:43.000Z","dependencies_parsed_at":"2025-02-08T20:12:23.059Z","dependency_job_id":"acb630cc-0e7e-4f78-984a-3ccbf5746e5c","html_url":"https://github.com/GermaniaKG/ipstack","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/GermaniaKG/ipstack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2Fipstack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2Fipstack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2Fipstack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2Fipstack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GermaniaKG","download_url":"https://codeload.github.com/GermaniaKG/ipstack/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GermaniaKG%2Fipstack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273989153,"owners_count":25203214,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","ip","ipstack","lookup","middleware","psr-6","slim3"],"created_at":"2024-12-16T02:14:53.215Z","updated_at":"2025-09-07T02:41:01.112Z","avatar_url":"https://github.com/GermaniaKG.png","language":"PHP","readme":"# Germania KG · ipstack client\n\n**PHP client for the [ipstack API](https://ipstack.com/) with cache support and middleware**\n\n[![Packagist](https://img.shields.io/packagist/v/germania-kg/ipstack.svg?style=flat)](https://packagist.org/packages/germania-kg/ipstack)\n[![PHP version](https://img.shields.io/packagist/php-v/germania-kg/ipstack.svg)](https://packagist.org/packages/germania-kg/ipstack)\n[![Build Status](https://img.shields.io/travis/GermaniaKG/ipstack.svg?label=Travis%20CI)](https://travis-ci.org/GermaniaKG/ipstack)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/GermaniaKG/ipstack/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/GermaniaKG/ipstack/?branch=master)\n[![Code Coverage](https://scrutinizer-ci.com/g/GermaniaKG/ipstack/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/GermaniaKG/ipstack/?branch=master)\n[![Build Status](https://scrutinizer-ci.com/g/GermaniaKG/ipstack/badges/build.png?b=master)](https://scrutinizer-ci.com/g/GermaniaKG/ipstack/build-status/master)\n\n## Installation\n\n```bash\n$ composer require germania-kg/ipstack\n```\n\n\n\n## Using ipstack \n\n```php\n\u003c?php\nuse Germania\\IpstackClient\\IpstackClient;\n\n// Setup the Client\n$endpoint  = \"http://api.ipstack.com/\";\n$api_key   = \"your_api_key\";\n$ipstack   = new IpstackClient( $endpoint, $api_key);\n\n// Ask ipstack\n$client_ip = \"8.8.8.8\";\n$response  = $ipstack-\u003eget( $client_ip );\n```\n\n\n\n### Response example\n\nThe *IpstackClient* internally works with array and thus asks *ipstack* to return JSON. Here is a shortened example; For a full example see **ipstack's [documentation](https://ipstack.com/documentation#standard)** on Standard IP lookups: \n\n```\nArray ()\n  [ip] =\u003e 8.8.8.8\n  [type] =\u003e ipv4\n  [continent_code] =\u003e EU\n  [continent_name] =\u003e Europe\n  [country_code] =\u003e DE\n  [country_name] =\u003e Germany\n  [region_code] =\u003e SH\n  [region_name] =\u003e Schleswig-Holstein\n  [latitude] =\u003e 54.3667\n  [longitude] =\u003e 10.2\n  ...\n)\n```\n\n\n\n### Customizing the response\n\nYou can customize the ipstack response by adding certain fields to the underlying request, as explained in the ipstack docs on [“Specify Response Fields”](https://ipstack.com/documentation#fields). Just pass an array with query fields which will be added to the GET request:\n\n```php\n$response = $ipstack-\u003eget( \"8.8.8.8\", array(\n  'language' =\u003e \"de\",\n  'fields'   =\u003e \"ip,country_code,country_name,latitude,longitude,region_name\"\n));\n```\n\n\n\n## Caching the ipstack response\n\nIf you are using a ipstack [*free plan*](https://ipstack.com/plan) limited to with 10.000 requests a month, you may want to save requests by saving the lookup results to a PSR-6 Cache. The **IpstackClientPsr6CacheDecorator** implements the **IpstackClientInterface** as well and thus can transparently be used in place of the *IpstackClient*.\n\nIts constructor accepts your **IpstackClient** instance and a **PSR-6 CacheItemPool** instance. This example uses the cache implementation from [Stash](http://www.stashphp.com/):\n\n```php\n\u003c?php\nuse Germania\\IpstackClient\\IpstackClientPsr6CacheDecorator;\nuse Germania\\IpstackClient\\IpstackClient;\nuse Stash\\Pool as CacheItemPool;\n\n// Setup your client as shown above\n$ipstack = new IpstackClient( $endpoint, $api_key);\n\n// Example cache \n$cache   = new \\Stash\\Pool(\n  new \\Stash\\Driver\\Sqlite( array('path' =\u003e \"/tmp\" ))\n);\n\n// Setup the decorator\n$caching_ipstack = new IpstackClientPsr6CacheDecorator($ipstack, $cache);\n\n// Optional: Set lifetime in seconds (or null)\n$caching_ipstack-\u003esetCacheLifeTime( 3600 );\n\n// Use as usual\n$response = $caching_ipstack-\u003eget( \"8.8.8.8\" );\n```\n\n\n\n\n\n## Middleware\n\nThe **IpstackMiddleware** can be used as PSR-15 Middleware as well as a traditional Slim3-style “Double pass” middleware. It requires the *IpstackClient* instance and will inject a **ipstack** attribute to the *Request* object that carries the *IpstackClient's* response. This example shows the “Double pass” approach:\n\n```php\n\u003c?php\nuse Germania\\IpstackClient\\IpstackMiddleware;\n\n// Setup your client as shown above\n$ipstack = new IpstackClient( $endpoint, $api_key);\n\n// The middleware:\n$ipstack_middleware = new IpstackMiddleware( $ipstack );\n\n// Setup Slim app\n$app = new \\Slim\\App;\n$app-\u003eadd( $ipstack_middleware );\n\n```\n\nIn your Controller, you then simply grab the ipsatck information from the *Request* object:\n\n```php\n$ipstack_attr = $request-\u003egetAttribute( \"ipstack\" );\n\necho $ipstack_attr['ip'];\necho $ipstack_attr['country_code'];\necho $ipstack_attr['country_name'];\n```\n\n\n\n### A word on IP addresses\n\nThe IP address used for the ipstack request is per default determined from `$_SERVER['REMOTE_ADDR']`. It is recommended to use **Rob Allen** aka **akrabat's [Client IP address middleware](https://github.com/akrabat/ip-address-middleware)** that determines the IP address more safely.\n\n**Pitfall 1:** Akrabats middleware must be used BEFORE the *IpstackMiddleware*. It must be added *second* to the Slim app.\n\n**Pitfall 2:** Akrabats middleware allows customizing the request attribute name for the client IP address. From the docs:\n\n\u003e By default, the name of the attribute is '`ip_address`'. This can be changed by the third constructor parameter.\n\nThis means, the IP may be stored in a custom request attribute. The *IpstackMiddleware* therefore must know this attribute name. \n\nSimply pass the IP address attribute name as second constructor, be it default or custom. Remember, if you leave this parameter out,  `$_SERVER['REMOTE_ADDR']` will be used as fallback.\n\n```php\n\u003c?php\nuse RKA\\Middleware\\IpAddress as IpAddressMiddleware;\nuse Germania\\IpstackClient\\IpstackMiddleware;\n\n// Setup Slim app\n$app = new \\Slim\\App;\n\n// Executed second\n$ipstack_middleware = new IpstackMiddleware( $ipstack, \"ip_address\" );\n$app-\u003eadd( $ipstack_middleware );\n\n// Executed first\n$checkProxyHeaders = true; // Note: Never trust the IP address for security processes!\n$trustedProxies = ['10.0.0.1', '10.0.0.2']; // example\n$akrabats_middleware = new IpAddressMiddleware($checkProxyHeaders, $trustedProxies);\n$app-\u003eadd( $akrabats_middleware );\n```\n\n\n\n## Exceptions\n\nThe *IpstackClient* checks for *Guzzle Exceptions* during request and evaluate *ipstack error responses.* Both will be abstracted to **IpstackRequestException,** or **IpstackResponseException** respectively, both of them  implementing the **IpstackExceptionInterface.**\n\n```php\n\u003c?php\nuse Germania\\IpstackClient\\IpstackExceptionInterface;\nuse Germania\\IpstackClient\\IpstackRequestException;\nuse Germania\\IpstackClient\\IpstackResponseException;\n\ntry {\n  $ipstack = new IpstackClient( $endpoint, $api_key);\n  $response = $ipstack-\u003eget( $client_ip );\n}\ncatch( IpstackExceptionInterface $e ) {\n\n  // a) IpstackResponseException\n  // b) IpstackRequestException \n  echo $e-\u003egetMessage();\n  echo $e-\u003egetCode();  \n  \n  // to get Guzzle's original exception:\n  $original_guzzle_exception = $e-\u003egetPrevious();\n}\n```\n\n\n\n\n\n## Development\n\n```bash\n$ git clone https://github.com/GermaniaKG/ipstack.git\n$ cd ipstack\n$ composer install\n```\n\n\n\n## Unit testing\n\nCopy **phpunit.xml.dist** to **phunit.xml** and adapt the ipstack-related globals. Endpoint and API key are self-explaining; the dummy **IP4** and **IP6** are IP addresses to check during test runs. The IP examples used here are [Google's DNS servers](https://developers.google.com/speed/public-dns/).\n\n```xml\n\u003cphp\u003e\n  \u003cvar name=\"IPSTACK_ENDPOINT\"   value=\"http://api.ipstack.com/\" /\u003e\n  \u003cvar name=\"IPSTACK_APIKEY\"     value=\"your_api_key\" /\u003e\n  \u003cvar name=\"IPSTACK_DUMMY_IP4\"  value=\"8.8.4.4\" /\u003e\n  \u003cvar name=\"IPSTACK_DUMMY_IP6\"  value=\"2001:4860:4860::8888\" /\u003e\n\u003c/php\u003e\n```\n\n**Run phpunit** using vendor binary or composer *test* script:\n\n```bash\n$ vendor/bin/phpunit\n# or\n$ composer test\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgermaniakg%2Fipstack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgermaniakg%2Fipstack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgermaniakg%2Fipstack/lists"}