Skip to content

Commit 8005c31

Browse files
committed
Explicitly check Content-Type before decoding json
1 parent 8c5fdbc commit 8005c31

File tree

2 files changed

+48
-12
lines changed

2 files changed

+48
-12
lines changed

geoip2/webservices.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ def _handle_error(self, response, uri):
237237
self._handle_non_200_status(status, uri)
238238

239239
def _handle_4xx_status(self, response, status, uri):
240-
if response.content:
240+
if response.content and \
241+
response.headers['Content-Type'].find('json') >= 0:
241242
try:
242243
body = response.json()
243244
except ValueError as ex:
@@ -254,6 +255,11 @@ def _handle_4xx_status(self, response, status, uri):
254255
raise HTTPError(
255256
'Response contains JSON but it does not specify '
256257
'code or error keys', status, uri)
258+
elif response.content:
259+
raise GeoIP2HTTPError('Received a %i for %s with the following '
260+
'body: %s' %
261+
(status, uri, response.content),
262+
status, uri)
257263
else:
258264
raise HTTPError('Received a %(status)i error for %(uri)s '
259265
'with no body.' % locals(), status, uri)

tests/webservices_test.py

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,16 @@ def setUp(self):
4848
'traits': {'ip_address': '1.2.3.4',},
4949
}
5050

51+
def _content_type(self, endpoint):
52+
return ('application/vnd.maxmind.com-' +
53+
endpoint + '+json; charset=UTF-8; version=1.0')
54+
5155
def test_country_ok(self):
5256
httpretty.register_uri(httpretty.GET,
5357
self.base_uri + 'country/1.2.3.4',
5458
body = json.dumps(self.country),
55-
status = 200)
59+
status = 200,
60+
content_type = self._content_type('country'))
5661
country = self.client.country('1.2.3.4')
5762
self.assertEqual(type(country), geoip2.models.Country,
5863
'return value of client.country')
@@ -77,7 +82,8 @@ def test_me(self):
7782
httpretty.register_uri(httpretty.GET,
7883
self.base_uri + 'country/me',
7984
body = json.dumps(self.country),
80-
status = 200)
85+
status = 200,
86+
content_type = self._content_type('country'))
8187
implicit_me = self.client.country()
8288
self.assertEqual(type(implicit_me), geoip2.models.Country,
8389
'country() returns Country object')
@@ -88,7 +94,8 @@ def test_me(self):
8894
def test_200_error(self):
8995
httpretty.register_uri(httpretty.GET,
9096
self.base_uri + 'country/1.1.1.1',
91-
status = 200)
97+
status = 200,
98+
content_type = self._content_type('country'))
9299
with self.assertRaisesRegex(GeoIP2Error,
93100
'could not decode the response as JSON'):
94101
self.client.country('1.1.1.1')
@@ -100,7 +107,8 @@ def test_400_error(self):
100107
httpretty.register_uri(httpretty.GET,
101108
self.base_uri + 'country/1.2.3',
102109
body = json.dumps(body),
103-
status = 400)
110+
status = 400,
111+
content_type = self._content_type('country'))
104112
with self.assertRaisesRegex(WebServiceError,
105113
'The value "1.2.3" is not a valid '
106114
'ip address'):
@@ -121,6 +129,9 @@ def test_no_body_error(self):
121129
self.base_uri + 'country/' + '1.2.3.7',
122130
body ='',
123131
status=400)
132+
with self.assertRaisesRegex(HTTPError,
133+
status=400,
134+
content_type = self._content_type('country'))
124135
with self.assertRaisesRegex(HTTPError,
125136
'Received a 400 error for .* with no body'):
126137
self.client.country('1.2.3.7')
@@ -129,7 +140,8 @@ def test_weird_body_error(self):
129140
httpretty.register_uri(httpretty.GET,
130141
self.base_uri + 'country/' + '1.2.3.8',
131142
body='{"wierd": 42}',
132-
status=400)
143+
status=400,
144+
content_type = self._content_type('country'))
133145
with self.assertRaisesRegex(HTTPError,
134146
'Response contains JSON but it does not '
135147
'specify code or error keys'):
@@ -140,12 +152,25 @@ def test_bad_body_error(self):
140152
httpretty.register_uri(httpretty.GET,
141153
self.base_uri + 'country/' + '1.2.3.9',
142154
body='bad body',
143-
status=400)
155+
status=400,
156+
content_type = self._content_type('country'))
144157
with self.assertRaisesRegex(HTTPError,
145158
'it did not include the expected JSON body'
146159
):
147160
self.client.country('1.2.3.9')
148161

162+
@httpretty.activate
163+
def test_bad_body_error(self):
164+
httpretty.register_uri(httpretty.GET,
165+
self.base_uri + 'country/' + '1.2.3.9',
166+
body='bad body',
167+
status=400,
168+
content_type = 'text/plain')
169+
with self.assertRaisesRegex(GeoIP2HTTPError,
170+
'Received a .* with the following body'
171+
):
172+
self.client.country('1.2.3.9')
173+
149174
def test_500_error(self):
150175
httpretty.register_uri(httpretty.GET,
151176
self.base_uri + 'country/' + '1.2.3.10',
@@ -157,7 +182,8 @@ def test_500_error(self):
157182
def test_300_error(self):
158183
httpretty.register_uri(httpretty.GET,
159184
self.base_uri + 'country/' + '1.2.3.11',
160-
status=300)
185+
status=300,
186+
content_type = self._content_type('country'))
161187
with self.assertRaisesRegex(HTTPError,
162188
'Received a very surprising HTTP status '
163189
'\(300\) for'):
@@ -168,7 +194,8 @@ def test_request(self):
168194
httpretty.register_uri(httpretty.GET,
169195
self.base_uri + 'country/' + '1.2.3.4',
170196
body = json.dumps(self.country),
171-
status = 200)
197+
status = 200,
198+
content_type = self._content_type('country'))
172199
country = self.client.country('1.2.3.4')
173200
request = httpretty.core.httpretty.latest_requests[-1]
174201

@@ -188,7 +215,8 @@ def test_city_ok(self):
188215
httpretty.register_uri(httpretty.GET,
189216
self.base_uri + 'city/' + '1.2.3.4',
190217
body = json.dumps(self.country),
191-
status = 200)
218+
status = 200,
219+
content_type = self._content_type('city'))
192220
city = self.client.city('1.2.3.4')
193221
self.assertEqual(type(city), geoip2.models.City,
194222
'return value of client.city')
@@ -197,7 +225,8 @@ def test_city_isp_org_ok(self):
197225
httpretty.register_uri(httpretty.GET,
198226
self.base_uri + 'city_isp_org/1.2.3.4',
199227
body = json.dumps(self.country),
200-
status = 200)
228+
status = 200,
229+
content_type = self._content_type('country'))
201230
city_isp_org = self.client.city_isp_org('1.2.3.4')
202231
self.assertEqual(type(city_isp_org), geoip2.models.CityISPOrg,
203232
'return value of client.city_isp_org')
@@ -206,7 +235,8 @@ def test_omni_ok(self):
206235
httpretty.register_uri(httpretty.GET,
207236
self.base_uri + 'omni/1.2.3.4',
208237
body = json.dumps(self.country),
209-
status = 200)
238+
status = 200,
239+
content_type = self._content_type('country'))
210240
omni = self.client.omni('1.2.3.4')
211241
self.assertEqual(type(omni), geoip2.models.Omni,
212242
'return value of client.omni')

0 commit comments

Comments
 (0)