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
@@ -478,6 +480,7 @@ def __init__(self, handler=None, **kwargs):
478480 self .password = kwargs .get ("password" , "" )
479481 self .basic = kwargs .get ("basic" , False )
480482 self .autologin = kwargs .get ("autologin" , False )
483+ self .additional_headers = kwargs .get ("headers" , [])
481484
482485 # Store any cookies in the self.http._cookies dict
483486 if "cookie" in kwargs and kwargs ['cookie' ] not in [None , _NoAuthenticationToken ]:
@@ -613,7 +616,7 @@ def delete(self, path_segment, owner=None, app=None, sharing=None, **query):
613616
614617 @_authentication
615618 @_log_duration
616- def get (self , path_segment , owner = None , app = None , sharing = None , ** query ):
619+ def get (self , path_segment , owner = None , app = None , headers = None , sharing = None , ** query ):
617620 """Performs a GET operation from the REST path segment with the given
618621 namespace and query.
619622
@@ -636,6 +639,8 @@ def get(self, path_segment, owner=None, app=None, sharing=None, **query):
636639 :type owner: ``string``
637640 :param app: The app context of the namespace (optional).
638641 :type app: ``string``
642+ :param headers: List of extra HTTP headers to send (optional).
643+ :type headers: ``list`` of 2-tuples.
639644 :param sharing: The sharing mode of the namespace (optional).
640645 :type sharing: ``string``
641646 :param query: All other keyword arguments, which are used as query
@@ -663,10 +668,14 @@ def get(self, path_segment, owner=None, app=None, sharing=None, **query):
663668 c.logout()
664669 c.get('apps/local') # raises AuthenticationError
665670 """
671+ if headers is None :
672+ headers = []
673+
666674 path = self .authority + self ._abspath (path_segment , owner = owner ,
667675 app = app , sharing = sharing )
668676 logging .debug ("GET request to %s (body: %s)" , path , repr (query ))
669- response = self .http .get (path , self ._auth_headers , ** query )
677+ all_headers = headers + self .additional_headers + self ._auth_headers
678+ response = self .http .get (path , all_headers , ** query )
670679 return response
671680
672681 @_authentication
@@ -738,7 +747,7 @@ def post(self, path_segment, owner=None, app=None, sharing=None, headers=None, *
738747
739748 path = self .authority + self ._abspath (path_segment , owner = owner , app = app , sharing = sharing )
740749 logging .debug ("POST request to %s (body: %s)" , path , repr (query ))
741- all_headers = headers + self ._auth_headers
750+ all_headers = headers + self .additional_headers + self . _auth_headers
742751 response = self .http .post (path , all_headers , ** query )
743752 return response
744753
@@ -804,7 +813,7 @@ def request(self, path_segment, method="GET", headers=None, body="",
804813 path = self .authority \
805814 + self ._abspath (path_segment , owner = owner ,
806815 app = app , sharing = sharing )
807- all_headers = headers + self ._auth_headers
816+ all_headers = headers + self .additional_headers + self . _auth_headers
808817 logging .debug ("%s request to %s (headers: %s, body: %s)" ,
809818 method , path , str (all_headers ), repr (body ))
810819 response = self .http .request (path ,
@@ -858,6 +867,7 @@ def login(self):
858867 self .authority + self ._abspath ("/services/auth/login" ),
859868 username = self .username ,
860869 password = self .password ,
870+ headers = self .additional_headers ,
861871 cookie = "1" ) # In Splunk 6.2+, passing "cookie=1" will return the "set-cookie" header
862872
863873 body = response .body .read ()
@@ -968,6 +978,8 @@ def connect(**kwargs):
968978 :type username: ``string``
969979 :param password: The password for the Splunk account.
970980 :type password: ``string``
981+ :param headers: List of extra HTTP headers to send (optional).
982+ :type headers: ``list`` of 2-tuples.
971983 :param autologin: When ``True``, automatically tries to log in again if the
972984 session terminates.
973985 :type autologin: ``Boolean``
@@ -1190,7 +1202,7 @@ def post(self, url, headers=None, **kwargs):
11901202 # to support the receivers/stream endpoint.
11911203 if 'body' in kwargs :
11921204 # 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
1205+ # Content-Type header present. This can happen in cases where we
11941206 # send requests as application/json, e.g. for KV Store.
11951207 if len ([x for x in headers if x [0 ].lower () == "content-type" ]) == 0 :
11961208 headers .append (("Content-Type" , "application/x-www-form-urlencoded" ))
0 commit comments