14
14
import json
15
15
import os
16
16
import re
17
+ import socket
17
18
from enum import Enum
18
19
from typing import NamedTuple
19
20
from urllib import parse
20
21
21
22
import requests
22
- import requests_unixsocket
23
+ import requests .adapters
24
+ import urllib3
25
+ import urllib3 .connection
23
26
from cryptography import x509
24
27
from cryptography .hazmat .primitives import hashes
25
28
from ws4py .client import WebSocketBaseClient
26
29
27
30
from pylxd import exceptions , managers
28
31
29
- requests_unixsocket .monkeypatch ()
30
-
31
32
SNAP_ROOT = os .path .expanduser ("~/snap/lxd/common/config/" )
32
33
APT_ROOT = os .path .expanduser ("~/.config/lxc/" )
33
34
CERT_FILE_NAME = "client.crt"
@@ -51,6 +52,9 @@ class Cert(NamedTuple):
51
52
key = os .path .join (CERTS_PATH , KEY_FILE_NAME ),
52
53
) # pragma: no cover
53
54
55
+ DEFAULT_SCHEME = "http+unix://"
56
+ SOCKET_CONNECTION_TIMEOUT = 60
57
+
54
58
55
59
class EventType (Enum ):
56
60
All = "all"
@@ -59,6 +63,65 @@ class EventType(Enum):
59
63
Lifecycle = "lifecycle"
60
64
61
65
66
+ class _UnixSocketHTTPConnection (urllib3 .connection .HTTPConnection , object ):
67
+ def __init__ (self , unix_socket_url ):
68
+ super (_UnixSocketHTTPConnection , self ).__init__ (
69
+ "localhost" , timeout = SOCKET_CONNECTION_TIMEOUT
70
+ )
71
+ self .unix_socket_url = unix_socket_url
72
+ self .timeout = SOCKET_CONNECTION_TIMEOUT
73
+ self .sock = None
74
+
75
+ def __del__ (self ):
76
+ if self .sock :
77
+ self .sock .close ()
78
+
79
+ def connect (self ):
80
+ sock = socket .socket (socket .AF_UNIX , socket .SOCK_STREAM )
81
+ sock .settimeout (self .timeout )
82
+ socket_path = parse .unquote (parse .urlparse (self .unix_socket_url ).netloc )
83
+ sock .connect (socket_path )
84
+ self .sock = sock
85
+
86
+
87
+ class _UnixSocketHTTPConnectionPool (urllib3 .HTTPConnectionPool ):
88
+ def __init__ (self , socket_path ):
89
+ super (_UnixSocketHTTPConnectionPool , self ).__init__ ("localhost" )
90
+ self .socket_path = socket_path
91
+
92
+ def _new_conn (self ):
93
+ return _UnixSocketHTTPConnection (self .socket_path )
94
+
95
+
96
+ class _UnixAdapter (requests .adapters .HTTPAdapter ):
97
+ def __init__ (self , pool_connections = 25 , * args , ** kwargs ):
98
+ super (_UnixAdapter , self ).__init__ (* args , ** kwargs )
99
+ self .pools = urllib3 ._collections .RecentlyUsedContainer (
100
+ pool_connections , dispose_func = lambda p : p .close ()
101
+ )
102
+
103
+ def get_connection (self , url , proxies ):
104
+ with self .pools .lock :
105
+ conn = self .pools .get (url )
106
+ if conn :
107
+ return conn
108
+
109
+ conn = _UnixSocketHTTPConnectionPool (url )
110
+ self .pools [url ] = conn
111
+
112
+ return conn
113
+
114
+ # This method is needed fo compatibility with later requests versions.
115
+ def get_connection_with_tls_context (self , request , verify , proxies = None , cert = None ):
116
+ return self .get_connection (request .url , None )
117
+
118
+ def request_url (self , request , proxies ):
119
+ return request .path_url
120
+
121
+ def close (self ):
122
+ self .pools .clear ()
123
+
124
+
62
125
class LXDSSLAdapter (requests .adapters .HTTPAdapter ):
63
126
def cert_verify (self , conn , url , verify , cert ):
64
127
with open (verify , "rb" ) as fd :
@@ -74,11 +137,10 @@ def get_session_for_url(url: str, verify=None, cert=None) -> requests.Session:
74
137
75
138
Call sites can use this to customise the session before passing into a Client.
76
139
"""
77
- session : requests .Session
78
- if url .startswith ("http+unix://" ):
79
- session = requests_unixsocket . Session ( )
140
+ session = requests .Session ()
141
+ if url .startswith (DEFAULT_SCHEME ):
142
+ session . mount ( DEFAULT_SCHEME , _UnixAdapter () )
80
143
else :
81
- session = requests .Session ()
82
144
session .cert = cert
83
145
session .verify = verify
84
146
0 commit comments