urllib 3.20.0 → 3.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,9 +35,25 @@ function formatSocket(socket: Socket) {
35
35
  localPort: socket[symbols.kSocketLocalPort],
36
36
  remoteAddress: socket.remoteAddress,
37
37
  remotePort: socket.remotePort,
38
+ attemptedAddresses: socket.autoSelectFamilyAttemptedAddresses,
39
+ connecting: socket.connecting,
38
40
  };
39
41
  }
40
42
 
43
+ // make sure error contains socket info
44
+ const kDestroy = Symbol('kDestroy');
45
+ Socket.prototype[kDestroy] = Socket.prototype.destroy;
46
+ Socket.prototype.destroy = function(err?: any) {
47
+ if (err) {
48
+ Object.defineProperty(err, symbols.kErrorSocket, {
49
+ // don't show on console log
50
+ enumerable: false,
51
+ value: this,
52
+ });
53
+ }
54
+ return this[kDestroy](err);
55
+ };
56
+
41
57
  export function initDiagnosticsChannel() {
42
58
  // makre sure init global DiagnosticsChannel once
43
59
  if (initedDiagnosticsChannel) return;
@@ -67,10 +83,37 @@ export function initDiagnosticsChannel() {
67
83
  });
68
84
 
69
85
  // diagnosticsChannel.channel('undici:client:beforeConnect')
70
- // diagnosticsChannel.channel('undici:client:connectError')
86
+
87
+ subscribe('undici:client:connectError', (message, name) => {
88
+ const { error, connectParams } = message as DiagnosticsChannel.ClientConnectErrorMessage & { error: any };
89
+ let { socket } = message as DiagnosticsChannel.ClientConnectErrorMessage;
90
+ if (!socket && error[symbols.kErrorSocket]) {
91
+ socket = error[symbols.kErrorSocket];
92
+ }
93
+ if (socket) {
94
+ socket[symbols.kSocketId] = globalId('UndiciSocket');
95
+ socket[symbols.kSocketConnectErrorTime] = new Date();
96
+ socket[symbols.kHandledRequests] = 0;
97
+ socket[symbols.kHandledResponses] = 0;
98
+ // copy local address to symbol, avoid them be reset after request error throw
99
+ if (socket.localAddress) {
100
+ socket[symbols.kSocketLocalAddress] = socket.localAddress;
101
+ socket[symbols.kSocketLocalPort] = socket.localPort;
102
+ }
103
+ socket[symbols.kSocketConnectProtocol] = connectParams.protocol;
104
+ socket[symbols.kSocketConnectHost] = connectParams.host;
105
+ socket[symbols.kSocketConnectPort] = connectParams.port;
106
+ debug('[%s] Socket#%d connectError, connectParams: %o, error: %s, (sock: %o)',
107
+ name, socket[symbols.kSocketId], connectParams, (error as Error).message, formatSocket(socket));
108
+ } else {
109
+ debug('[%s] connectError, connectParams: %o, error: %o',
110
+ name, connectParams, error);
111
+ }
112
+ });
113
+
71
114
  // This message is published after a connection is established.
72
115
  subscribe('undici:client:connected', (message, name) => {
73
- const { socket } = message as DiagnosticsChannel.ClientConnectedMessage;
116
+ const { socket, connectParams } = message as DiagnosticsChannel.ClientConnectedMessage;
74
117
  socket[symbols.kSocketId] = globalId('UndiciSocket');
75
118
  socket[symbols.kSocketStartTime] = performance.now();
76
119
  socket[symbols.kSocketConnectedTime] = new Date();
@@ -79,6 +122,9 @@ export function initDiagnosticsChannel() {
79
122
  // copy local address to symbol, avoid them be reset after request error throw
80
123
  socket[symbols.kSocketLocalAddress] = socket.localAddress;
81
124
  socket[symbols.kSocketLocalPort] = socket.localPort;
125
+ socket[symbols.kSocketConnectProtocol] = connectParams.protocol;
126
+ socket[symbols.kSocketConnectHost] = connectParams.host;
127
+ socket[symbols.kSocketConnectPort] = connectParams.port;
82
128
  debug('[%s] Socket#%d connected (sock: %o)', name, socket[symbols.kSocketId], formatSocket(socket));
83
129
  });
84
130
 
package/src/index.ts CHANGED
@@ -2,25 +2,29 @@ import LRU from 'ylru';
2
2
  import { HttpClient, HEADER_USER_AGENT } from './HttpClient.js';
3
3
  import { RequestOptions, RequestURL } from './Request.js';
4
4
 
5
- let httpclient: HttpClient;
6
- const domainSocketHttpclients = new LRU(50);
5
+ let httpClient: HttpClient;
6
+ const domainSocketHttpClients = new LRU(50);
7
+
8
+ export function getDefaultHttpClient(): HttpClient {
9
+ if (!httpClient) {
10
+ httpClient = new HttpClient();
11
+ }
12
+ return httpClient;
13
+ }
7
14
 
8
15
  export async function request<T = any>(url: RequestURL, options?: RequestOptions) {
9
16
  if (options?.socketPath) {
10
- let domainSocketHttpclient = domainSocketHttpclients.get<HttpClient>(options.socketPath);
17
+ let domainSocketHttpclient = domainSocketHttpClients.get<HttpClient>(options.socketPath);
11
18
  if (!domainSocketHttpclient) {
12
19
  domainSocketHttpclient = new HttpClient({
13
20
  connect: { socketPath: options.socketPath },
14
21
  });
15
- domainSocketHttpclients.set(options.socketPath, domainSocketHttpclient);
22
+ domainSocketHttpClients.set(options.socketPath, domainSocketHttpclient);
16
23
  }
17
24
  return await domainSocketHttpclient.request<T>(url, options);
18
25
  }
19
26
 
20
- if (!httpclient) {
21
- httpclient = new HttpClient({});
22
- }
23
- return await httpclient.request<T>(url, options);
27
+ return await getDefaultHttpClient().request<T>(url, options);
24
28
  }
25
29
 
26
30
  // export curl method is keep compatible with urllib.curl()
@@ -36,12 +40,12 @@ export {
36
40
  MockAgent, ProxyAgent, Agent, Dispatcher,
37
41
  setGlobalDispatcher, getGlobalDispatcher,
38
42
  } from 'undici';
39
- // HttpClient2 is keep compatible with urlib@2 HttpClient2
43
+ // HttpClient2 is keep compatible with urllib@2 HttpClient2
40
44
  export {
41
45
  HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT,
42
46
  RequestDiagnosticsMessage, ResponseDiagnosticsMessage,
43
47
  } from './HttpClient.js';
44
- // RequestOptions2 is keep compatible with urlib@2 RequestOptions2
48
+ // RequestOptions2 is keep compatible with urllib@2 RequestOptions2
45
49
  export {
46
50
  RequestOptions, RequestOptions as RequestOptions2, RequestURL, HttpMethod,
47
51
  FixJSONCtlCharsHandler, FixJSONCtlChars,
@@ -53,6 +57,7 @@ export {
53
57
  export {
54
58
  IncomingHttpHeaders,
55
59
  } from './IncomingHttpHeaders.js';
60
+ export * from './HttpClientError.js';
56
61
 
57
62
  export default {
58
63
  request,
package/src/symbols.ts CHANGED
@@ -2,9 +2,13 @@ export default {
2
2
  kSocketId: Symbol('socket id'),
3
3
  kSocketStartTime: Symbol('socket start time'),
4
4
  kSocketConnectedTime: Symbol('socket connected time'),
5
+ kSocketConnectErrorTime: Symbol('socket connectError time'),
5
6
  kSocketRequestEndTime: Symbol('socket request end time'),
6
7
  kSocketLocalAddress: Symbol('socket local address'),
7
8
  kSocketLocalPort: Symbol('socket local port'),
9
+ kSocketConnectHost: Symbol('socket connect params: host'),
10
+ kSocketConnectPort: Symbol('socket connect params: port'),
11
+ kSocketConnectProtocol: Symbol('socket connect params: protocol'),
8
12
  kHandledRequests: Symbol('handled requests per socket'),
9
13
  kHandledResponses: Symbol('handled responses per socket'),
10
14
  kRequestSocket: Symbol('request on the socket'),
@@ -13,4 +17,5 @@ export default {
13
17
  kEnableRequestTiming: Symbol('enable request timing or not'),
14
18
  kRequestTiming: Symbol('request timing'),
15
19
  kRequestOriginalOpaque: Symbol('request original opaque'),
20
+ kErrorSocket: Symbol('socket of error'),
16
21
  };