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

Commit e460d78

Browse files
committed
added openapi_url config - rarely used outside of development
1 parent 4383548 commit e460d78

2 files changed

Lines changed: 85 additions & 120 deletions

File tree

CloudFlare/cloudflare.py

Lines changed: 82 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,21 @@ def _call_network(self, method, headers, parts, identifiers, params, data_str, d
305305
else:
306306
self.logger.debug('Response: %d, %s, %s', response_code, response_type, '...')
307307

308+
if response_code == 500:
309+
# The /certificates API call insists on a 500 error return and yet has valid error data
310+
# lets check and convert if able
311+
try:
312+
j = json.loads(response_data)
313+
if 'status' not in j and 'errors' not in j:
314+
# no go - it's not a Cloudflare error format
315+
pass
316+
else:
317+
# yippe - try to continue by allowing to process fully
318+
response_code = 200
319+
except:
320+
# ignore - maybe a real 500!
321+
pass
322+
308323
if response_code >= 500 and response_code <= 599:
309324
# 500 Internal Server Error
310325
# 501 Not Implemented
@@ -336,13 +351,13 @@ def _call_network(self, method, headers, parts, identifiers, params, data_str, d
336351
#
337352
# # don't deal with these errors, just pass upwards!
338353
# response.raise_for_status()
339-
#
354+
340355
#if response_code >= 300 and response_code <= 399:
341356
# # 304 Not Modified
342357
#
343358
# # don't deal with these errors, just pass upwards!
344359
# response.raise_for_status()
345-
#
360+
346361
# should be a 200 response at this point
347362

348363
return [response_type, response_code, response_data]
@@ -355,143 +370,90 @@ def _raw(self, method, headers, parts, identifiers, params, data_str, data_json,
355370
identifiers,
356371
params, data_str, data_json, files)
357372

373+
if response_code != requests_codes.ok:
374+
# 3xx & 4xx errors (5xx's handled above)
375+
response_data = {'success': False,
376+
'errors': [{'code': response_code, 'message':'HTTP response code %d' % response_code}],
377+
'result': str(response_data)}
378+
379+
# it would be nice to return the error code and content type values; but not quite yet
380+
return response_data
381+
358382
if response_type == 'application/json':
359383
# API says it's JSON; so it better be parsable as JSON
360384
# NDJSON is returned by Enterprise Log Share i.e. /zones/:id/logs/received
361385
if hasattr(response_data, 'decode'):
362386
response_data = response_data.decode('utf-8')
363387
try:
364-
response_data = json.loads(response_data)
365-
if not isinstance(response_data, (dict)):
366-
response_data = {'success': True,
367-
'result': response_data}
368-
except ValueError:
369388
if response_data == '':
370389
# This should really be 'null' but it isn't. Even then, it's wrong!
371-
if response_code == requests_codes.ok:
372-
# 200 ok
373-
response_data = {'success': True,
374-
'result': None}
375-
else:
376-
# 3xx & 4xx errors
377-
response_data = {'success': False,
378-
'code': response_code,
379-
'result': None}
390+
response_data = None
380391
else:
381-
# Lets see if it's NDJSON data
382-
# NDJSON is a series of JSON elements with newlines between each element
383-
try:
384-
r = []
385-
for l in response_data.splitlines():
386-
r.append(json.loads(l))
387-
response_data = r
388-
except:
389-
# While this should not happen; it's always possible
390-
if self.logger:
391-
self.logger.debug('Response data not JSON: %r', response_data)
392-
raise CloudFlareAPIError(0, 'JSON parse failed - report to Cloudflare.')
392+
response_data = json.loads(response_data)
393+
except ValueError:
394+
# Lets see if it's NDJSON data
395+
# NDJSON is a series of JSON elements with newlines between each element
396+
try:
397+
r = []
398+
for l in response_data.splitlines():
399+
r.append(json.loads(l))
400+
response_data = r
401+
except:
402+
# While this should not happen; it's always possible
403+
if self.logger:
404+
self.logger.debug('Response data not JSON: %r', response_data)
405+
raise CloudFlareAPIError(0, 'JSON parse failed - report to Cloudflare.')
393406

394-
if response_code == requests_codes.ok:
395-
# 200 ok - so nothing needs to be done
396-
pass
397-
else:
398-
# 3xx & 4xx errors - we should report that somehow - but not quite yet
399-
# response_data['code'] = response_code
400-
pass
401-
elif response_type == 'application/octet-stream' and isinstance(response_data, (int, float)):
402-
# It's binary data
403-
if response_code == requests_codes.ok:
404-
# 200 ok
405-
response_data = {'success': True,
406-
'result': response_data}
407-
else:
408-
# 3xx & 4xx errors
409-
response_data = {'success': False,
410-
'code': response_code,
411-
'result': response_data}
412-
elif response_type == 'application/octet-stream' and isinstance(response_data, (bytes, bytearray)):
407+
if isinstance(response_data, dict) and 'success' in response_data:
408+
return response_data
409+
# if it's not a dict then it's not going to have 'success'
410+
return {'success': True, 'result': response_data}
411+
412+
if response_type in ['text/plain', 'text/csv', 'application/octet-stream']:
413413
# API says it's text; but maybe it's actually JSON? - should be fixed in API
414414
if hasattr(response_data, 'decode'):
415415
response_data = response_data.decode('utf-8')
416416
try:
417417
response_data = json.loads(response_data)
418-
if not isinstance(response_data, (dict)) or 'success' not in response_data:
419-
if response_code == requests_codes.ok:
420-
# 200 ok
421-
response_data = {'success': True,
422-
'result': response_data}
423-
else:
424-
# 3xx & 4xx errors
425-
response_data = {'success': False,
426-
'code': response_code,
427-
'result': response_data}
428418
except ValueError:
429419
# So it wasn't JSON - moving on as if it's text!
430-
# A single value is returned (vs an array or object)
431-
if response_code == requests_codes.ok:
432-
# 200 ok
433-
response_data = {'success': True, 'result': response_data}
434-
else:
435-
# 3xx & 4xx errors
436-
response_data = {'success': False,
437-
'code': response_code,
438-
'result': response_data}
439-
elif response_type in ['text/plain', 'text/csv', 'application/octet-stream']:
420+
pass
421+
if isinstance(response_data, dict) and 'success' in response_data:
422+
return response_data
423+
return {'success': True, 'result': response_data}
424+
425+
if response_type in ['text/javascript', 'application/javascript', 'text/html']:
426+
# used by Cloudflare workers
427+
if hasattr(response_data, 'decode'):
428+
response_data = response_data.decode('utf-8')
429+
return {'success': True, 'result': str(response_data)}
430+
431+
if response_type == 'application/octet-stream' and isinstance(response_data, (int, float)):
432+
# it's raw/binary - just pass thru
433+
return {'success': True, 'result': response_data}
434+
435+
if response_type == 'application/octet-stream' and isinstance(response_data, (bytes, bytearray)):
440436
# API says it's text; but maybe it's actually JSON? - should be fixed in API
441437
if hasattr(response_data, 'decode'):
442438
response_data = response_data.decode('utf-8')
443439
try:
444440
response_data = json.loads(response_data)
445-
if not isinstance(response_data, (dict)):
446-
response_data = {'success': True,
447-
'result': response_data}
448441
except ValueError:
449442
# So it wasn't JSON - moving on as if it's text!
450-
# A single value is returned (vs an array or object)
451-
if response_code == requests_codes.ok:
452-
# 200 ok
453-
response_data = {'success': True, 'result': response_data}
454-
else:
455-
# 3xx & 4xx errors
456-
response_data = {'success': False,
457-
'code': response_code,
458-
'result': response_data}
459-
elif response_type in ['text/javascript', 'application/javascript', 'text/html']:
460-
# used by Cloudflare workers
461-
if hasattr(response_data, 'decode'):
462-
response_data = response_data.decode('utf-8')
463-
if response_code == requests_codes.ok:
464-
# 200 ok
465-
response_data = {'success': True,
466-
'result': str(response_data)}
467-
else:
468-
# 3xx & 4xx errors
469-
response_data = {'success': False,
470-
'code': response_code,
471-
'result': str(response_data)}
472-
elif response_type[0:6] in ['audio/', 'image/', 'video/']:
473-
# raw - just pass thru
474-
if response_code == requests_codes.ok:
475-
response_data = {'success': True, 'result': response_data}
476-
else:
477-
response_data = {'success': False,
478-
'code': response_code,
479-
'result': response_data}
480-
else:
481-
# Assuming nothing - but continuing anyway
482-
# A single value is returned (vs an array or object)
483-
if response_code == requests_codes.ok:
484-
# 200 ok
485-
response_data = {'success': True,
486-
'result': str(response_data)}
487-
else:
488-
# 3xx & 4xx errors
489-
response_data = {'success': False,
490-
'code': response_code,
491-
'result': str(response_data)}
443+
pass
444+
445+
if isinstance(response_data, dict) and 'success' in response_data:
446+
return response_data
447+
return {'success': True, 'result': response_data}
492448

493-
# it would be nice to return the error code and content type values; but not quite yet
494-
return response_data
449+
if response_type[0:6] in ['audio/', 'image/', 'video/']:
450+
# it's raw/binary - just pass thru
451+
return {'success': True, 'result': response_data}
452+
453+
# Assuming nothing - but continuing anyway as if its a string
454+
if hasattr(response_data, 'decode'):
455+
response_data = response_data.decode('utf-8')
456+
return {'success': True, 'result': str(response_data)}
495457

496458
def _call(self, method, parts, identifiers, params, data_str, data_json, files):
497459
""" Cloudflare v4 API"""
@@ -528,6 +490,7 @@ def _call(self, method, parts, identifiers, params, data_str, data_json, files):
528490
if 'result' not in response_data:
529491
# Only happens on /certificates call
530492
# should be fixed in /certificates API
493+
# may well be fixed by now
531494
if self.logger:
532495
self.logger.debug('Response: assuming success = "False"')
533496
r = response_data
@@ -586,12 +549,13 @@ def _call(self, method, parts, identifiers, params, data_str, data_json, files):
586549
result = response_data['result']
587550
except:
588551
result = response_data
552+
589553
if self.logger:
590-
if isinstance(result, str):
591-
if len(result) > 100:
592-
self.logger.debug('Response: %s...', result[0:100].replace('\n', ' '))
554+
if isinstance(result, (str, dict, list)):
555+
if len(str(result)) > 100:
556+
self.logger.debug('Response: %s...', str(result)[0:100].replace('\n', ' '))
593557
else:
594-
self.logger.debug('Response: %s', result.replace('\n', ' '))
558+
self.logger.debug('Response: %s', str(result).replace('\n', ' '))
595559
elif isinstance(result, (bytes,bytearray)):
596560
self.logger.debug('Response: %s', result[0:100])
597561
else:

CloudFlare/read_configs.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def read_configs(profile=None):
1111
""" reading the config file for Cloudflare API"""
1212

1313
# We return all these values
14-
config = {'email': None, 'key': None, 'token': None, 'certtoken': None, 'extras': None, 'base_url': None, 'profile': None}
14+
config = {'email': None, 'key': None, 'token': None, 'certtoken': None, 'extras': None, 'base_url': None, 'openapi_url': None, 'profile': None}
1515

1616
# envioronment variables override config files - so setup first
1717
config['email'] = os.getenv('CLOUDFLARE_EMAIL') if os.getenv('CLOUDFLARE_EMAIL') is not None else os.getenv('CF_API_EMAIL')
@@ -20,6 +20,7 @@ def read_configs(profile=None):
2020
config['certtoken'] = os.getenv('CLOUDFLARE_API_CERTKEY') if os.getenv('CLOUDFLARE_API_CERTKEY') is not None else os.getenv('CF_API_CERTKEY')
2121
config['extras'] = os.getenv('CLOUDFLARE_API_EXTRAS') if os.getenv('CLOUDFLARE_API_EXTRAS') is not None else os.getenv('CF_API_EXTRAS')
2222
config['base_url'] = os.getenv('CLOUDFLARE_API_URL') if os.getenv('CLOUDFLARE_API_URL') is not None else os.getenv('CF_API_URL')
23+
config['openapi_url'] = os.getenv('CLOUDFLARE_OPENAPI_URL') if os.getenv('CLOUDFLARE_OPENAPI_URL') is not None else os.getenv('CF_OPENAPI_URL')
2324

2425
config['global_request_timeout'] = os.getenv('CLOUDFLARE_GLOBAL_REQUEST_TIMEOUT')
2526
config['max_request_retries'] = os.getenv('CLOUDFLARE_MAX_REQUEST_RETRIES')
@@ -58,7 +59,7 @@ def read_configs(profile=None):
5859
if not cp.has_section(profile):
5960
raise Exception("%s: configuration section missing - configuration file only has these sections: %s" % (profile, ','.join(cp.sections())))
6061

61-
for option in ['email', 'key', 'token', 'certtoken', 'extras', 'base_url', 'global_request_timeout', 'max_request_retries']:
62+
for option in ['email', 'key', 'token', 'certtoken', 'extras', 'base_url', 'openapi_url', 'global_request_timeout', 'max_request_retries']:
6263
try:
6364
config_value = cp.get(profile, option)
6465
if option == 'extras':

0 commit comments

Comments
 (0)