Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds a new IP geocoding provider,
Geocoder\Provider\IPGeolocation\IPGeolocation, for the IPGeolocation.io API. It will be published asgeocoder-php/ipgeolocation-provider.It is modeled on the existing
IpstackandIpInfoproviders:AbstractHttpProviderand implementsProvider;No existing code changes. The only edits outside the new folder are list entries: the README table, the CI matrix, the subtree split and the phpunit placeholder.
Files changed
New provider folder,
src/Provider/IPGeolocation/(same layout as the other providers):IPGeolocation.phpTests/IPGeolocationTest.phpTests/IntegrationTest.phpProviderIntegrationTestsubclass (address and reverse disabled)Tests/.cached_responses/composer.jsongeocoder-php/ipgeolocation-provider; requiresphp ^8.0,geocoder-php/common-http ^4.0,willdurand/geocoder ^4.0|^5.0Readme.md,CHANGELOG.md,LICENSEphpunit.xml.dist,.gitattributes,.gitignore,.github/workflows/provider.ymlIpstackwith the env key renamedEdits in the monorepo root:
README.md.github/workflows/provider.ymlIPGeolocationadded to the provider matrix.github/workflows/subtree.yml{ folder: IPGeolocation, repository: ipgeolocation-provider }addedphpunit.xml.distIPGEOLOCATION_API_KEYplaceholder addedUsage
A free API key is available at https://app.ipgeolocation.io/login.
How the provider calls the API
Each geocode query sends one GET request:
fields: limits the response to the two objects the provider maps. It keeps the payload small and doesn't change the price: the base lookup costs 1 credit either way. It is available on every plan.lang: sent only when the query has a locale (GeocodeQuery::withLocale()). English works on every plan; other languages need a paid plan, and on a free plan the API rejects them with HTTP 401.http_build_query(), so IPv6 addresses are encoded correctly.include=security,abuseand so on), so it works the same on free and paid keys.Behaviour
InvalidCredentials('No API key provided.')UnsupportedOperation127.0.0.1or::1AddressfromgetLocationForLocalhost(), no request sent (same as other IP providers)reverseQuery()UnsupportedOperationlocationobjectAddress(see mapping below)locationobject10.0.0.1or2001:db8::/32InvalidCredentialsQuotaExceededInvalidServerResponseInvalidServerResponseWhy the provider checks the HTTP status itself. It sends the request through
getHttpClient()->sendRequest()instead ofgetUrlContents(), the same approachMapQuestuses.getUrlContents()throwsInvalidServerResponsefor every status ≥ 300, but for this API 404 and 423 mean "no result for this IP", not "server error". Returning an empty collection matches what other providers do when an IP has no location. The 401/403, 429 and other status handling is identical toAbstractHttpProvider::getParsedResponse().Field mapping
Addressfieldcoordinateslatitudelocation.latitude(cast to float)59.36888coordinateslongitudelocation.longitude(cast to float)18.00843localitylocation.citySolnapostalCodelocation.zipcode169 03adminLevels[1]namelocation.state_provStockholm CountyadminLevels[1]codelocation.state_codeSE-ABadminLevels[2]namelocation.districtStockholmcountrynamelocation.country_nameSwedencountrycodelocation.country_code2SEtimezonetime_zone.nameEurope/StockholmprovidedByipgeolocationipgeolocationNotes on the mapping:
SE-AB,US-CA).null. The API returns""for fields that have no value, so the provider converts them. Admin levels are only added when they have a name.streetName,streetNumber,subLocalityandboundsare not set: the API has no matching field.Tests
Unit tests (
Tests/IPGeolocationTest.php, 13 tests, no network). They cover:getName();fieldsandlang;null;InvalidCredentials;QuotaExceeded;reverseQuery()rejected.The mocked response bodies are taken from the free-plan example in the IPGeolocation.io API reference.
Integration test (
Tests/IntegrationTest.php). It sets$testAddress = falseand$testReverse = false, likeIpstack. The two cached responses were recorded from the live API with a free-plan key, and neither contains the key:83.227.123.8: a full Swedish location (the mapping table above uses it).2001:0db8:0000:0042:0000:8a2e:0370:7334: the API's bogon response ("'2001:db8:0:42:0:8a2e:370:7334' is a bogon IP address."), which becomes an empty collection.Results:
vendor/bin/phpunit src/Provider/IPGeolocation/Tests: 29 tests OK, 4 skipped (the address and reverse integration tests, which are disabled for IP providers).vendor/bin/phpstan analyse src/Provider/IPGeolocation: no errors.vendor/bin/php-cs-fixer fix --dry-run src/Provider/IPGeolocation: no changes.Note for maintainers
After merge, the subtree split targets
geocoder-php/ipgeolocation-provider, so that repository and its Packagist package need to be created before the first release. The provider'sCHANGELOG.mdstarts at1.0.0. I'm happy to change the package name or the version if you prefer something else.Disclosure
I work at IPGeolocation.io. We will maintain this provider, keep it in step with the API, and respond to issues about it.