16
16
from __future__ import unicode_literals
17
17
18
18
import requests
19
- import ssl
20
19
21
- from requests .adapters import HTTPAdapter
22
- from requests .exceptions import SSLError
23
- from requests .packages .urllib3 .poolmanager import PoolManager
24
- from labkey .exceptions import RequestError , RequestAuthorizationError , QueryNotFoundError , \
25
- ServerContextError , ServerNotFoundError
20
+ from requests .exceptions import RequestException
21
+ from labkey .exceptions import RequestError , RequestAuthorizationError , QueryNotFoundError , ServerContextError , \
22
+ ServerNotFoundError
26
23
27
24
__default_timeout = 60 * 5 # 5 minutes
25
+ API_KEY_TOKEN = 'apikey'
28
26
CSRF_TOKEN = 'X-LABKEY-CSRF'
29
27
DISABLE_CSRF_CHECK = False # Used by tests to disable CSRF token check
30
28
31
29
32
- def create_server_context (domain , container_path , context_path = None , use_ssl = True ):
30
+ def create_server_context (domain , container_path , context_path = None , use_ssl = True , api_key = None ):
33
31
"""
34
32
Create a LabKey server context. This context is used to encapsulate properties
35
33
about the LabKey server that is being requested against. This includes, but is not limited to,
@@ -38,9 +36,17 @@ def create_server_context(domain, container_path, context_path=None, use_ssl=Tru
38
36
:param container_path:
39
37
:param context_path:
40
38
:param use_ssl:
39
+ :param api_key:
41
40
:return:
42
41
"""
43
- config = dict (domain = domain , container_path = container_path , context_path = context_path , use_ssl = use_ssl )
42
+ config = dict (
43
+ domain = domain ,
44
+ container_path = container_path ,
45
+ context_path = context_path ,
46
+ use_ssl = use_ssl ,
47
+ api_key = api_key
48
+ )
49
+
44
50
return ServerContext (** config )
45
51
46
52
@@ -57,6 +63,12 @@ def build_url(server_context, controller, action, container_path=None):
57
63
return server_context .build_url (controller , action , container_path = container_path )
58
64
59
65
66
+ def handle_request_exception (e , server_context = None ):
67
+ if type (e ) in [RequestAuthorizationError , QueryNotFoundError , ServerNotFoundError ]:
68
+ raise e
69
+ raise ServerContextError (server_context , e )
70
+
71
+
60
72
def handle_response (response ):
61
73
sc = response .status_code
62
74
@@ -81,32 +93,23 @@ def handle_response(response):
81
93
# could not decode response
82
94
raise ServerNotFoundError (response )
83
95
else :
96
+ # consider response.raise_for_status()
84
97
raise RequestError (response )
85
98
86
99
87
- # _ssl.c:504: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
88
- # http://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/
89
- class SafeTLSAdapter (HTTPAdapter ):
90
- def init_poolmanager (self , connections , maxsize , block = False ):
91
- self .poolmanager = PoolManager (num_pools = connections ,
92
- maxsize = maxsize ,
93
- block = block ,
94
- ssl_version = ssl .PROTOCOL_TLSv1 )
95
-
96
-
97
100
class ServerContext (object ):
98
101
99
102
def __init__ (self , ** kwargs ):
100
103
self ._container_path = kwargs .pop ('container_path' , None )
101
104
self ._context_path = kwargs .pop ('context_path' , None )
102
105
self ._domain = kwargs .pop ('domain' , None )
103
106
self ._use_ssl = kwargs .pop ('use_ssl' , True )
107
+ self ._api_key = kwargs .pop ('api_key' , None )
104
108
105
109
self ._session = requests .Session ()
106
110
107
111
if self ._use_ssl :
108
112
self ._scheme = 'https://'
109
- self ._session .mount (self ._scheme , SafeTLSAdapter ())
110
113
else :
111
114
self ._scheme = 'http://'
112
115
@@ -129,6 +132,14 @@ def build_url(self, controller, action, container_path=None):
129
132
130
133
def make_request (self , url , payload , headers = None , timeout = 300 , method = 'POST' ):
131
134
135
+ if self ._api_key is not None :
136
+ global API_KEY_TOKEN
137
+
138
+ if self ._session .headers .get (API_KEY_TOKEN ) is not self ._api_key :
139
+ self ._session .headers .update ({
140
+ API_KEY_TOKEN : self ._api_key
141
+ })
142
+
132
143
if not DISABLE_CSRF_CHECK :
133
144
global CSRF_TOKEN
134
145
@@ -140,14 +151,14 @@ def make_request(self, url, payload, headers=None, timeout=300, method='POST'):
140
151
self ._session .headers .update ({
141
152
CSRF_TOKEN : response ['CSRF' ]
142
153
})
143
- except SSLError as e :
144
- raise ServerContextError ( e )
154
+ except RequestException as e :
155
+ handle_request_exception ( e , server_context = self )
145
156
146
157
try :
147
158
if method is 'GET' :
148
159
raw_response = self ._session .get (url , params = payload , headers = headers , timeout = timeout )
149
160
else :
150
161
raw_response = self ._session .post (url , data = payload , headers = headers , timeout = timeout )
151
162
return handle_response (raw_response )
152
- except SSLError as e :
153
- raise ServerContextError ( e )
163
+ except RequestException as e :
164
+ handle_request_exception ( e , server_context = self )
0 commit comments