Skip to content

Commit 34fe3a1

Browse files
authored
Merge pull request #102 from maxmind/greg/proxy
Allow setting a proxy
2 parents 105c8aa + 37cb32a commit 34fe3a1

File tree

4 files changed

+51
-24
lines changed

4 files changed

+51
-24
lines changed

HISTORY.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
History
44
-------
55

6+
4.2.0
7+
++++++++++++++++++
8+
9+
* You may now set a proxy to use when making web service request by passing
10+
the ``proxy`` parameter to the ``AsyncClient`` or ``Client`` constructor.
11+
612
4.1.0 (2020-09-25)
713
++++++++++++++++++
814

README.rst

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -104,45 +104,50 @@ Async Web Service Example
104104

105105
.. code-block:: pycon
106106
107+
>>> import asyncio
108+
>>>
107109
>>> import geoip2.webservice
108110
>>>
109-
>>> # This creates an AsyncClient object that can be reused across
110-
>>> # requests on the running event loop. If you are using multiple event
111-
>>> # loops, you must ensure the object is not used on another loop.
112-
>>> #
113-
>>> # Replace "42" with your account ID and "license_key" with your license
114-
>>> # key.
115-
>>> async with geoip2.webservice.AsyncClient(42, 'license_key') as client:
111+
>>> async def main():
112+
>>> # This creates an AsyncClient object that can be reused across
113+
>>> # requests on the running event loop. If you are using multiple event
114+
>>> # loops, you must ensure the object is not used on another loop.
115+
>>> #
116+
>>> # Replace "42" with your account ID and "license_key" with your license
117+
>>> # key.
118+
>>> async with geoip2.webservice.AsyncClient(42, 'license_key') as client:
116119
>>>
117-
>>> # Replace "insights" with the method corresponding to the web service
118-
>>> # that you are using, e.g., "country", "city".
119-
>>> response = await client.insights('203.0.113.0')
120+
>>> # Replace "insights" with the method corresponding to the web service
121+
>>> # that you are using, e.g., "country", "city".
122+
>>> response = await client.insights('203.0.113.0')
120123
>>>
121-
>>> response.country.iso_code
124+
>>> response.country.iso_code
122125
'US'
123-
>>> response.country.name
126+
>>> response.country.name
124127
'United States'
125-
>>> response.country.names['zh-CN']
128+
>>> response.country.names['zh-CN']
126129
u'美国'
127130
>>>
128-
>>> response.subdivisions.most_specific.name
131+
>>> response.subdivisions.most_specific.name
129132
'Minnesota'
130-
>>> response.subdivisions.most_specific.iso_code
133+
>>> response.subdivisions.most_specific.iso_code
131134
'MN'
132135
>>>
133-
>>> response.city.name
136+
>>> response.city.name
134137
'Minneapolis'
135138
>>>
136-
>>> response.postal.code
139+
>>> response.postal.code
137140
'55455'
138141
>>>
139-
>>> response.location.latitude
142+
>>> response.location.latitude
140143
44.9733
141-
>>> response.location.longitude
144+
>>> response.location.longitude
142145
-93.2323
143146
>>>
144-
>>> response.traits.network
147+
>>> response.traits.network
145148
IPv4Network('203.0.113.0/32')
149+
>>>
150+
>>> asyncio.run(main())
146151
147152
Web Service Client Exceptions
148153
-----------------------------

geoip2/webservice.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
import ipaddress
2929
import json
30-
from typing import Any, cast, List, Optional, Type, Union
30+
from typing import Any, Dict, cast, List, Optional, Type, Union
3131

3232
import aiohttp
3333
import aiohttp.http
@@ -248,10 +248,14 @@ class AsyncClient(BaseClient):
248248
:param timeout: The timeout in seconts to use when waiting on the request.
249249
This sets both the connect timeout and the read timeout. The default is
250250
60.
251+
:param proxy: The URL of an HTTP proxy to use. It may optionally include
252+
a basic auth username and password, e.g.,
253+
``http://username:password@host:port``.
251254
252255
"""
253256

254257
_existing_session: aiohttp.ClientSession
258+
_proxy: Optional[str]
255259

256260
def __init__( # pylint: disable=too-many-arguments
257261
self,
@@ -260,6 +264,7 @@ def __init__( # pylint: disable=too-many-arguments
260264
host: str = "geoip.maxmind.com",
261265
locales: Optional[List[str]] = None,
262266
timeout: float = 60,
267+
proxy: Optional[str] = None,
263268
) -> None:
264269
super().__init__(
265270
account_id,
@@ -268,6 +273,7 @@ def __init__( # pylint: disable=too-many-arguments
268273
locales,
269274
timeout,
270275
)
276+
self._proxy = proxy
271277

272278
async def city(self, ip_address: IPAddress = "me") -> City:
273279
"""Call GeoIP2 Precision City endpoint with the specified IP.
@@ -331,7 +337,7 @@ async def _response_for(
331337
) -> Union[Country, City, Insights]:
332338
uri = self._uri(path, ip_address)
333339
session = await self._session()
334-
async with await session.get(uri) as response:
340+
async with await session.get(uri, proxy=self._proxy) as response:
335341
status = response.status
336342
content_type = response.content_type
337343
body = await response.text()
@@ -398,10 +404,15 @@ class Client(BaseClient):
398404
:param timeout: The timeout in seconts to use when waiting on the request.
399405
This sets both the connect timeout and the read timeout. The default is
400406
60.
407+
:param proxy: The URL of an HTTP proxy to use. It may optionally include
408+
a basic auth username and password, e.g.,
409+
``http://username:password@host:port``.
410+
401411
402412
"""
403413

404414
_session: requests.Session
415+
_proxies: Optional[Dict[str, str]]
405416

406417
def __init__( # pylint: disable=too-many-arguments
407418
self,
@@ -410,12 +421,17 @@ def __init__( # pylint: disable=too-many-arguments
410421
host: str = "geoip.maxmind.com",
411422
locales: Optional[List[str]] = None,
412423
timeout: float = 60,
424+
proxy: Optional[str] = None,
413425
) -> None:
414426
super().__init__(account_id, license_key, host, locales, timeout)
415427
self._session = requests.Session()
416428
self._session.auth = (self._account_id, self._license_key)
417429
self._session.headers["Accept"] = "application/json"
418430
self._session.headers["User-Agent"] = _REQUEST_UA
431+
if proxy is None:
432+
self._proxies = None
433+
else:
434+
self._proxies = {"https": proxy}
419435

420436
def city(self, ip_address: IPAddress = "me") -> City:
421437
"""Call GeoIP2 Precision City endpoint with the specified IP.
@@ -464,7 +480,7 @@ def _response_for(
464480
ip_address: IPAddress,
465481
) -> Union[Country, City, Insights]:
466482
uri = self._uri(path, ip_address)
467-
response = self._session.get(uri, timeout=self._timeout)
483+
response = self._session.get(uri, proxies=self._proxies, timeout=self._timeout)
468484
status = response.status_code
469485
content_type = response.headers["Content-Type"]
470486
body = response.text

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ max-line-length = 88
99
universal = 1
1010

1111
[tox:tox]
12-
envlist = py36, py37, py38, mypy
12+
envlist = py36, py37, py38, py39, mypy
1313

1414
[gh-actions]
1515
python =

0 commit comments

Comments
 (0)