Skip to content
This repository was archived by the owner on Nov 22, 2024. It is now read-only.

Commit 680d5b9

Browse files
committed
added dns_records/export API endpoint hence added code to handle non-JSON responses. added some initial http error code processing
1 parent 77a69b7 commit 680d5b9

2 files changed

Lines changed: 96 additions & 7 deletions

File tree

CloudFlare/api_v4.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ def zones(self):
108108
setattr(branch, "subscriptions",
109109
self._add_with_auth(base, "zones", "subscriptions"))
110110
branch = getattr(getattr(self, "zones"), "dns_records")
111+
setattr(branch, "export",
112+
self._add_with_auth(base, "zones", "dns_records/export"))
111113
setattr(branch, "import",
112114
self._add_with_auth(base, "zones", "dns_records/import"))
113115

CloudFlare/cloudflare.py

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ def call_with_certauth(self, method,
8989
raise CloudFlareAPIError(0, 'no cert token defined')
9090
headers = {
9191
'User-Agent': self.user_agent,
92-
'X-Auth-User-Service-Key': self.certtoken,
93-
'Content-Type': 'application/json'
92+
'X-Auth-User-Service-Key': self.certtoken,
93+
'Content-Type': 'application/json'
9494
}
9595
return self._call(method, headers,
9696
api_call_part1, api_call_part2, api_call_part3,
@@ -180,14 +180,101 @@ def _raw(self, method, headers,
180180
if self.logger:
181181
self.logger.debug('Response: url %s', response.url)
182182

183+
# Create response_{type|code|data}
184+
try:
185+
response_type = response.headers['Content-Type']
186+
if ';' in response_type:
187+
# remove the ;paramaters part (like charset=, etc.)
188+
response_type = response_type[0:response_type.rfind(';')]
189+
response_type = response_type.strip().lower()
190+
except:
191+
# API should always response; but if it doesn't; here's the default
192+
response_type = 'application/octet-stream'
193+
response_code = response.status_code
183194
response_data = response.text
195+
184196
if self.logger:
185-
self.logger.debug('Response: data %s' % response_data)
186-
try:
187-
response_data = json.loads(response_data)
188-
except ValueError:
189-
raise CloudFlareAPIError(0, 'JSON parse failed.')
197+
self.logger.debug('Response: %d, %s %s' % (response_code, response_type, response_data))
198+
199+
if response_code >= 500 and response_code <= 599:
200+
# 500 Internal Server Error
201+
# 501 Not Implemented
202+
# 502 Bad Gateway
203+
# 503 Service Unavailable
204+
# 504 Gateway Timeout
205+
# 505 HTTP Version Not Supported
206+
# 506 Variant Also Negotiates
207+
# 507 Insufficient Storage
208+
# 508 Loop Detected
209+
# 509 Unassigned
210+
# 510 Not Extended
211+
# 511 Network Authentication Required
212+
213+
# the libary doesn't deal with these errors, just pass upwards!
214+
# there's no value to add and the returned data is questionable or not useful
215+
response.raise_for_status()
216+
217+
# should not be reached
218+
raise CloudFlareInternalError(0, 'internal error in status code processing')
219+
220+
#if response_code >= 400 and response_code <= 499:
221+
# # 400 Bad Request
222+
# # 401 Unauthorized
223+
# # 403 Forbidden
224+
# # 405 Method Not Allowed
225+
# # 415 Unsupported Media Type
226+
# # 429 Too many requests
227+
#
228+
# # don't deal with these errors, just pass upwards!
229+
# response.raise_for_status()
230+
#
231+
#if response_code >= 300 and response_code <= 399:
232+
# # 304 Not Modified
233+
#
234+
# # don't deal with these errors, just pass upwards!
235+
# response.raise_for_status()
236+
#
237+
# should be a 200 response at this point
238+
239+
if response_type == 'application/json':
240+
# API says it's JSON; so it better be parsable as JSON
241+
try:
242+
response_data = json.loads(response_data)
243+
except ValueError:
244+
# While this should not happen; it's always possible
245+
raise CloudFlareAPIError(0, 'JSON parse failed - report to Cloudflare.')
246+
247+
if response_code == requests.codes.ok:
248+
# 200 ok - so nothing needs to be done
249+
pass
250+
else:
251+
# 3xx & 4xx errors - we should report that somehow - but not quite yet
252+
# response_data['code'] = response_code
253+
pass
254+
elif response_type == 'text/plain' or response_type == 'application/octet-stream':
255+
# API says it's text; but maybe it's actually JSON? - should be fixed in API
256+
try:
257+
response_data = json.loads(response_data)
258+
except ValueError:
259+
# So it wasn't JSON - moving on as if it's text!
260+
# A single value is returned (vs an array or object)
261+
if response_code == requests.codes.ok:
262+
# 200 ok
263+
response_data = {'success': True, 'result': str(response_data)}
264+
else:
265+
# 3xx & 4xx errors
266+
response_data = {'success': False, 'code': response_code, 'result': str(response_data)}
267+
else:
268+
# Assuming nothing - but continuing anyway
269+
# A single value is returned (vs an array or object)
270+
if response_code == requests.codes.ok:
271+
# 200 ok
272+
response_data = {'success': True, 'result': str(response_data)}
273+
else:
274+
# 3xx & 4xx errors
275+
response_data = {'success': False, 'code': response_code, 'result': str(response_data)}
190276

277+
# it would be nice to return the error code and content type values; but not quite yet
191278
return response_data
192279

193280
def _call(self, method, headers,

0 commit comments

Comments
 (0)