Skip to content

Commit 9626bde

Browse files
authored
Merge pull request #66 from maxmind/greg/v2.1.0
Prepare for v2.1.0
2 parents 9ebf68f + 21f61e9 commit 9626bde

File tree

8 files changed

+50
-7
lines changed

8 files changed

+50
-7
lines changed

HISTORY.rst

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

6+
2.1.0 (2020-09-25)
7+
++++++++++++++++++
8+
9+
* Added ``response.ip_address.traits.is_residential_proxy`` to the
10+
minFraud Insights and Factors models. This indicates whether the IP
11+
address is on a suspected anonymizing network and belongs to a
12+
residential ISP.
13+
* ``HTTPError`` now provides the decoded response content in the
14+
``decoded_content`` attribute.
15+
616
2.0.3 (2020-07-28)
717
++++++++++++++++++
818

minfraud/errors.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,29 @@ class HTTPError(MinFraudError):
3939
4040
:type: str
4141
42+
.. attribute:: decoded_content:
43+
44+
The decoded response content
45+
46+
:type: str
47+
4248
"""
4349

50+
http_status: Optional[int]
51+
uri: Optional[str]
52+
decoded_content: Optional[str]
53+
4454
def __init__(
45-
self, message: str, http_status: Optional[int] = None, uri: Optional[str] = None
55+
self,
56+
message: str,
57+
http_status: Optional[int] = None,
58+
uri: Optional[str] = None,
59+
decoded_content: Optional[str] = None,
4660
) -> None:
4761
super().__init__(message)
4862
self.http_status = http_status
4963
self.uri = uri
64+
self.decoded_content = decoded_content
5065

5166

5267
class InvalidRequestError(MinFraudError):

minfraud/webservice.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ def _exception_for_error(
136136
if 400 <= status < 500:
137137
return self._exception_for_4xx_status(status, content_type, body, uri)
138138
if 500 <= status < 600:
139-
return self._exception_for_5xx_status(status, uri)
140-
return self._exception_for_unexpected_status(status, uri)
139+
return self._exception_for_5xx_status(status, body, uri)
140+
return self._exception_for_unexpected_status(status, body, uri)
141141

142142
def _exception_for_4xx_status(
143143
self, status: int, content_type: str, body: str, uri: str
@@ -151,13 +151,14 @@ def _exception_for_4xx_status(
151151
"""Returns exception for error responses with 4xx status codes."""
152152
if not body:
153153
return HTTPError(
154-
"Received a {0} error with no body".format(status), status, uri
154+
"Received a {0} error with no body".format(status), status, uri, body
155155
)
156156
if content_type.find("json") == -1:
157157
return HTTPError(
158158
"Received a {0} with the following " "body: {1}".format(status, body),
159159
status,
160160
uri,
161+
body,
161162
)
162163
try:
163164
decoded_body = json.loads(body)
@@ -169,6 +170,7 @@ def _exception_for_4xx_status(
169170
),
170171
status,
171172
uri,
173+
body,
172174
)
173175
else:
174176
if "code" in decoded_body and "error" in decoded_body:
@@ -180,6 +182,7 @@ def _exception_for_4xx_status(
180182
" or error keys: {0}".format(body),
181183
status,
182184
uri,
185+
body,
183186
)
184187

185188
@staticmethod
@@ -207,21 +210,31 @@ def _exception_for_web_service_error(
207210
return InvalidRequestError(message, code, status, uri)
208211

209212
@staticmethod
210-
def _exception_for_5xx_status(status: int, uri: str) -> HTTPError:
213+
def _exception_for_5xx_status(
214+
status: int,
215+
body: Optional[str],
216+
uri: str,
217+
) -> HTTPError:
211218
"""Returns exception for error response with 5xx status codes."""
212219
return HTTPError(
213220
u"Received a server error ({0}) for " u"{1}".format(status, uri),
214221
status,
215222
uri,
223+
body,
216224
)
217225

218226
@staticmethod
219-
def _exception_for_unexpected_status(status: int, uri: str) -> HTTPError:
227+
def _exception_for_unexpected_status(
228+
status: int,
229+
body: Optional[str],
230+
uri: str,
231+
) -> HTTPError:
220232
"""Returns exception for responses with unexpected status codes."""
221233
return HTTPError(
222234
u"Received an unexpected HTTP status " u"({0}) for {1}".format(status, uri),
223235
status,
224236
uri,
237+
body,
225238
)
226239

227240

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
requirements = [
2020
"aiohttp>=3.6.2,<4.0.0",
2121
"email_validator>=1.1.1,<2.0.0",
22-
"geoip2>=4.0.0,<5.0.0",
22+
"geoip2>=4.1.0,<5.0.0",
2323
"requests>=2.24.0,<3.0.0",
2424
"urllib3>=1.25.2,<2.0.0",
2525
"voluptuous",

tests/data/factors-response.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"is_anonymous_vpn": true,
9595
"is_hosting_provider": true,
9696
"is_public_proxy": true,
97+
"is_residential_proxy": true,
9798
"is_satellite_provider": true,
9899
"is_tor_exit_node": true,
99100
"isp": "Andrews & Arnold Ltd",

tests/data/insights-response.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"is_anonymous_vpn": true,
9595
"is_hosting_provider": true,
9696
"is_public_proxy": true,
97+
"is_residential_proxy": true,
9798
"is_satellite_provider": true,
9899
"is_tor_exit_node": true,
99100
"isp": "Andrews & Arnold Ltd",

tests/test_models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ def test_ip_address(self):
160160
"is_anonymous_vpn": True,
161161
"is_hosting_provider": True,
162162
"is_public_proxy": True,
163+
"is_residential_proxy": True,
163164
"is_satellite_provider": True,
164165
"is_tor_exit_node": True,
165166
},
@@ -175,6 +176,7 @@ def test_ip_address(self):
175176
self.assertEqual(True, address.traits.is_anonymous_vpn)
176177
self.assertEqual(True, address.traits.is_hosting_provider)
177178
self.assertEqual(True, address.traits.is_public_proxy)
179+
self.assertEqual(True, address.traits.is_residential_proxy)
178180
self.assertEqual(True, address.traits.is_satellite_provider)
179181
self.assertEqual(True, address.traits.is_tor_exit_node)
180182
self.assertEqual(True, address.country.is_high_risk)

tests/test_webservice.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ def test_200(self):
195195
self.assertEqual(self.cls(response), model)
196196
if self.has_ip_location():
197197
self.assertEqual("United Kingdom", model.ip_address.country.name)
198+
self.assertEqual(True, model.ip_address.traits.is_residential_proxy)
198199

199200
@httprettified
200201
def test_200_on_request_with_nones(self):

0 commit comments

Comments
 (0)