@@ -223,10 +223,17 @@ class TCPConnector(BaseConnector):
223
223
"""
224
224
225
225
def __init__ (self , * args , verify_ssl = True ,
226
- resolve = False , family = socket .AF_INET , ** kwargs ):
226
+ resolve = False , family = socket .AF_INET , ssl_context = None ,
227
+ ** kwargs ):
228
+ if not verify_ssl and ssl_context is not None :
229
+ raise ValueError (
230
+ "Either disable ssl certificate validation by "
231
+ "verify_ssl=False or specify ssl_context, not both." )
232
+
227
233
super ().__init__ (* args , ** kwargs )
228
234
229
235
self ._verify_ssl = verify_ssl
236
+ self ._ssl_context = ssl_context
230
237
self ._family = family
231
238
self ._resolve = resolve
232
239
self ._resolved_hosts = {}
@@ -236,6 +243,30 @@ def verify_ssl(self):
236
243
"""Do check for ssl certifications?"""
237
244
return self ._verify_ssl
238
245
246
+ @property
247
+ def ssl_context (self ):
248
+ """SSLContext instance for https requests.
249
+
250
+ Lazy property, creates context on demand.
251
+ """
252
+ if self ._ssl_context is None :
253
+ if not self ._verify_ssl :
254
+ sslcontext = ssl .SSLContext (ssl .PROTOCOL_SSLv23 )
255
+ sslcontext .options |= ssl .OP_NO_SSLv2
256
+ sslcontext .set_default_verify_paths ()
257
+ elif hasattr (ssl , 'create_default_context' ):
258
+ # Python 3.4+
259
+ sslcontext = ssl .create_default_context ()
260
+ else : # pragma: no cover
261
+ # Fallback for Python 3.3.
262
+ sslcontext = ssl .SSLContext (ssl .PROTOCOL_SSLv23 )
263
+ sslcontext .options |= ssl .OP_NO_SSLv2
264
+ sslcontext .options |= ssl .OP_NO_SSLv3
265
+ sslcontext .set_default_verify_paths ()
266
+ sslcontext .verify_mode = ssl .CERT_REQUIRED
267
+ self ._ssl_context = sslcontext
268
+ return self ._ssl_context
269
+
239
270
@property
240
271
def family (self ):
241
272
"""Socket family like AF_INET."""
@@ -288,11 +319,10 @@ def _create_connection(self, req, **kwargs):
288
319
289
320
Has same keyword arguments as BaseEventLoop.create_connection.
290
321
"""
291
- sslcontext = req .ssl
292
- if req .ssl and not self ._verify_ssl :
293
- sslcontext = ssl .SSLContext (ssl .PROTOCOL_SSLv23 )
294
- sslcontext .options |= ssl .OP_NO_SSLv2
295
- sslcontext .set_default_verify_paths ()
322
+ if req .ssl :
323
+ sslcontext = self .ssl_context
324
+ else :
325
+ sslcontext = None
296
326
297
327
hosts = yield from self ._resolve_host (req .host , req .port )
298
328
0 commit comments