@@ -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 :
0 commit comments