3030import logging
3131import socket
3232import ssl
33+ import sys
34+ import time
3335from base64 import b64encode
3436from contextlib import contextmanager
3537from datetime import datetime
@@ -295,8 +297,7 @@ def wrapper(self, *args, **kwargs):
295297 with _handle_auth_error ("Autologin failed." ):
296298 self .login ()
297299 with _handle_auth_error (
298- "Autologin succeeded, but there was an auth error on "
299- "next request. Something is very wrong." ):
300+ "Authentication Failed! If session token is used, it seems to have been expired." ):
300301 return request_fun (self , * args , ** kwargs )
301302 elif he .status == 401 and not self .autologin :
302303 raise AuthenticationError (
@@ -453,6 +454,12 @@ class Context(object):
453454 :type splunkToken: ``string``
454455 :param headers: List of extra HTTP headers to send (optional).
455456 :type headers: ``list`` of 2-tuples.
457+ :param retires: Number of retries for each HTTP connection (optional, the default is 0).
458+ NOTE THAT THIS MAY INCREASE THE NUMBER OF ROUND TRIP CONNECTIONS TO THE SPLUNK SERVER AND BLOCK THE
459+ CURRENT THREAD WHILE RETRYING.
460+ :type retries: ``int``
461+ :param retryDelay: How long to wait between connection attempts if `retries` > 0 (optional, defaults to 10s).
462+ :type retryDelay: ``int`` (in seconds)
456463 :param handler: The HTTP request handler (optional).
457464 :returns: A ``Context`` instance.
458465
@@ -470,7 +477,8 @@ class Context(object):
470477 """
471478 def __init__ (self , handler = None , ** kwargs ):
472479 self .http = HttpLib (handler , kwargs .get ("verify" , False ), key_file = kwargs .get ("key_file" ),
473- cert_file = kwargs .get ("cert_file" ), context = kwargs .get ("context" )) # Default to False for backward compat
480+ cert_file = kwargs .get ("cert_file" ), context = kwargs .get ("context" ), # Default to False for backward compat
481+ retries = kwargs .get ("retries" , 0 ), retryDelay = kwargs .get ("retryDelay" , 10 ))
474482 self .token = kwargs .get ("token" , _NoAuthenticationToken )
475483 if self .token is None : # In case someone explicitly passes token=None
476484 self .token = _NoAuthenticationToken
@@ -499,13 +507,13 @@ def get_cookies(self):
499507 return self .http ._cookies
500508
501509 def has_cookies (self ):
502- """Returns true if the ``HttpLib`` member of this instance has at least
503- one cookie stored.
510+ """Returns true if the ``HttpLib`` member of this instance has auth token stored.
504511
505- :return: ``True`` if there is at least one cookie , else ``False``
512+ :return: ``True`` if there is auth token present , else ``False``
506513 :rtype: ``bool``
507514 """
508- return len (self .get_cookies ()) > 0
515+ auth_token_key = "splunkd_"
516+ return any (auth_token_key in key for key in self .get_cookies ().keys ())
509517
510518 # Shared per-context request headers
511519 @property
@@ -800,9 +808,6 @@ def request(self, path_segment, method="GET", headers=None, body={},
800808 :type app: ``string``
801809 :param sharing: The sharing mode of the namespace (optional).
802810 :type sharing: ``string``
803- :param query: All other keyword arguments, which are used as query
804- parameters.
805- :type query: ``string``
806811 :return: The response from the server.
807812 :rtype: ``dict`` with keys ``body``, ``headers``, ``reason``,
808813 and ``status``
@@ -1157,12 +1162,14 @@ class HttpLib(object):
11571162
11581163 If using the default handler, SSL verification can be disabled by passing verify=False.
11591164 """
1160- def __init__ (self , custom_handler = None , verify = False , key_file = None , cert_file = None , context = None ):
1165+ def __init__ (self , custom_handler = None , verify = False , key_file = None , cert_file = None , context = None , retries = 0 , retryDelay = 10 ):
11611166 if custom_handler is None :
11621167 self .handler = handler (verify = verify , key_file = key_file , cert_file = cert_file , context = context )
11631168 else :
11641169 self .handler = custom_handler
11651170 self ._cookies = {}
1171+ self .retries = retries
1172+ self .retryDelay = retryDelay
11661173
11671174 def delete (self , url , headers = None , ** kwargs ):
11681175 """Sends a DELETE request to a URL.
@@ -1276,7 +1283,16 @@ def request(self, url, message, **kwargs):
12761283 its structure).
12771284 :rtype: ``dict``
12781285 """
1279- response = self .handler (url , message , ** kwargs )
1286+ while True :
1287+ try :
1288+ response = self .handler (url , message , ** kwargs )
1289+ break
1290+ except Exception :
1291+ if self .retries <= 0 :
1292+ raise
1293+ else :
1294+ time .sleep (self .retryDelay )
1295+ self .retries -= 1
12801296 response = record (response )
12811297 if 400 <= response .status :
12821298 raise HTTPError (response )
@@ -1414,7 +1430,7 @@ def request(url, message, **kwargs):
14141430 head = {
14151431 "Content-Length" : str (len (body )),
14161432 "Host" : host ,
1417- "User-Agent" : "splunk-sdk-python/1.6.19 " ,
1433+ "User-Agent" : "splunk-sdk-python/1.6.20 " ,
14181434 "Accept" : "*/*" ,
14191435 "Connection" : "Close" ,
14201436 } # defaults
0 commit comments