25
25
26
26
27
27
class SignedRequest (object ):
28
- def __init__ (self , base_url , crypto ):
29
- self .__base_url = base_url
30
- self .__crypto = crypto
28
+ def __init__ (self , url , http_method , payload , headers ):
29
+ self .__url = url
30
+ self .__http_method = http_method
31
+ self .__payload = payload
32
+ self .__headers = headers
31
33
32
- def do_request (self , endpoint , http_method , payload = None , query_params = None ):
33
- endpoint = endpoint + self .__append_query_params (query_params )
34
- headers = self .__get_request_headers (endpoint , http_method , payload )
35
- url = self .__base_url + endpoint
34
+ @property
35
+ def url (self ):
36
+ """
37
+ Returns the URL for the SignedRequest
38
+ """
39
+ return self .__url
36
40
37
- return requests .request (
38
- method = http_method ,
39
- url = url ,
40
- data = payload ,
41
- headers = headers ,
42
- verify = yoti_python_sdk .YOTI_API_VERIFY_SSL ,
43
- )
41
+ @property
42
+ def method (self ):
43
+ """
44
+ Returns the HTTP method for the SignedRequest
45
+ """
46
+ return self .__http_method
47
+
48
+ @property
49
+ def data (self ):
50
+ """
51
+ Returns the payload data for the SignedRequest
52
+ """
53
+ return self .__payload
54
+
55
+ @property
56
+ def headers (self ):
57
+ """
58
+ Returns the HTTP headers for the SignedRequest
59
+ """
60
+ return self .__headers
44
61
45
- def post (self , endpoint , payload = None , query_params = None ):
46
- return self .do_request (
47
- endpoint , HTTP_POST , payload = payload , query_params = query_params
62
+ def prepare (self ):
63
+ """
64
+ Creates a PreparedRequest object for use in a requests Session
65
+ """
66
+ r = requests .Request (
67
+ method = self .method , url = self .url , headers = self .headers , data = self .data
48
68
)
69
+ return r .prepare ()
70
+
71
+ def execute (self ):
72
+ """
73
+ Creates and sends a PreparedRequest in a requests Session, returning the requests Response object
74
+ """
75
+ prepared = self .prepare ()
76
+ with requests .Session () as s :
77
+ return s .send (prepared )
78
+
79
+ @staticmethod
80
+ def builder ():
81
+ """
82
+ Returns an instance of SignedRequestBuilder
83
+ """
84
+ return SignedRequestBuilder ()
85
+
49
86
50
- def get (self , endpoint , query_params = None ):
51
- return self .do_request (endpoint , HTTP_GET , query_params = query_params )
87
+ class SignedRequestBuilder (object ):
88
+ def __init__ (self ):
89
+ self .__crypto = None
90
+ self .__base_url = None
91
+ self .__endpoint = None
92
+ self .__http_method = None
93
+ self .__params = None
94
+ self .__headers = None
95
+ self .__payload = None
96
+
97
+ def with_pem_file (self , pem_file ):
98
+ """
99
+ Sets the PEM file to be used for signing the request. Can be an instance of yoti_python_sdk.crypto.Crypto
100
+ or a path to a PEM file
101
+ """
102
+ if isinstance (pem_file , Crypto ):
103
+ self .__crypto = pem_file
104
+ else :
105
+ self .__crypto = Crypto .read_pem_file (pem_file )
106
+
107
+ return self
108
+
109
+ def with_base_url (self , base_url ):
110
+ """
111
+ Sets the base URL for the signed request
112
+ """
113
+ self .__base_url = base_url
114
+ return self
115
+
116
+ def with_endpoint (self , endpoint ):
117
+ """
118
+ Sets the endpoint for the signed request
119
+ """
120
+ self .__endpoint = endpoint
121
+ return self
122
+
123
+ def with_param (self , name , value ):
124
+ """
125
+ Sets a query param to be used with the endpoint
126
+ """
127
+ if self .__params is None :
128
+ self .__params = {}
129
+
130
+ self .__params [name ] = value
131
+ return self
132
+
133
+ def with_header (self , name , value ):
134
+ """
135
+ Sets a HTTP header to be used in the request
136
+ """
137
+ if self .__headers is None :
138
+ self .__headers = {}
139
+
140
+ self .__headers [name ] = value
141
+ return self
142
+
143
+ def with_http_method (self , http_method ):
144
+ """
145
+ Sets the HTTP method to be used in the request
146
+ """
147
+ self .__http_method = http_method
148
+ return self
149
+
150
+ def with_post (self ):
151
+ """
152
+ Sets the HTTP method for a POST request
153
+ """
154
+ self .with_http_method (HTTP_POST )
155
+ return self
156
+
157
+ def with_get (self ):
158
+ """
159
+ Sets the HTTP method for a GET request
160
+ """
161
+ self .__http_method = HTTP_GET
162
+ return self
52
163
53
164
def __append_query_params (self , query_params = None ):
165
+ """
166
+ Appends supplied query params in a dict to default query params.
167
+ Returns a url encoded query param string
168
+ """
54
169
required = {
55
170
"nonce" : self .__create_nonce (),
56
171
"timestamp" : self .__create_timestamp (),
57
172
}
58
173
59
- query_params = self .__merge_query_params (query_params , required )
174
+ query_params = self .__merge_dictionary (query_params , required )
60
175
return "?{}" .format (urlencode (query_params ))
61
176
62
177
@staticmethod
63
- def __merge_query_params (query_params , required ):
64
- if query_params is None :
65
- return required
178
+ def __merge_dictionary (a , b ):
179
+ """
180
+ Merges two dictionaries a and b, with b taking precedence over a
181
+ """
182
+ if a is None :
183
+ return b
66
184
67
- merged = query_params .copy ()
68
- merged .update (required )
185
+ merged = a .copy ()
186
+ merged .update (b )
69
187
return merged
70
188
71
189
def __get_request_headers (self , path , http_method , content ):
190
+ """
191
+ Returns a dictionary of request headers, also using supplied headers from builder. Default headers take precedence.
192
+ """
72
193
request = self .__create_request (http_method , path , content )
73
194
sdk_version = yoti_python_sdk .__version__
74
195
75
- return {
196
+ default = {
76
197
X_YOTI_AUTH_KEY : self .__crypto .get_public_key (),
77
198
X_YOTI_AUTH_DIGEST : self .__crypto .sign (request ),
78
199
X_YOTI_SDK : SDK_IDENTIFIER ,
@@ -81,8 +202,20 @@ def __get_request_headers(self, path, http_method, content):
81
202
"Accept" : JSON_CONTENT_TYPE ,
82
203
}
83
204
205
+ if self .__headers is not None :
206
+ return self .__merge_dictionary (self .__headers , default )
207
+
208
+ return default
209
+
84
210
@staticmethod
85
211
def __create_request (http_method , path , content ):
212
+ """
213
+ Creates a concatenated string that is used in the X-YOTI-AUTH-DIGEST header
214
+ :param http_method:
215
+ :param path:
216
+ :param content:
217
+ :return:
218
+ """
86
219
if http_method not in HTTP_SUPPORTED_METHODS :
87
220
raise ValueError (
88
221
"{} is not in the list of supported methods: {}" .format (
@@ -99,6 +232,20 @@ def __create_request(http_method, path, content):
99
232
100
233
return request
101
234
235
+ def __validate_request (self ):
236
+ """
237
+ Validates the request object to ensure the required values
238
+ have been supplied.
239
+ """
240
+ if self .__base_url is None :
241
+ raise ValueError ("Base URL must not be None" )
242
+ if self .__endpoint is None :
243
+ raise ValueError ("Endpoint must not be None" )
244
+ if self .__crypto is None :
245
+ raise ValueError ("PEM file must not be None" )
246
+ if self .__http_method is None :
247
+ raise ValueError ("HTTP method must be specified" )
248
+
102
249
@staticmethod
103
250
def __create_nonce ():
104
251
return uuid .uuid4 ()
@@ -107,30 +254,16 @@ def __create_nonce():
107
254
def __create_timestamp ():
108
255
return int (time .time () * 1000 )
109
256
110
- @staticmethod
111
- def builder ():
112
- return SignedRequestBuilder ()
113
-
114
-
115
- class SignedRequestBuilder (object ):
116
- def __init__ (self ):
117
- self .__crypto = None
118
- self .__base_url = None
119
-
120
- def with_pem_file (self , pem_file ):
121
- if isinstance (pem_file , Crypto ):
122
- self .__crypto = pem_file
123
- else :
124
- self .__crypto = Crypto .read_pem_file (pem_file )
125
-
126
- return self
127
-
128
- def with_base_url (self , base_url ):
129
- self .__base_url = base_url
130
- return self
131
-
132
257
def build (self ):
133
- if self .__crypto is None or self .__base_url is None :
134
- raise ValueError ("Crypto and base URL must not be None" )
258
+ """
259
+ Builds a SignedRequest object with the supplied values
260
+ """
261
+ self .__validate_request ()
262
+
263
+ endpoint = self .__endpoint + self .__append_query_params (self .__params )
264
+ headers = self .__get_request_headers (
265
+ endpoint , self .__http_method , self .__payload
266
+ )
267
+ url = self .__base_url + endpoint
135
268
136
- return SignedRequest (self .__base_url , self .__crypto )
269
+ return SignedRequest (url , self .__http_method , self .__payload , headers )
0 commit comments