+
+
+
+
+
1: <?php
+ 2:
+ 3: namespace GeoIp2\WebService;
+ 4:
+ 5: use GeoIp2\Exception\AddressNotFoundException;
+ 6: use GeoIp2\Exception\AuthenticationException;
+ 7: use GeoIp2\Exception\GeoIp2Exception;
+ 8: use GeoIp2\Exception\HttpException;
+ 9: use GeoIp2\Exception\InvalidRequestException;
+ 10: use GeoIp2\Exception\OutOfQueriesException;
+ 11: use GeoIp2\ProviderInterface;
+ 12: use Guzzle\Common\Exception\RuntimeException;
+ 13: use Guzzle\Http\Client as GuzzleClient;
+ 14: use Guzzle\Http\Exception\ClientErrorResponseException;
+ 15: use Guzzle\Http\Exception\ServerErrorResponseException;
+ 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: class Client implements ProviderInterface
+ 49: {
+ 50: private $userId;
+ 51: private $licenseKey;
+ 52: private $locales;
+ 53: private $host;
+ 54: private $guzzleClient;
+ 55:
+ 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66:
+ 67: public function __construct(
+ 68: $userId,
+ 69: $licenseKey,
+ 70: $locales = array('en'),
+ 71: $host = 'geoip.maxmind.com',
+ 72: $guzzleClient = null
+ 73: ) {
+ 74: $this->userId = $userId;
+ 75: $this->licenseKey = $licenseKey;
+ 76: $this->locales = $locales;
+ 77: $this->host = $host;
+ 78:
+ 79: $this->guzzleClient = $guzzleClient;
+ 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: public function city($ipAddress = 'me')
+110: {
+111: return $this->responseFor('city', 'City', $ipAddress);
+112: }
+113:
+114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140:
+141: public function country($ipAddress = 'me')
+142: {
+143: return $this->responseFor('country', 'Country', $ipAddress);
+144: }
+145:
+146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172:
+173: public function cityIspOrg($ipAddress = 'me')
+174: {
+175: return $this->responseFor('city_isp_org', 'CityIspOrg', $ipAddress);
+176: }
+177:
+178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204:
+205: public function omni($ipAddress = 'me')
+206: {
+207: return $this->responseFor('omni', 'Omni', $ipAddress);
+208: }
+209:
+210: private function responseFor($endpoint, $class, $ipAddress)
+211: {
+212: $uri = implode('/', array($this->baseUri(), $endpoint, $ipAddress));
+213:
+214: $client = $this->guzzleClient ?
+215: $this->guzzleClient : new GuzzleClient();
+216: $request = $client->get($uri, array('Accept' => 'application/json'));
+217: $request->setAuth($this->userId, $this->licenseKey);
+218: $this->setUserAgent($request);
+219:
+220: try {
+221: $response = $request->send();
+222: } catch (ClientErrorResponseException $e) {
+223: $this->handle4xx($e->getResponse(), $uri);
+224: } catch (ServerErrorResponseException $e) {
+225: $this->handle5xx($e->getResponse(), $uri);
+226: }
+227:
+228: if ($response && $response->isSuccessful()) {
+229: $body = $this->handleSuccess($response, $uri);
+230: $class = "GeoIp2\\Model\\" . $class;
+231: return new $class($body, $this->locales);
+232: } else {
+233: $this->handleNon200($response, $uri);
+234: }
+235: }
+236:
+237: private function handleSuccess($response, $uri)
+238: {
+239: if ($response->getContentLength() == 0) {
+240: throw new GeoIp2Exception(
+241: "Received a 200 response for $uri but did not " .
+242: "receive a HTTP body."
+243: );
+244: }
+245:
+246: try {
+247: return $response->json();
+248: } catch (RuntimeException $e) {
+249: throw new GeoIp2Exception(
+250: "Received a 200 response for $uri but could not decode " .
+251: "the response as JSON: " . $e->getMessage()
+252: );
+253:
+254: }
+255: }
+256:
+257: private function handle4xx($response, $uri)
+258: {
+259: $status = $response->getStatusCode();
+260:
+261: if ($response->getContentLength() > 0) {
+262: if (strstr($response->getContentType(), 'json')) {
+263: try {
+264: $body = $response->json();
+265: if (!isset($body['code']) || !isset($body['error'])) {
+266: throw new GeoIp2Exception(
+267: 'Response contains JSON but it does not specify ' .
+268: 'code or error keys: ' . $response->getBody()
+269: );
+270: }
+271: } catch (RuntimeException $e) {
+272: throw new HttpException(
+273: "Received a $status error for $uri but it did not " .
+274: "include the expected JSON body: " .
+275: $e->getMessage(),
+276: $status,
+277: $uri
+278: );
+279: }
+280: } else {
+281: throw new HttpException(
+282: "Received a $status error for $uri with the " .
+283: "following body: " . $response->getBody(),
+284: $status,
+285: $uri
+286: );
+287: }
+288: } else {
+289: throw new HttpException(
+290: "Received a $status error for $uri with no body",
+291: $status,
+292: $uri
+293: );
+294: }
+295: $this->handleWebServiceError(
+296: $body['error'],
+297: $body['code'],
+298: $status,
+299: $uri
+300: );
+301: }
+302:
+303: private function handleWebServiceError($message, $code, $status, $uri)
+304: {
+305: switch ($code) {
+306: case 'IP_ADDRESS_NOT_FOUND':
+307: case 'IP_ADDRESS_RESERVED':
+308: throw new AddressNotFoundException($message);
+309: case 'AUTHORIZATION_INVALID':
+310: case 'LICENSE_KEY_REQUIRED':
+311: case 'USER_ID_REQUIRED':
+312: throw new AuthenticationException($message);
+313: case 'OUT_OF_QUERIES':
+314: throw new OutOfQueriesException($message);
+315: default:
+316: throw new InvalidRequestException(
+317: $message,
+318: $code,
+319: $status,
+320: $uri
+321: );
+322: }
+323: }
+324:
+325: private function handle5xx($response, $uri)
+326: {
+327: $status = $response->getStatusCode();
+328:
+329: throw new HttpException(
+330: "Received a server error ($status) for $uri",
+331: $status,
+332: $uri
+333: );
+334: }
+335:
+336: private function handleNon200($response, $uri)
+337: {
+338: $status = $response->getStatusCode();
+339:
+340: throw new HttpException(
+341: "Received a very surprising HTTP status " .
+342: "($status) for $uri",
+343: $status,
+344: $uri
+345: );
+346: }
+347:
+348: private function setUserAgent($request)
+349: {
+350: $userAgent = $request->getHeader('User-Agent');
+351: $userAgent = "GeoIP2 PHP API ($userAgent)";
+352: $request->setHeader('User-Agent', $userAgent);
+353: }
+354:
+355: private function baseUri()
+356: {
+357: return 'https://' . $this->host . '/geoip/v2.0';
+358: }
+359: }
+360:
+
+
+