@@ -306,23 +306,89 @@ def getMap(self, ips):
306306 response .raise_for_status ()
307307 return response .json ()["reportUrl" ]
308308
309- def getIterativeBatchDetails (self , ip_addresses , batch_size = None ):
309+ def getIterativeBatchDetails (
310+ self ,
311+ ip_addresses ,
312+ batch_size = None ,
313+ raise_on_fail = True ,
314+ ):
310315 if batch_size == None :
311316 batch_size = BATCH_MAX_SIZE
312317
318+ results = {}
319+
320+ # pre-populate with anything we've got in the cache, and keep around
321+ # the IPs not in the cache.
322+ lookup_addresses = []
323+ for ip_address in ip_addresses :
324+ # if the supplied IP address uses the objects defined in the
325+ # built-in module ipaddress extract the appropriate string notation
326+ # before formatting the URL.
327+ if isinstance (ip_address , IPv4Address ) or isinstance (
328+ ip_address , IPv6Address
329+ ):
330+ ip_address = ip_address .exploded
331+
332+ # check if bogon.
333+ if ip_address and is_bogon (ip_address ):
334+ details = {}
335+ details ["ip" ] = ip_address
336+ details ["bogon" ] = True
337+ yield Details (details )
338+
339+ # check cache first.
340+ try :
341+ cached_ipaddr = self .cache [cache_key (ip_address )]
342+ results [ip_address ] = cached_ipaddr
343+ except KeyError :
344+ lookup_addresses .append (ip_address )
345+
346+ # all in cache - return early.
347+ if len (lookup_addresses ) == 0 :
348+ for ip_address , details in results .items ():
349+ yield ip_address , details
350+
351+ # loop over batch chunks and do lookup for each.
313352 url = API_URL + "/batch"
314353 headers = handler_utils .get_headers (self .access_token , self .headers )
315354 headers ["content-type" ] = "application/json"
355+ for i in range (0 , len (lookup_addresses ), batch_size ):
356+ batch = lookup_addresses [i : i + batch_size ]
316357
317- # Split the IP addresses into batches
318- batches = [
319- ip_addresses [ i : i + batch_size ]
320- for i in range ( 0 , len ( ip_addresses ), batch_size )
321- ]
358+ # lookup.
359+ try :
360+ response = requests . post ( url , json = batch , headers = headers )
361+ except Exception as e :
362+ return handler_utils . return_or_fail ( raise_on_fail , e , result )
322363
323- for batch in batches :
324- response = requests .post (url , json = batch , headers = headers )
325- json_response = response .json ()
364+ # fail on bad status codes
365+ try :
366+ if response .status_code == 429 :
367+ raise RequestQuotaExceededError ()
368+ response .raise_for_status ()
369+ except Exception as e :
370+ return handler_utils .return_or_fail (raise_on_fail , e , result )
326371
372+ # fill cache
373+ json_response = response .json ()
374+ print (f"JSON: { json_response } " )
327375 for ip_address , details in json_response .items ():
376+ self .cache [cache_key (ip_address )] = details
377+
378+ # merge cached results with new lookup
379+ results .update (json_response )
380+
381+ # format all
382+ for detail in results .values ():
383+ if isinstance (detail , dict ):
384+ handler_utils .format_details (
385+ detail ,
386+ self .countries ,
387+ self .eu_countries ,
388+ self .countries_flags ,
389+ self .countries_currencies ,
390+ self .continents ,
391+ )
392+
393+ for ip_address , details in results .items ():
328394 yield ip_address , details
0 commit comments