2525""" 
2626
2727from  __future__ import  absolute_import 
28+ 
29+ import  io 
2830import  logging 
2931import  socket 
3032import  ssl 
31- from  io  import  BytesIO 
32- 
33- from  splunklib .six .moves  import  urllib 
34- import  io 
3533import  sys 
36- 
3734from  base64  import  b64encode 
35+ from  contextlib  import  contextmanager 
3836from  datetime  import  datetime 
3937from  functools  import  wraps 
38+ from  io  import  BytesIO 
39+ from  xml .etree .ElementTree  import  XML 
40+ 
41+ from  splunklib  import  six 
4042from  splunklib .six  import  StringIO 
43+ from  splunklib .six .moves  import  urllib 
4144
42- from  contextlib  import  contextmanager 
45+ from  . data  import  record 
4346
44- from  xml .etree .ElementTree  import  XML 
45- from  splunklib  import  six 
4647try :
4748    from  xml .etree .ElementTree  import  ParseError 
4849except  ImportError  as  e :
4950    from  xml .parsers .expat  import  ExpatError  as  ParseError 
5051
51- from  .data  import  record 
5252
5353__all__  =  [
5454    "AuthenticationError" ,
@@ -449,6 +449,8 @@ class Context(object):
449449    :type username: ``string`` 
450450    :param password: The password for the Splunk account. 
451451    :type password: ``string`` 
452+     :param headers: List of extra HTTP headers to send (optional). 
453+     :type headers: ``list`` of 2-tuples. 
452454    :param handler: The HTTP request handler (optional). 
453455    :returns: A ``Context`` instance. 
454456
@@ -465,7 +467,8 @@ class Context(object):
465467        c = binding.Context(cookie="splunkd_8089=...") 
466468    """ 
467469    def  __init__ (self , handler = None , ** kwargs ):
468-         self .http  =  HttpLib (handler , kwargs .get ("verify" , True ))
470+         self .http  =  HttpLib (handler , kwargs .get ("verify" , False ), key_file = kwargs .get ("key_file" ),
471+                             cert_file = kwargs .get ("cert_file" ))  # Default to False for backward compat 
469472        self .token  =  kwargs .get ("token" , _NoAuthenticationToken )
470473        if  self .token  is  None : # In case someone explicitly passes token=None 
471474            self .token  =  _NoAuthenticationToken 
@@ -478,6 +481,7 @@ def __init__(self, handler=None, **kwargs):
478481        self .password  =  kwargs .get ("password" , "" )
479482        self .basic  =  kwargs .get ("basic" , False )
480483        self .autologin  =  kwargs .get ("autologin" , False )
484+         self .additional_headers  =  kwargs .get ("headers" , [])
481485
482486        # Store any cookies in the self.http._cookies dict 
483487        if  "cookie"  in  kwargs  and  kwargs ['cookie' ] not  in None , _NoAuthenticationToken ]:
@@ -613,7 +617,7 @@ def delete(self, path_segment, owner=None, app=None, sharing=None, **query):
613617
614618    @_authentication  
615619    @_log_duration  
616-     def  get (self , path_segment , owner = None , app = None , sharing = None , ** query ):
620+     def  get (self , path_segment , owner = None , app = None , headers = None ,  sharing = None , ** query ):
617621        """Performs a GET operation from the REST path segment with the given 
618622        namespace and query. 
619623
@@ -636,6 +640,8 @@ def get(self, path_segment, owner=None, app=None, sharing=None, **query):
636640        :type owner: ``string`` 
637641        :param app: The app context of the namespace (optional). 
638642        :type app: ``string`` 
643+         :param headers: List of extra HTTP headers to send (optional). 
644+         :type headers: ``list`` of 2-tuples. 
639645        :param sharing: The sharing mode of the namespace (optional). 
640646        :type sharing: ``string`` 
641647        :param query: All other keyword arguments, which are used as query 
@@ -663,10 +669,14 @@ def get(self, path_segment, owner=None, app=None, sharing=None, **query):
663669            c.logout() 
664670            c.get('apps/local') # raises AuthenticationError 
665671        """ 
672+         if  headers  is  None :
673+             headers  =  []
674+ 
666675        path  =  self .authority  +  self ._abspath (path_segment , owner = owner ,
667676                                              app = app , sharing = sharing )
668677        logging .debug ("GET request to %s (body: %s)" , path , repr (query ))
669-         response  =  self .http .get (path , self ._auth_headers , ** query )
678+         all_headers  =  headers  +  self .additional_headers  +  self ._auth_headers 
679+         response  =  self .http .get (path , all_headers , ** query )
670680        return  response 
671681
672682    @_authentication  
@@ -738,7 +748,7 @@ def post(self, path_segment, owner=None, app=None, sharing=None, headers=None, *
738748
739749        path  =  self .authority  +  self ._abspath (path_segment , owner = owner , app = app , sharing = sharing )
740750        logging .debug ("POST request to %s (body: %s)" , path , repr (query ))
741-         all_headers  =  headers  +  self ._auth_headers 
751+         all_headers  =  headers  +  self .additional_headers   +   self . _auth_headers 
742752        response  =  self .http .post (path , all_headers , ** query )
743753        return  response 
744754
@@ -804,7 +814,7 @@ def request(self, path_segment, method="GET", headers=None, body="",
804814        path  =  self .authority  \
805815            +  self ._abspath (path_segment , owner = owner ,
806816                            app = app , sharing = sharing )
807-         all_headers  =  headers  +  self ._auth_headers 
817+         all_headers  =  headers  +  self .additional_headers   +   self . _auth_headers 
808818        logging .debug ("%s request to %s (headers: %s, body: %s)" ,
809819                      method , path , str (all_headers ), repr (body ))
810820        response  =  self .http .request (path ,
@@ -858,6 +868,7 @@ def login(self):
858868                self .authority  +  self ._abspath ("/services/auth/login" ),
859869                username = self .username ,
860870                password = self .password ,
871+                 headers = self .additional_headers ,
861872                cookie = "1" ) # In Splunk 6.2+, passing "cookie=1" will return the "set-cookie" header 
862873
863874            body  =  response .body .read ()
@@ -968,6 +979,8 @@ def connect(**kwargs):
968979    :type username: ``string`` 
969980    :param password: The password for the Splunk account. 
970981    :type password: ``string`` 
982+     :param headers: List of extra HTTP headers to send (optional). 
983+     :type headers: ``list`` of 2-tuples. 
971984    :param autologin: When ``True``, automatically tries to log in again if the 
972985        session terminates. 
973986    :type autologin: ``Boolean`` 
@@ -1108,8 +1121,11 @@ class HttpLib(object):
11081121
11091122    If using the default handler, SSL verification can be disabled by passing verify=False. 
11101123    """ 
1111-     def  __init__ (self , custom_handler = None , verify = True ):
1112-         self .handler  =  handler (verify = verify ) if  custom_handler  is  None  else  custom_handler 
1124+     def  __init__ (self , custom_handler = None , verify = False , key_file = None , cert_file = None ):
1125+         if  custom_handler  is  None :
1126+             self .handler  =  handler (verify = verify , key_file = key_file , cert_file = cert_file )
1127+         else :
1128+             self .handler  =  custom_handler 
11131129        self ._cookies  =  {}
11141130
11151131    def  delete (self , url , headers = None , ** kwargs ):
@@ -1190,7 +1206,7 @@ def post(self, url, headers=None, **kwargs):
11901206        # to support the receivers/stream endpoint. 
11911207        if  'body'  in  kwargs :
11921208            # We only use application/x-www-form-urlencoded if there is no other 
1193-             # Content-Type header present. This can happen in cases where we   
1209+             # Content-Type header present. This can happen in cases where we 
11941210            # send requests as application/json, e.g. for KV Store. 
11951211            if  len ([x  for  x  in  headers  if  x [0 ].lower () ==  "content-type" ]) ==  0 :
11961212                headers .append (("Content-Type" , "application/x-www-form-urlencoded" ))
@@ -1280,8 +1296,8 @@ def peek(self, size):
12801296
12811297    def  close (self ):
12821298        """Closes this response.""" 
1283-         if  _connection :
1284-             _connection .close ()
1299+         if  self . _connection :
1300+             self . _connection .close ()
12851301        self ._response .close ()
12861302
12871303    def  read (self , size  =  None ):
@@ -1317,7 +1333,7 @@ def readinto(self, byte_array):
13171333        return  bytes_read 
13181334
13191335
1320- def  handler (key_file = None , cert_file = None , timeout = None , verify = True ):
1336+ def  handler (key_file = None , cert_file = None , timeout = None , verify = False ):
13211337    """This class returns an instance of the default HTTP request handler using 
13221338    the values you provide. 
13231339
@@ -1341,7 +1357,7 @@ def connect(scheme, host, port):
13411357            if  cert_file  is  not None : kwargs ['cert_file' ] =  cert_file 
13421358
13431359            # If running Python 2.7.9+, disable SSL certificate validation 
1344-             if  (sys .version_info  >=  (2 ,7 ,9 ) and  key_file  is  None  and  cert_file  is  None ) or  not  verify :
1360+             if  (sys .version_info  >=  (2 ,7 ,9 ) and  key_file  is  None  and  cert_file  is  None ) and  not  verify :
13451361                kwargs ['context' ] =  ssl ._create_unverified_context ()
13461362            return  six .moves .http_client .HTTPSConnection (host , port , ** kwargs )
13471363        raise  ValueError ("unsupported scheme: %s"  %  scheme )
@@ -1352,7 +1368,7 @@ def request(url, message, **kwargs):
13521368        head  =  {
13531369            "Content-Length" : str (len (body )),
13541370            "Host" : host ,
1355-             "User-Agent" : "splunk-sdk-python/1.6.5 " ,
1371+             "User-Agent" : "splunk-sdk-python/1.6.6 " ,
13561372            "Accept" : "*/*" ,
13571373            "Connection" : "Close" ,
13581374        } # defaults 
0 commit comments