@api-client/core 0.18.12 → 0.18.13

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.
Files changed (259) hide show
  1. package/build/src/browser.d.ts +0 -3
  2. package/build/src/browser.d.ts.map +1 -1
  3. package/build/src/browser.js +0 -3
  4. package/build/src/browser.js.map +1 -1
  5. package/build/src/index.d.ts +2 -5
  6. package/build/src/index.d.ts.map +1 -1
  7. package/build/src/index.js +2 -5
  8. package/build/src/index.js.map +1 -1
  9. package/build/src/lib/logging/DefaultLogger.d.ts +14 -0
  10. package/build/src/lib/logging/DefaultLogger.d.ts.map +1 -1
  11. package/build/src/lib/logging/DefaultLogger.js +27 -0
  12. package/build/src/lib/logging/DefaultLogger.js.map +1 -1
  13. package/build/src/lib/logging/index.d.ts +4 -0
  14. package/build/src/lib/logging/index.d.ts.map +1 -0
  15. package/build/src/lib/logging/index.js +10 -0
  16. package/build/src/lib/logging/index.js.map +1 -0
  17. package/build/src/models/ClientCertificate.d.ts +1 -1
  18. package/build/src/models/ClientCertificate.js.map +1 -1
  19. package/build/src/models/RequestConfig.d.ts +1 -1
  20. package/build/src/models/RequestConfig.js.map +1 -1
  21. package/build/src/models/SerializableError.d.ts +1 -1
  22. package/build/src/models/SerializableError.d.ts.map +1 -1
  23. package/build/src/models/SerializableError.js.map +1 -1
  24. package/build/src/proxy/RequestProxy.d.ts.map +1 -1
  25. package/build/src/proxy/RequestProxy.js +2 -2
  26. package/build/src/proxy/RequestProxy.js.map +1 -1
  27. package/build/src/runtime/http-engine/CoreEngine.d.ts +218 -139
  28. package/build/src/runtime/http-engine/CoreEngine.d.ts.map +1 -1
  29. package/build/src/runtime/http-engine/CoreEngine.js +716 -870
  30. package/build/src/runtime/http-engine/CoreEngine.js.map +1 -1
  31. package/build/src/runtime/http-engine/PayloadSupport.d.ts.map +1 -1
  32. package/build/src/runtime/http-engine/PayloadSupport.js +2 -1
  33. package/build/src/runtime/http-engine/PayloadSupport.js.map +1 -1
  34. package/build/src/runtime/http-engine/auth/AuthManager.d.ts +73 -0
  35. package/build/src/runtime/http-engine/auth/AuthManager.d.ts.map +1 -0
  36. package/build/src/runtime/http-engine/auth/AuthManager.js +186 -0
  37. package/build/src/runtime/http-engine/auth/AuthManager.js.map +1 -0
  38. package/build/src/runtime/http-engine/auth/index.d.ts +2 -0
  39. package/build/src/runtime/http-engine/auth/index.d.ts.map +1 -0
  40. package/build/src/runtime/http-engine/auth/index.js +2 -0
  41. package/build/src/runtime/http-engine/auth/index.js.map +1 -0
  42. package/build/src/runtime/http-engine/certificates/CertificateManager.d.ts +11 -0
  43. package/build/src/runtime/http-engine/certificates/CertificateManager.d.ts.map +1 -0
  44. package/build/src/runtime/http-engine/certificates/CertificateManager.js +76 -0
  45. package/build/src/runtime/http-engine/certificates/CertificateManager.js.map +1 -0
  46. package/build/src/runtime/http-engine/certificates/index.d.ts +2 -0
  47. package/build/src/runtime/http-engine/certificates/index.d.ts.map +1 -0
  48. package/build/src/runtime/http-engine/certificates/index.js +2 -0
  49. package/build/src/runtime/http-engine/certificates/index.js.map +1 -0
  50. package/build/src/runtime/http-engine/compression/CompressionManager.d.ts +25 -0
  51. package/build/src/runtime/http-engine/compression/CompressionManager.d.ts.map +1 -0
  52. package/build/src/runtime/http-engine/compression/CompressionManager.js +89 -0
  53. package/build/src/runtime/http-engine/compression/CompressionManager.js.map +1 -0
  54. package/build/src/runtime/http-engine/compression/index.d.ts +2 -0
  55. package/build/src/runtime/http-engine/compression/index.d.ts.map +1 -0
  56. package/build/src/runtime/http-engine/compression/index.js +2 -0
  57. package/build/src/runtime/http-engine/compression/index.js.map +1 -0
  58. package/build/src/runtime/http-engine/connections/ConnectionManager.d.ts +57 -0
  59. package/build/src/runtime/http-engine/connections/ConnectionManager.d.ts.map +1 -0
  60. package/build/src/runtime/http-engine/connections/ConnectionManager.js +78 -0
  61. package/build/src/runtime/http-engine/connections/ConnectionManager.js.map +1 -0
  62. package/build/src/runtime/http-engine/connections/DigestAuthHandler.d.ts +70 -0
  63. package/build/src/runtime/http-engine/connections/DigestAuthHandler.d.ts.map +1 -0
  64. package/build/src/runtime/http-engine/connections/DigestAuthHandler.js +184 -0
  65. package/build/src/runtime/http-engine/connections/DigestAuthHandler.js.map +1 -0
  66. package/build/src/runtime/http-engine/connections/DirectConnection.d.ts +22 -0
  67. package/build/src/runtime/http-engine/connections/DirectConnection.d.ts.map +1 -0
  68. package/build/src/runtime/http-engine/connections/DirectConnection.js +105 -0
  69. package/build/src/runtime/http-engine/connections/DirectConnection.js.map +1 -0
  70. package/build/src/runtime/http-engine/connections/ProxyAuthHandler.d.ts +60 -0
  71. package/build/src/runtime/http-engine/connections/ProxyAuthHandler.d.ts.map +1 -0
  72. package/build/src/runtime/http-engine/connections/ProxyAuthHandler.js +138 -0
  73. package/build/src/runtime/http-engine/connections/ProxyAuthHandler.js.map +1 -0
  74. package/build/src/runtime/http-engine/connections/ProxyConnection.d.ts +14 -0
  75. package/build/src/runtime/http-engine/connections/ProxyConnection.d.ts.map +1 -0
  76. package/build/src/runtime/http-engine/connections/ProxyConnection.js +47 -0
  77. package/build/src/runtime/http-engine/connections/ProxyConnection.js.map +1 -0
  78. package/build/src/runtime/http-engine/connections/TunnelConnection.d.ts +13 -0
  79. package/build/src/runtime/http-engine/connections/TunnelConnection.d.ts.map +1 -0
  80. package/build/src/runtime/http-engine/connections/TunnelConnection.js +175 -0
  81. package/build/src/runtime/http-engine/connections/TunnelConnection.js.map +1 -0
  82. package/build/src/runtime/http-engine/connections/index.d.ts +7 -0
  83. package/build/src/runtime/http-engine/connections/index.d.ts.map +1 -0
  84. package/build/src/runtime/http-engine/connections/index.js +7 -0
  85. package/build/src/runtime/http-engine/connections/index.js.map +1 -0
  86. package/build/src/runtime/http-engine/constants.d.ts +69 -0
  87. package/build/src/runtime/http-engine/constants.d.ts.map +1 -0
  88. package/build/src/runtime/http-engine/constants.js +90 -0
  89. package/build/src/runtime/http-engine/constants.js.map +1 -0
  90. package/build/src/runtime/http-engine/cookies/CookieProcessor.d.ts +5 -0
  91. package/build/src/runtime/http-engine/cookies/CookieProcessor.d.ts.map +1 -0
  92. package/build/src/runtime/http-engine/cookies/CookieProcessor.js +20 -0
  93. package/build/src/runtime/http-engine/cookies/CookieProcessor.js.map +1 -0
  94. package/build/src/runtime/http-engine/cookies/index.d.ts +2 -0
  95. package/build/src/runtime/http-engine/cookies/index.d.ts.map +1 -0
  96. package/build/src/runtime/http-engine/cookies/index.js +2 -0
  97. package/build/src/runtime/http-engine/cookies/index.js.map +1 -0
  98. package/build/src/runtime/http-engine/errors/HttpEngineErrors.d.ts +156 -0
  99. package/build/src/runtime/http-engine/errors/HttpEngineErrors.d.ts.map +1 -0
  100. package/build/src/runtime/http-engine/errors/HttpEngineErrors.js +227 -0
  101. package/build/src/runtime/http-engine/errors/HttpEngineErrors.js.map +1 -0
  102. package/build/src/runtime/http-engine/errors/index.d.ts +2 -0
  103. package/build/src/runtime/http-engine/errors/index.d.ts.map +1 -0
  104. package/build/src/runtime/http-engine/errors/index.js +2 -0
  105. package/build/src/runtime/http-engine/errors/index.js.map +1 -0
  106. package/build/src/runtime/http-engine/message/MessageBuilder.d.ts +66 -0
  107. package/build/src/runtime/http-engine/message/MessageBuilder.d.ts.map +1 -0
  108. package/build/src/runtime/http-engine/message/MessageBuilder.js +161 -0
  109. package/build/src/runtime/http-engine/message/MessageBuilder.js.map +1 -0
  110. package/build/src/runtime/http-engine/message/MessageProcessor.d.ts +27 -0
  111. package/build/src/runtime/http-engine/message/MessageProcessor.d.ts.map +1 -0
  112. package/build/src/runtime/http-engine/message/MessageProcessor.js +51 -0
  113. package/build/src/runtime/http-engine/message/MessageProcessor.js.map +1 -0
  114. package/build/src/runtime/http-engine/message/index.d.ts +3 -0
  115. package/build/src/runtime/http-engine/message/index.d.ts.map +1 -0
  116. package/build/src/runtime/http-engine/message/index.js +3 -0
  117. package/build/src/runtime/http-engine/message/index.js.map +1 -0
  118. package/build/src/runtime/http-engine/ntlm/NtlmAuth.d.ts +2 -8
  119. package/build/src/runtime/http-engine/ntlm/NtlmAuth.d.ts.map +1 -1
  120. package/build/src/runtime/http-engine/ntlm/NtlmAuth.js +11 -5
  121. package/build/src/runtime/http-engine/ntlm/NtlmAuth.js.map +1 -1
  122. package/build/src/runtime/http-engine/ntlm/NtlmMessage.js +6 -6
  123. package/build/src/runtime/http-engine/ntlm/NtlmMessage.js.map +1 -1
  124. package/build/src/runtime/http-engine/parsers/BodyParser.d.ts +39 -0
  125. package/build/src/runtime/http-engine/parsers/BodyParser.d.ts.map +1 -0
  126. package/build/src/runtime/http-engine/parsers/BodyParser.js +145 -0
  127. package/build/src/runtime/http-engine/parsers/BodyParser.js.map +1 -0
  128. package/build/src/runtime/http-engine/parsers/HeadersParser.d.ts +29 -0
  129. package/build/src/runtime/http-engine/parsers/HeadersParser.d.ts.map +1 -0
  130. package/build/src/runtime/http-engine/parsers/HeadersParser.js +88 -0
  131. package/build/src/runtime/http-engine/parsers/HeadersParser.js.map +1 -0
  132. package/build/src/runtime/http-engine/parsers/HttpResponseParser.d.ts +91 -0
  133. package/build/src/runtime/http-engine/parsers/HttpResponseParser.d.ts.map +1 -0
  134. package/build/src/runtime/http-engine/parsers/HttpResponseParser.js +236 -0
  135. package/build/src/runtime/http-engine/parsers/HttpResponseParser.js.map +1 -0
  136. package/build/src/runtime/http-engine/parsers/StatusParser.d.ts +20 -0
  137. package/build/src/runtime/http-engine/parsers/StatusParser.d.ts.map +1 -0
  138. package/build/src/runtime/http-engine/parsers/StatusParser.js +51 -0
  139. package/build/src/runtime/http-engine/parsers/StatusParser.js.map +1 -0
  140. package/build/src/runtime/http-engine/parsers/index.d.ts +5 -0
  141. package/build/src/runtime/http-engine/parsers/index.d.ts.map +1 -0
  142. package/build/src/runtime/http-engine/parsers/index.js +5 -0
  143. package/build/src/runtime/http-engine/parsers/index.js.map +1 -0
  144. package/build/src/runtime/http-engine/response/ResponseProcessor.d.ts +22 -0
  145. package/build/src/runtime/http-engine/response/ResponseProcessor.d.ts.map +1 -0
  146. package/build/src/runtime/http-engine/response/ResponseProcessor.js +25 -0
  147. package/build/src/runtime/http-engine/response/ResponseProcessor.js.map +1 -0
  148. package/build/src/runtime/http-engine/response/index.d.ts +2 -0
  149. package/build/src/runtime/http-engine/response/index.d.ts.map +1 -0
  150. package/build/src/runtime/http-engine/response/index.js +2 -0
  151. package/build/src/runtime/http-engine/response/index.js.map +1 -0
  152. package/build/src/runtime/http-engine/statistics/StatisticsProcessor.d.ts +7 -0
  153. package/build/src/runtime/http-engine/statistics/StatisticsProcessor.d.ts.map +1 -0
  154. package/build/src/runtime/http-engine/statistics/StatisticsProcessor.js +40 -0
  155. package/build/src/runtime/http-engine/statistics/StatisticsProcessor.js.map +1 -0
  156. package/build/src/runtime/http-engine/statistics/index.d.ts +2 -0
  157. package/build/src/runtime/http-engine/statistics/index.d.ts.map +1 -0
  158. package/build/src/runtime/http-engine/statistics/index.js +2 -0
  159. package/build/src/runtime/http-engine/statistics/index.js.map +1 -0
  160. package/build/src/runtime/http-engine/url/UrlProcessor.d.ts +24 -0
  161. package/build/src/runtime/http-engine/url/UrlProcessor.d.ts.map +1 -0
  162. package/build/src/runtime/http-engine/url/UrlProcessor.js +50 -0
  163. package/build/src/runtime/http-engine/url/UrlProcessor.js.map +1 -0
  164. package/build/src/runtime/http-engine/url/index.d.ts +2 -0
  165. package/build/src/runtime/http-engine/url/index.d.ts.map +1 -0
  166. package/build/src/runtime/http-engine/url/index.js +2 -0
  167. package/build/src/runtime/http-engine/url/index.js.map +1 -0
  168. package/build/src/runtime/http-runner/HttpRequestRunner.d.ts +3 -3
  169. package/build/src/runtime/http-runner/HttpRequestRunner.d.ts.map +1 -1
  170. package/build/src/runtime/http-runner/HttpRequestRunner.js.map +1 -1
  171. package/build/src/runtime/node/InteropInterfaces.d.ts +3 -3
  172. package/build/src/runtime/node/InteropInterfaces.d.ts.map +1 -1
  173. package/build/src/runtime/node/InteropInterfaces.js.map +1 -1
  174. package/build/src/runtime/node/ProjectRequestRunner.d.ts +2 -2
  175. package/build/src/runtime/node/ProjectRequestRunner.d.ts.map +1 -1
  176. package/build/src/runtime/node/ProjectRequestRunner.js.map +1 -1
  177. package/build/src/runtime/node/ProjectRunner.d.ts.map +1 -1
  178. package/build/src/runtime/node/ProjectRunner.js +2 -2
  179. package/build/src/runtime/node/ProjectRunner.js.map +1 -1
  180. package/build/tsconfig.tsbuildinfo +1 -1
  181. package/data/models/example-generator-api.json +6 -6
  182. package/package.json +2 -2
  183. package/src/lib/logging/DefaultLogger.ts +32 -0
  184. package/src/models/ClientCertificate.ts +1 -1
  185. package/src/models/RequestConfig.ts +1 -1
  186. package/src/models/SerializableError.ts +1 -1
  187. package/src/proxy/RequestProxy.ts +2 -2
  188. package/src/runtime/http-engine/CoreEngine.ts +858 -893
  189. package/src/runtime/http-engine/PayloadSupport.ts +2 -1
  190. package/src/runtime/http-engine/auth/AuthManager.ts +242 -0
  191. package/src/runtime/http-engine/certificates/CertificateManager.ts +74 -0
  192. package/src/runtime/http-engine/compression/CompressionManager.ts +99 -0
  193. package/src/runtime/http-engine/connections/ConnectionManager.ts +123 -0
  194. package/src/runtime/http-engine/connections/DigestAuthHandler.ts +238 -0
  195. package/src/runtime/http-engine/connections/DirectConnection.ts +134 -0
  196. package/src/runtime/http-engine/connections/ProxyAuthHandler.ts +179 -0
  197. package/src/runtime/http-engine/connections/ProxyConnection.ts +55 -0
  198. package/src/runtime/http-engine/connections/TunnelConnection.ts +192 -0
  199. package/src/runtime/http-engine/constants.ts +103 -0
  200. package/src/runtime/http-engine/cookies/CookieProcessor.ts +25 -0
  201. package/src/runtime/http-engine/errors/HttpEngineErrors.ts +319 -0
  202. package/src/runtime/http-engine/message/MessageBuilder.ts +201 -0
  203. package/src/runtime/http-engine/message/MessageProcessor.ts +73 -0
  204. package/src/runtime/http-engine/ntlm/NtlmAuth.ts +16 -13
  205. package/src/runtime/http-engine/ntlm/NtlmMessage.ts +6 -6
  206. package/src/runtime/http-engine/parsers/BodyParser.ts +171 -0
  207. package/src/runtime/http-engine/parsers/HeadersParser.ts +103 -0
  208. package/src/runtime/http-engine/parsers/HttpResponseParser.ts +280 -0
  209. package/src/runtime/http-engine/parsers/StatusParser.ts +69 -0
  210. package/src/runtime/http-engine/response/ResponseProcessor.ts +46 -0
  211. package/src/runtime/http-engine/statistics/StatisticsProcessor.ts +52 -0
  212. package/src/runtime/http-engine/url/UrlProcessor.ts +55 -0
  213. package/src/runtime/http-runner/HttpRequestRunner.ts +3 -3
  214. package/src/runtime/node/InteropInterfaces.ts +3 -3
  215. package/src/runtime/node/ProjectRequestRunner.ts +2 -2
  216. package/src/runtime/node/ProjectRunner.ts +2 -2
  217. package/tests/servers/ProxyServer.ts +32 -19
  218. package/tests/servers/express-routes/ApiEndpoint.ts +24 -0
  219. package/tests/servers/express-routes/BasicAuthRoute.ts +36 -0
  220. package/tests/servers/express-routes/BearerAuthRoute.ts +35 -0
  221. package/tests/servers/express-routes/NTLMRoute.ts +2 -3
  222. package/tests/servers/express-routes/PostApi.ts +15 -2
  223. package/tests/servers/express-routes/RedirectsApi.ts +12 -1
  224. package/tests/servers/express-routes/ResponsesApi.ts +1 -1
  225. package/tests/servers/express-routes/StreamApi.ts +19 -0
  226. package/tests/servers/oauth2mock/ServerMock.js +1 -1
  227. package/tests/unit/runtime/http-engine/HttpResponseParser.spec.ts +337 -0
  228. package/tests/unit/runtime/http-engine/abort.spec.ts +4 -5
  229. package/tests/unit/runtime/http-engine/auth.spec.ts +7 -58
  230. package/tests/unit/runtime/http-engine/certificates/CertificateManager.spec.ts +482 -0
  231. package/tests/unit/runtime/http-engine/certificates.spec.ts +2 -2
  232. package/tests/unit/runtime/http-engine/compression/CompressionManager.spec.ts +498 -0
  233. package/tests/unit/runtime/http-engine/compression.spec.ts +3 -72
  234. package/tests/unit/runtime/http-engine/connections/ConnectionManager.spec.ts +379 -0
  235. package/tests/unit/runtime/http-engine/connections/DigestAuthHandler.spec.ts +164 -0
  236. package/tests/unit/runtime/http-engine/core_engine.spec.ts +561 -0
  237. package/tests/unit/runtime/http-engine/engine_statuses.spec.ts +2 -2
  238. package/tests/unit/runtime/http-engine/events.spec.ts +2 -2
  239. package/tests/unit/runtime/http-engine/headers.spec.ts +2 -88
  240. package/tests/unit/runtime/http-engine/hosts.spec.ts +2 -2
  241. package/tests/unit/runtime/http-engine/http-get.spec.ts +2 -2
  242. package/tests/unit/runtime/http-engine/http-post.spec.ts +2 -2
  243. package/tests/unit/runtime/http-engine/logger.spec.ts +0 -8
  244. package/tests/unit/runtime/http-engine/message.spec.ts +2 -194
  245. package/tests/unit/runtime/http-engine/params.spec.ts +4 -4
  246. package/tests/unit/runtime/http-engine/proxy.spec.ts +15 -14
  247. package/tests/unit/runtime/http-engine/redirects.spec.ts +2 -2
  248. package/tests/unit/runtime/http-engine/responses.spec.ts +170 -277
  249. package/tests/unit/runtime/http-engine/timeout.spec.ts +3 -3
  250. package/tests/unit/runtime/http-engine/timings.spec.ts +2 -2
  251. package/tests/unit/runtime/proxy/HttpProjectProxy.spec.ts +25 -28
  252. package/tests/unit/runtime/runners/project_runner.spec.ts +2 -2
  253. package/tests/unit/runtime/runners/request_runner.spec.ts +2 -2
  254. package/build/src/runtime/http-engine/HttpEngine.d.ts +0 -311
  255. package/build/src/runtime/http-engine/HttpEngine.d.ts.map +0 -1
  256. package/build/src/runtime/http-engine/HttpEngine.js +0 -802
  257. package/build/src/runtime/http-engine/HttpEngine.js.map +0 -1
  258. package/src/runtime/http-engine/HttpEngine.ts +0 -952
  259. package/tests/unit/runtime/http-engine/connecting.spec.ts +0 -140
@@ -0,0 +1,184 @@
1
+ import crypto from 'node:crypto';
2
+ /**
3
+ * Handles HTTP Digest authentication according to RFC 2617
4
+ */
5
+ export class DigestAuthHandler {
6
+ logger;
7
+ username;
8
+ password;
9
+ nc = 1;
10
+ cnonce;
11
+ constructor(username, password, logger) {
12
+ this.username = username;
13
+ this.password = password;
14
+ this.logger = logger;
15
+ this.cnonce = this.generateCnonce();
16
+ }
17
+ /**
18
+ * Parse a WWW-Authenticate or Proxy-Authenticate header
19
+ */
20
+ parseChallenge(authenticateHeader) {
21
+ const challenge = { realm: '', nonce: '' };
22
+ // Extract the method (Digest)
23
+ const methodMatch = authenticateHeader.match(/^(\w+)/);
24
+ if (!methodMatch || methodMatch[1].toLowerCase() !== 'digest') {
25
+ throw new Error('Not a Digest authentication challenge');
26
+ }
27
+ // Parse key-value pairs (both quoted and unquoted)
28
+ const paramRegex = /(\w+)=(?:"([^"]*)"|([^,\s]+))/g;
29
+ let match;
30
+ while ((match = paramRegex.exec(authenticateHeader)) !== null) {
31
+ const [, key, quotedValue, unquotedValue] = match;
32
+ const value = quotedValue !== undefined ? quotedValue : unquotedValue;
33
+ switch (key.toLowerCase()) {
34
+ case 'realm':
35
+ challenge.realm = value;
36
+ break;
37
+ case 'nonce':
38
+ challenge.nonce = value;
39
+ break;
40
+ case 'qop':
41
+ challenge.qop = value;
42
+ break;
43
+ case 'algorithm':
44
+ challenge.algorithm = value;
45
+ break;
46
+ case 'opaque':
47
+ challenge.opaque = value;
48
+ break;
49
+ case 'stale':
50
+ challenge.stale = value;
51
+ break;
52
+ case 'domain':
53
+ challenge.domain = value;
54
+ break;
55
+ }
56
+ }
57
+ // Validate required fields
58
+ if (!challenge.realm || !challenge.nonce) {
59
+ throw new Error('Invalid Digest challenge: missing realm or nonce');
60
+ }
61
+ this.logger.debug('Parsed Digest challenge:', challenge);
62
+ return challenge;
63
+ }
64
+ /**
65
+ * Generate a Digest authentication response
66
+ */
67
+ generateResponse(challenge, method, uri) {
68
+ const algorithm = challenge.algorithm?.toLowerCase() || 'md5';
69
+ const qop = challenge.qop?.toLowerCase();
70
+ // Generate HA1 = MD5(username:realm:password)
71
+ const ha1 = this.calculateHA1(challenge.realm, algorithm);
72
+ // Generate HA2 = MD5(method:uri)
73
+ const ha2 = this.calculateHA2(method, uri, algorithm);
74
+ let response;
75
+ if (qop) {
76
+ // With quality of protection
77
+ const nc = this.formatNC(this.nc);
78
+ const cnonce = this.cnonce;
79
+ if (qop === 'auth') {
80
+ // response = MD5(HA1:nonce:nc:cnonce:qop:HA2)
81
+ const responseInput = `${ha1}:${challenge.nonce}:${nc}:${cnonce}:${qop}:${ha2}`;
82
+ response = crypto.createHash(algorithm).update(responseInput).digest('hex');
83
+ }
84
+ else {
85
+ throw new Error(`Unsupported qop value: ${qop}`);
86
+ }
87
+ }
88
+ else {
89
+ // Without quality of protection
90
+ // response = MD5(HA1:nonce:HA2)
91
+ const responseInput = `${ha1}:${challenge.nonce}:${ha2}`;
92
+ response = crypto.createHash(algorithm).update(responseInput).digest('hex');
93
+ }
94
+ // Build the response header
95
+ const responseParams = {
96
+ username: this.username,
97
+ realm: challenge.realm,
98
+ nonce: challenge.nonce,
99
+ uri,
100
+ response,
101
+ };
102
+ if (challenge.algorithm) {
103
+ responseParams.algorithm = challenge.algorithm;
104
+ }
105
+ if (challenge.opaque) {
106
+ responseParams.opaque = challenge.opaque;
107
+ }
108
+ if (qop) {
109
+ responseParams.qop = qop;
110
+ responseParams.nc = this.formatNC(this.nc);
111
+ responseParams.cnonce = this.cnonce;
112
+ }
113
+ const responseHeader = this.buildResponseHeader(responseParams);
114
+ this.logger.debug('Generated Digest response:', responseHeader);
115
+ // Increment nonce count for next request
116
+ this.nc++;
117
+ return responseHeader;
118
+ }
119
+ /**
120
+ * Calculate HA1 = MD5(username:realm:password)
121
+ */
122
+ calculateHA1(realm, algorithm) {
123
+ const input = `${this.username}:${realm}:${this.password}`;
124
+ return crypto.createHash(algorithm).update(input).digest('hex');
125
+ }
126
+ /**
127
+ * Calculate HA2 = MD5(method:uri)
128
+ */
129
+ calculateHA2(method, uri, algorithm) {
130
+ const input = `${method}:${uri}`;
131
+ return crypto.createHash(algorithm).update(input).digest('hex');
132
+ }
133
+ /**
134
+ * Generate a client nonce
135
+ */
136
+ generateCnonce() {
137
+ return crypto.randomBytes(16).toString('hex');
138
+ }
139
+ /**
140
+ * Format nonce count as 8-digit hex string
141
+ */
142
+ formatNC(nc) {
143
+ return nc.toString(16).padStart(8, '0');
144
+ }
145
+ /**
146
+ * Build the Authorization header string
147
+ */
148
+ buildResponseHeader(params) {
149
+ const parts = ['Digest'];
150
+ // Add required parameters
151
+ parts.push(`username="${params.username}"`);
152
+ parts.push(`realm="${params.realm}"`);
153
+ parts.push(`nonce="${params.nonce}"`);
154
+ parts.push(`uri="${params.uri}"`);
155
+ parts.push(`response="${params.response}"`);
156
+ // Add optional parameters
157
+ if (params.algorithm) {
158
+ parts.push(`algorithm="${params.algorithm}"`);
159
+ }
160
+ if (params.opaque) {
161
+ parts.push(`opaque="${params.opaque}"`);
162
+ }
163
+ if (params.qop) {
164
+ parts.push(`qop="${params.qop}"`);
165
+ parts.push(`nc="${params.nc}"`);
166
+ parts.push(`cnonce="${params.cnonce}"`);
167
+ }
168
+ return parts.join(', ');
169
+ }
170
+ /**
171
+ * Reset the nonce count (useful for new sessions)
172
+ */
173
+ reset() {
174
+ this.nc = 1;
175
+ this.cnonce = this.generateCnonce();
176
+ }
177
+ /**
178
+ * Check if a challenge is stale
179
+ */
180
+ isStale(challenge) {
181
+ return challenge.stale === 'true';
182
+ }
183
+ }
184
+ //# sourceMappingURL=DigestAuthHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DigestAuthHandler.js","sourceRoot":"","sources":["../../../../../src/runtime/http-engine/connections/DigestAuthHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from 'node:crypto'\nimport { type Logger, type ILogObj } from '../../../lib/logging/index.js'\n\nexport interface DigestChallenge {\n realm: string\n nonce: string\n qop?: string\n algorithm?: string\n opaque?: string\n stale?: string\n domain?: string\n}\n\nexport interface DigestResponse {\n username: string\n realm: string\n nonce: string\n uri: string\n response: string\n qop?: string\n nc?: string\n cnonce?: string\n algorithm?: string\n opaque?: string\n}\n\n/**\n * Handles HTTP Digest authentication according to RFC 2617\n */\nexport class DigestAuthHandler {\n private logger: Logger<ILogObj>\n private username: string\n private password: string\n private nc = 1\n private cnonce: string\n\n constructor(username: string, password: string, logger: Logger<ILogObj>) {\n this.username = username\n this.password = password\n this.logger = logger\n this.cnonce = this.generateCnonce()\n }\n\n /**\n * Parse a WWW-Authenticate or Proxy-Authenticate header\n */\n parseChallenge(authenticateHeader: string): DigestChallenge {\n const challenge: DigestChallenge = { realm: '', nonce: '' }\n\n // Extract the method (Digest)\n const methodMatch = authenticateHeader.match(/^(\\w+)/)\n if (!methodMatch || methodMatch[1].toLowerCase() !== 'digest') {\n throw new Error('Not a Digest authentication challenge')\n }\n\n // Parse key-value pairs (both quoted and unquoted)\n const paramRegex = /(\\w+)=(?:\"([^\"]*)\"|([^,\\s]+))/g\n let match\n while ((match = paramRegex.exec(authenticateHeader)) !== null) {\n const [, key, quotedValue, unquotedValue] = match\n const value = quotedValue !== undefined ? quotedValue : unquotedValue\n\n switch (key.toLowerCase()) {\n case 'realm':\n challenge.realm = value\n break\n case 'nonce':\n challenge.nonce = value\n break\n case 'qop':\n challenge.qop = value\n break\n case 'algorithm':\n challenge.algorithm = value\n break\n case 'opaque':\n challenge.opaque = value\n break\n case 'stale':\n challenge.stale = value\n break\n case 'domain':\n challenge.domain = value\n break\n }\n }\n\n // Validate required fields\n if (!challenge.realm || !challenge.nonce) {\n throw new Error('Invalid Digest challenge: missing realm or nonce')\n }\n\n this.logger.debug('Parsed Digest challenge:', challenge)\n return challenge\n }\n\n /**\n * Generate a Digest authentication response\n */\n generateResponse(challenge: DigestChallenge, method: string, uri: string): string {\n const algorithm = challenge.algorithm?.toLowerCase() || 'md5'\n const qop = challenge.qop?.toLowerCase()\n\n // Generate HA1 = MD5(username:realm:password)\n const ha1 = this.calculateHA1(challenge.realm, algorithm)\n\n // Generate HA2 = MD5(method:uri)\n const ha2 = this.calculateHA2(method, uri, algorithm)\n\n let response: string\n\n if (qop) {\n // With quality of protection\n const nc = this.formatNC(this.nc)\n const cnonce = this.cnonce\n\n if (qop === 'auth') {\n // response = MD5(HA1:nonce:nc:cnonce:qop:HA2)\n const responseInput = `${ha1}:${challenge.nonce}:${nc}:${cnonce}:${qop}:${ha2}`\n response = crypto.createHash(algorithm).update(responseInput).digest('hex')\n } else {\n throw new Error(`Unsupported qop value: ${qop}`)\n }\n } else {\n // Without quality of protection\n // response = MD5(HA1:nonce:HA2)\n const responseInput = `${ha1}:${challenge.nonce}:${ha2}`\n response = crypto.createHash(algorithm).update(responseInput).digest('hex')\n }\n\n // Build the response header\n const responseParams: DigestResponse = {\n username: this.username,\n realm: challenge.realm,\n nonce: challenge.nonce,\n uri,\n response,\n }\n\n if (challenge.algorithm) {\n responseParams.algorithm = challenge.algorithm\n }\n\n if (challenge.opaque) {\n responseParams.opaque = challenge.opaque\n }\n\n if (qop) {\n responseParams.qop = qop\n responseParams.nc = this.formatNC(this.nc)\n responseParams.cnonce = this.cnonce\n }\n\n const responseHeader = this.buildResponseHeader(responseParams)\n this.logger.debug('Generated Digest response:', responseHeader)\n\n // Increment nonce count for next request\n this.nc++\n\n return responseHeader\n }\n\n /**\n * Calculate HA1 = MD5(username:realm:password)\n */\n private calculateHA1(realm: string, algorithm: string): string {\n const input = `${this.username}:${realm}:${this.password}`\n return crypto.createHash(algorithm).update(input).digest('hex')\n }\n\n /**\n * Calculate HA2 = MD5(method:uri)\n */\n private calculateHA2(method: string, uri: string, algorithm: string): string {\n const input = `${method}:${uri}`\n return crypto.createHash(algorithm).update(input).digest('hex')\n }\n\n /**\n * Generate a client nonce\n */\n private generateCnonce(): string {\n return crypto.randomBytes(16).toString('hex')\n }\n\n /**\n * Format nonce count as 8-digit hex string\n */\n private formatNC(nc: number): string {\n return nc.toString(16).padStart(8, '0')\n }\n\n /**\n * Build the Authorization header string\n */\n private buildResponseHeader(params: DigestResponse): string {\n const parts: string[] = ['Digest']\n\n // Add required parameters\n parts.push(`username=\"${params.username}\"`)\n parts.push(`realm=\"${params.realm}\"`)\n parts.push(`nonce=\"${params.nonce}\"`)\n parts.push(`uri=\"${params.uri}\"`)\n parts.push(`response=\"${params.response}\"`)\n\n // Add optional parameters\n if (params.algorithm) {\n parts.push(`algorithm=\"${params.algorithm}\"`)\n }\n\n if (params.opaque) {\n parts.push(`opaque=\"${params.opaque}\"`)\n }\n\n if (params.qop) {\n parts.push(`qop=\"${params.qop}\"`)\n parts.push(`nc=\"${params.nc}\"`)\n parts.push(`cnonce=\"${params.cnonce}\"`)\n }\n\n return parts.join(', ')\n }\n\n /**\n * Reset the nonce count (useful for new sessions)\n */\n reset(): void {\n this.nc = 1\n this.cnonce = this.generateCnonce()\n }\n\n /**\n * Check if a challenge is stale\n */\n isStale(challenge: DigestChallenge): boolean {\n return challenge.stale === 'true'\n }\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import net from 'net';
2
+ import { ConnectionOptions } from './ConnectionManager.js';
3
+ /**
4
+ * Handles direct HTTP and HTTPS connections
5
+ */
6
+ export declare class DirectConnection {
7
+ private options;
8
+ constructor(options: ConnectionOptions);
9
+ /**
10
+ * Establish a connection to the target host
11
+ */
12
+ connect(): Promise<net.Socket>;
13
+ /**
14
+ * Create a TCP connection for HTTP
15
+ */
16
+ private createTcpConnection;
17
+ /**
18
+ * Create a TLS connection for HTTPS
19
+ */
20
+ private createTlsConnection;
21
+ }
22
+ //# sourceMappingURL=DirectConnection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectConnection.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/http-engine/connections/DirectConnection.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AAErB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAM1D;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAmB;gBAEtB,OAAO,EAAE,iBAAiB;IAItC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;IAmBpC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA8B3B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAyD5B"}
@@ -0,0 +1,105 @@
1
+ import net from 'net';
2
+ import tls from 'tls';
3
+ import { addClientCertificate, checkServerIdentity } from '../certificates/index.js';
4
+ /**
5
+ * Handles direct HTTP and HTTPS connections
6
+ */
7
+ export class DirectConnection {
8
+ options;
9
+ constructor(options) {
10
+ this.options = options;
11
+ }
12
+ /**
13
+ * Establish a connection to the target host
14
+ */
15
+ async connect() {
16
+ const { host, port, timeout, validateCertificates, certificates, logger, stats } = this.options;
17
+ let socket;
18
+ // Check if this is an HTTPS connection based on port or protocol
19
+ const isHttps = port === 443 || port === 8443 || this.options.protocol === 'https:';
20
+ if (isHttps) {
21
+ socket = await this.createTlsConnection(host, port, validateCertificates, certificates, logger, stats);
22
+ }
23
+ else {
24
+ socket = await this.createTcpConnection(host, port, logger, stats);
25
+ }
26
+ if (timeout && timeout > 0) {
27
+ socket.setTimeout(timeout);
28
+ }
29
+ return socket;
30
+ }
31
+ /**
32
+ * Create a TCP connection for HTTP
33
+ */
34
+ createTcpConnection(host, port, logger, stats) {
35
+ logger.debug(`Opening HTTP connection to ${host} on port ${port}`);
36
+ return new Promise((resolve, reject) => {
37
+ stats.connectionTime = Date.now();
38
+ const isIp = net.isIP(host);
39
+ if (isIp) {
40
+ stats.lookupTime = Date.now();
41
+ }
42
+ const client = net.createConnection(port, host, () => {
43
+ stats.connectedTime = Date.now();
44
+ logger.debug('HTTP connection established.');
45
+ resolve(client);
46
+ });
47
+ client.pause();
48
+ if (!isIp) {
49
+ client.once('lookup', () => {
50
+ stats.lookupTime = Date.now();
51
+ });
52
+ }
53
+ client.once('error', (err) => reject(err));
54
+ });
55
+ }
56
+ /**
57
+ * Create a TLS connection for HTTPS
58
+ */
59
+ createTlsConnection(host, port, validateCertificates, certificates, logger, stats) {
60
+ logger.debug('Opening an SSL connection...');
61
+ const options = {};
62
+ const isIp = net.isIP(host);
63
+ if (!isIp) {
64
+ options.servername = host;
65
+ }
66
+ if (validateCertificates) {
67
+ options.checkServerIdentity = (hostname, cert) => checkServerIdentity(hostname, cert);
68
+ }
69
+ else {
70
+ options.rejectUnauthorized = false;
71
+ options.checkServerIdentity = () => {
72
+ return undefined;
73
+ };
74
+ }
75
+ // Add client certificates if provided
76
+ if (Array.isArray(certificates)) {
77
+ certificates.forEach((cert) => addClientCertificate(cert, options));
78
+ }
79
+ return new Promise((resolve, reject) => {
80
+ const time = Date.now();
81
+ stats.connectionTime = time;
82
+ if (isIp) {
83
+ stats.lookupTime = time;
84
+ }
85
+ const client = tls.connect(port, host, options, () => {
86
+ logger.debug('SSL connection established.');
87
+ const connectTime = Date.now();
88
+ stats.connectedTime = connectTime;
89
+ stats.secureStartTime = connectTime;
90
+ resolve(client);
91
+ });
92
+ client.pause();
93
+ client.once('error', (e) => reject(e));
94
+ if (!isIp) {
95
+ client.once('lookup', () => {
96
+ stats.lookupTime = Date.now();
97
+ });
98
+ }
99
+ client.once('secureConnect', () => {
100
+ stats.secureConnectedTime = Date.now();
101
+ });
102
+ });
103
+ }
104
+ }
105
+ //# sourceMappingURL=DirectConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectConnection.js","sourceRoot":"","sources":["../../../../../src/runtime/http-engine/connections/DirectConnection.ts"],"names":[],"mappings":"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","sourcesContent":["import net from 'net'\nimport tls from 'tls'\nimport { ConnectionOptions } from './ConnectionManager.js'\nimport type { HttpCertificate } from '../../../models/ClientCertificate.js'\nimport { addClientCertificate, checkServerIdentity } from '../certificates/index.js'\nimport { type Logger, type ILogObj } from '../../../lib/logging/index.js'\nimport type { RequestStats } from '../CoreEngine.js'\n\n/**\n * Handles direct HTTP and HTTPS connections\n */\nexport class DirectConnection {\n private options: ConnectionOptions\n\n constructor(options: ConnectionOptions) {\n this.options = options\n }\n\n /**\n * Establish a connection to the target host\n */\n async connect(): Promise<net.Socket> {\n const { host, port, timeout, validateCertificates, certificates, logger, stats } = this.options\n\n let socket: net.Socket\n // Check if this is an HTTPS connection based on port or protocol\n const isHttps = port === 443 || port === 8443 || this.options.protocol === 'https:'\n if (isHttps) {\n socket = await this.createTlsConnection(host, port, validateCertificates, certificates, logger, stats)\n } else {\n socket = await this.createTcpConnection(host, port, logger, stats)\n }\n\n if (timeout && timeout > 0) {\n socket.setTimeout(timeout)\n }\n\n return socket\n }\n\n /**\n * Create a TCP connection for HTTP\n */\n private createTcpConnection(\n host: string,\n port: number,\n logger: Logger<ILogObj>,\n stats: RequestStats\n ): Promise<net.Socket> {\n logger.debug(`Opening HTTP connection to ${host} on port ${port}`)\n return new Promise((resolve, reject) => {\n stats.connectionTime = Date.now()\n const isIp = net.isIP(host)\n if (isIp) {\n stats.lookupTime = Date.now()\n }\n\n const client = net.createConnection(port, host, () => {\n stats.connectedTime = Date.now()\n logger.debug('HTTP connection established.')\n resolve(client)\n })\n\n client.pause()\n if (!isIp) {\n client.once('lookup', () => {\n stats.lookupTime = Date.now()\n })\n }\n client.once('error', (err: Error) => reject(err))\n })\n }\n\n /**\n * Create a TLS connection for HTTPS\n */\n private createTlsConnection(\n host: string,\n port: number,\n validateCertificates: boolean | undefined,\n certificates: HttpCertificate[] | undefined,\n logger: Logger<ILogObj>,\n stats: RequestStats\n ): Promise<tls.TLSSocket> {\n logger.debug('Opening an SSL connection...')\n const options: tls.ConnectionOptions = {}\n const isIp = net.isIP(host)\n\n if (!isIp) {\n options.servername = host\n }\n\n if (validateCertificates) {\n options.checkServerIdentity = (hostname: string, cert: tls.PeerCertificate) => checkServerIdentity(hostname, cert)\n } else {\n options.rejectUnauthorized = false\n options.checkServerIdentity = (): Error | undefined => {\n return undefined\n }\n }\n\n // Add client certificates if provided\n if (Array.isArray(certificates)) {\n certificates.forEach((cert) => addClientCertificate(cert, options))\n }\n\n return new Promise((resolve, reject) => {\n const time = Date.now()\n stats.connectionTime = time\n if (isIp) {\n stats.lookupTime = time\n }\n\n const client = tls.connect(port, host, options, () => {\n logger.debug('SSL connection established.')\n const connectTime = Date.now()\n stats.connectedTime = connectTime\n stats.secureStartTime = connectTime\n resolve(client)\n })\n\n client.pause()\n client.once('error', (e: Error) => reject(e))\n if (!isIp) {\n client.once('lookup', () => {\n stats.lookupTime = Date.now()\n })\n }\n client.once('secureConnect', () => {\n stats.secureConnectedTime = Date.now()\n })\n })\n }\n}\n"]}
@@ -0,0 +1,60 @@
1
+ import { type Logger, type ILogObj } from '../../../lib/logging/index.js';
2
+ export interface ProxyAuthOptions {
3
+ proxyUsername?: string;
4
+ proxyPassword?: string;
5
+ /**
6
+ * The type of proxy authentication to use.
7
+ */
8
+ proxyAuthorization?: 'Basic';
9
+ logger: Logger<ILogObj>;
10
+ }
11
+ export interface ProxyAuthChallenge {
12
+ method: string;
13
+ realm?: string;
14
+ nonce?: string;
15
+ qop?: string;
16
+ algorithm?: string;
17
+ }
18
+ /**
19
+ * Handles proxy authentication challenges and responses
20
+ */
21
+ export declare class ProxyAuthHandler {
22
+ private options;
23
+ private authState;
24
+ private challenge?;
25
+ private digestHandler?;
26
+ constructor(options: ProxyAuthOptions);
27
+ /**
28
+ * Check if we have proxy credentials configured
29
+ */
30
+ hasCredentials(): boolean;
31
+ /**
32
+ * Generate the initial proxy authorization header
33
+ */
34
+ generateAuthHeader(): string | undefined;
35
+ /**
36
+ * Handle a proxy authentication challenge
37
+ */
38
+ handleChallenge(authenticateHeader: string): string | undefined;
39
+ /**
40
+ * Parse the WWW-Authenticate or Proxy-Authenticate header
41
+ */
42
+ private parseChallenge;
43
+ /**
44
+ * Generate a Digest authentication response
45
+ */
46
+ private generateDigestResponse;
47
+ /**
48
+ * Check if authentication was successful
49
+ */
50
+ isAuthenticated(): boolean;
51
+ /**
52
+ * Mark authentication as successful
53
+ */
54
+ markAuthenticated(): void;
55
+ /**
56
+ * Reset authentication state
57
+ */
58
+ reset(): void;
59
+ }
60
+ //# sourceMappingURL=ProxyAuthHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProxyAuthHandler.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/http-engine/connections/ProxyAuthHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,MAAM,+BAA+B,CAAA;AAGzE,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,SAAS,CAAkD;IACnE,OAAO,CAAC,SAAS,CAAC,CAAoB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAmB;gBAE7B,OAAO,EAAE,gBAAgB;IAOrC;;OAEG;IACH,cAAc,IAAI,OAAO;IAKzB;;OAEG;IACH,kBAAkB,IAAI,MAAM,GAAG,SAAS;IAyBxC;;OAEG;IACH,eAAe,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAgB/D;;OAEG;IACH,OAAO,CAAC,cAAc;IAiCtB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAsB9B;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAIzB;;OAEG;IACH,KAAK,IAAI,IAAI;CAOd"}
@@ -0,0 +1,138 @@
1
+ import { SerializableError } from '../../../models/SerializableError.js';
2
+ import { DigestAuthHandler } from './DigestAuthHandler.js';
3
+ /**
4
+ * Handles proxy authentication challenges and responses
5
+ */
6
+ export class ProxyAuthHandler {
7
+ options;
8
+ authState = 'none';
9
+ challenge;
10
+ digestHandler;
11
+ constructor(options) {
12
+ this.options = options;
13
+ if (options.proxyUsername && options.proxyPassword) {
14
+ this.digestHandler = new DigestAuthHandler(options.proxyUsername, options.proxyPassword, options.logger);
15
+ }
16
+ }
17
+ /**
18
+ * Check if we have proxy credentials configured
19
+ */
20
+ hasCredentials() {
21
+ const { proxyUsername, proxyPassword, proxyAuthorization } = this.options;
22
+ return !!(proxyUsername && proxyPassword) || !!proxyAuthorization;
23
+ }
24
+ /**
25
+ * Generate the initial proxy authorization header
26
+ */
27
+ generateAuthHeader() {
28
+ const { proxyUsername, proxyPassword, proxyAuthorization } = this.options;
29
+ if (!proxyUsername || !proxyPassword) {
30
+ return undefined;
31
+ }
32
+ if (!proxyAuthorization || proxyAuthorization === 'Basic') {
33
+ // Basic authentication
34
+ const token = Buffer.from(`${proxyUsername}:${proxyPassword}`).toString('base64');
35
+ return `Basic ${token}`;
36
+ }
37
+ if (proxyAuthorization === 'Digest') {
38
+ // For Digest auth, we need a challenge first
39
+ if (this.authState === 'none') {
40
+ // Initial request without auth header
41
+ return undefined;
42
+ }
43
+ return this.generateDigestResponse();
44
+ }
45
+ throw new SerializableError(`Unsupported proxy authorization type: ${proxyAuthorization}`);
46
+ }
47
+ /**
48
+ * Handle a proxy authentication challenge
49
+ */
50
+ handleChallenge(authenticateHeader) {
51
+ this.authState = 'challenged';
52
+ this.challenge = this.parseChallenge(authenticateHeader);
53
+ this.options.logger.debug('Received proxy authentication challenge:', this.challenge);
54
+ if (this.challenge?.method === 'Basic') {
55
+ // For Basic auth, we can respond immediately
56
+ return this.generateAuthHeader();
57
+ }
58
+ else if (this.challenge?.method === 'Digest') {
59
+ // For Digest auth, we need to generate a proper response
60
+ return this.generateDigestResponse();
61
+ }
62
+ throw new SerializableError(`Unsupported proxy authentication method: ${this.challenge?.method}`);
63
+ }
64
+ /**
65
+ * Parse the WWW-Authenticate or Proxy-Authenticate header
66
+ */
67
+ parseChallenge(authenticateHeader) {
68
+ const challenge = { method: '' };
69
+ // Extract the method (Basic, Digest, etc.)
70
+ const methodMatch = authenticateHeader.match(/^(\w+)/);
71
+ if (methodMatch) {
72
+ challenge.method = methodMatch[1];
73
+ }
74
+ // Parse key-value pairs
75
+ const paramRegex = /(\w+)="([^"]*)"/g;
76
+ let match;
77
+ while ((match = paramRegex.exec(authenticateHeader)) !== null) {
78
+ const [, key, value] = match;
79
+ switch (key.toLowerCase()) {
80
+ case 'realm':
81
+ challenge.realm = value;
82
+ break;
83
+ case 'nonce':
84
+ challenge.nonce = value;
85
+ break;
86
+ case 'qop':
87
+ challenge.qop = value;
88
+ break;
89
+ case 'algorithm':
90
+ challenge.algorithm = value;
91
+ break;
92
+ }
93
+ }
94
+ return challenge;
95
+ }
96
+ /**
97
+ * Generate a Digest authentication response
98
+ */
99
+ generateDigestResponse() {
100
+ if (!this.digestHandler || !this.challenge) {
101
+ return undefined;
102
+ }
103
+ try {
104
+ // Parse the full Digest challenge
105
+ const digestChallenge = this.digestHandler.parseChallenge(`Digest realm="${this.challenge.realm}", nonce="${this.challenge.nonce}"${this.challenge.qop ? `, qop="${this.challenge.qop}"` : ''}${this.challenge.algorithm ? `, algorithm="${this.challenge.algorithm}"` : ''}`);
106
+ // Generate the response for CONNECT method
107
+ const response = this.digestHandler.generateResponse(digestChallenge, 'CONNECT', '/');
108
+ return response;
109
+ }
110
+ catch (error) {
111
+ this.options.logger.error('Failed to generate Digest response:', error);
112
+ throw new SerializableError(`Digest authentication failed: ${error.message}`, 127);
113
+ }
114
+ }
115
+ /**
116
+ * Check if authentication was successful
117
+ */
118
+ isAuthenticated() {
119
+ return this.authState === 'authenticated';
120
+ }
121
+ /**
122
+ * Mark authentication as successful
123
+ */
124
+ markAuthenticated() {
125
+ this.authState = 'authenticated';
126
+ }
127
+ /**
128
+ * Reset authentication state
129
+ */
130
+ reset() {
131
+ this.authState = 'none';
132
+ this.challenge = undefined;
133
+ if (this.digestHandler) {
134
+ this.digestHandler.reset();
135
+ }
136
+ }
137
+ }
138
+ //# sourceMappingURL=ProxyAuthHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProxyAuthHandler.js","sourceRoot":"","sources":["../../../../../src/runtime/http-engine/connections/ProxyAuthHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { SerializableError } from '../../../models/SerializableError.js'\nimport { type Logger, type ILogObj } from '../../../lib/logging/index.js'\nimport { DigestAuthHandler } from './DigestAuthHandler.js'\n\nexport interface ProxyAuthOptions {\n proxyUsername?: string\n proxyPassword?: string\n /**\n * The type of proxy authentication to use.\n */\n proxyAuthorization?: 'Basic'\n logger: Logger<ILogObj>\n}\n\nexport interface ProxyAuthChallenge {\n method: string\n realm?: string\n nonce?: string\n qop?: string\n algorithm?: string\n}\n\n/**\n * Handles proxy authentication challenges and responses\n */\nexport class ProxyAuthHandler {\n private options: ProxyAuthOptions\n private authState: 'none' | 'challenged' | 'authenticated' = 'none'\n private challenge?: ProxyAuthChallenge\n private digestHandler?: DigestAuthHandler\n\n constructor(options: ProxyAuthOptions) {\n this.options = options\n if (options.proxyUsername && options.proxyPassword) {\n this.digestHandler = new DigestAuthHandler(options.proxyUsername, options.proxyPassword, options.logger)\n }\n }\n\n /**\n * Check if we have proxy credentials configured\n */\n hasCredentials(): boolean {\n const { proxyUsername, proxyPassword, proxyAuthorization } = this.options\n return !!(proxyUsername && proxyPassword) || !!proxyAuthorization\n }\n\n /**\n * Generate the initial proxy authorization header\n */\n generateAuthHeader(): string | undefined {\n const { proxyUsername, proxyPassword, proxyAuthorization } = this.options\n\n if (!proxyUsername || !proxyPassword) {\n return undefined\n }\n\n if (!proxyAuthorization || proxyAuthorization === 'Basic') {\n // Basic authentication\n const token = Buffer.from(`${proxyUsername}:${proxyPassword}`).toString('base64')\n return `Basic ${token}`\n }\n\n if (proxyAuthorization === 'Digest') {\n // For Digest auth, we need a challenge first\n if (this.authState === 'none') {\n // Initial request without auth header\n return undefined\n }\n return this.generateDigestResponse()\n }\n\n throw new SerializableError(`Unsupported proxy authorization type: ${proxyAuthorization}`)\n }\n\n /**\n * Handle a proxy authentication challenge\n */\n handleChallenge(authenticateHeader: string): string | undefined {\n this.authState = 'challenged'\n this.challenge = this.parseChallenge(authenticateHeader)\n this.options.logger.debug('Received proxy authentication challenge:', this.challenge)\n\n if (this.challenge?.method === 'Basic') {\n // For Basic auth, we can respond immediately\n return this.generateAuthHeader()\n } else if (this.challenge?.method === 'Digest') {\n // For Digest auth, we need to generate a proper response\n return this.generateDigestResponse()\n }\n\n throw new SerializableError(`Unsupported proxy authentication method: ${this.challenge?.method}`)\n }\n\n /**\n * Parse the WWW-Authenticate or Proxy-Authenticate header\n */\n private parseChallenge(authenticateHeader: string): ProxyAuthChallenge {\n const challenge: ProxyAuthChallenge = { method: '' }\n\n // Extract the method (Basic, Digest, etc.)\n const methodMatch = authenticateHeader.match(/^(\\w+)/)\n if (methodMatch) {\n challenge.method = methodMatch[1]\n }\n\n // Parse key-value pairs\n const paramRegex = /(\\w+)=\"([^\"]*)\"/g\n let match\n while ((match = paramRegex.exec(authenticateHeader)) !== null) {\n const [, key, value] = match\n switch (key.toLowerCase()) {\n case 'realm':\n challenge.realm = value\n break\n case 'nonce':\n challenge.nonce = value\n break\n case 'qop':\n challenge.qop = value\n break\n case 'algorithm':\n challenge.algorithm = value\n break\n }\n }\n\n return challenge\n }\n\n /**\n * Generate a Digest authentication response\n */\n private generateDigestResponse(): string | undefined {\n if (!this.digestHandler || !this.challenge) {\n return undefined\n }\n\n try {\n // Parse the full Digest challenge\n const digestChallenge = this.digestHandler.parseChallenge(\n `Digest realm=\"${this.challenge.realm}\", nonce=\"${this.challenge.nonce}\"${\n this.challenge.qop ? `, qop=\"${this.challenge.qop}\"` : ''\n }${this.challenge.algorithm ? `, algorithm=\"${this.challenge.algorithm}\"` : ''}`\n )\n\n // Generate the response for CONNECT method\n const response = this.digestHandler.generateResponse(digestChallenge, 'CONNECT', '/')\n return response\n } catch (error) {\n this.options.logger.error('Failed to generate Digest response:', error)\n throw new SerializableError(`Digest authentication failed: ${(error as Error).message}`, 127)\n }\n }\n\n /**\n * Check if authentication was successful\n */\n isAuthenticated(): boolean {\n return this.authState === 'authenticated'\n }\n\n /**\n * Mark authentication as successful\n */\n markAuthenticated(): void {\n this.authState = 'authenticated'\n }\n\n /**\n * Reset authentication state\n */\n reset(): void {\n this.authState = 'none'\n this.challenge = undefined\n if (this.digestHandler) {\n this.digestHandler.reset()\n }\n }\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import net from 'net';
2
+ import { ProxyConnectionOptions } from './ConnectionManager.js';
3
+ /**
4
+ * Handles HTTP requests through a proxy server
5
+ */
6
+ export declare class ProxyConnection {
7
+ private options;
8
+ constructor(options: ProxyConnectionOptions);
9
+ /**
10
+ * Establish a connection to the proxy server
11
+ */
12
+ connect(): Promise<net.Socket>;
13
+ }
14
+ //# sourceMappingURL=ProxyConnection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProxyConnection.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/http-engine/connections/ProxyConnection.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AAErB,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAI/D;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAwB;gBAE3B,OAAO,EAAE,sBAAsB;IAI3C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;CAmCrC"}
@@ -0,0 +1,47 @@
1
+ import { URL } from 'url';
2
+ import { DirectConnection } from './DirectConnection.js';
3
+ import { SerializableError } from '../../../models/SerializableError.js';
4
+ /**
5
+ * Handles HTTP requests through a proxy server
6
+ */
7
+ export class ProxyConnection {
8
+ options;
9
+ constructor(options) {
10
+ this.options = options;
11
+ }
12
+ /**
13
+ * Establish a connection to the proxy server
14
+ */
15
+ async connect() {
16
+ const { proxy, proxyIsSsl, logger } = this.options;
17
+ logger.debug('Proxying an HTTP request...');
18
+ if (!proxy) {
19
+ throw new Error('No proxy configuration found.');
20
+ }
21
+ let proxyUrl = proxy;
22
+ if (proxyIsSsl && !proxyUrl.startsWith('https:')) {
23
+ proxyUrl = `https://${proxyUrl}`;
24
+ }
25
+ else if (!proxyIsSsl && !proxyUrl.startsWith('http:')) {
26
+ proxyUrl = `http://${proxyUrl}`;
27
+ }
28
+ const proxyUri = new URL(proxyUrl);
29
+ const port = Number(proxyUri.port || (proxyIsSsl ? 443 : 80));
30
+ const host = proxyUri.hostname;
31
+ // Create a direct connection to the proxy
32
+ const directConnection = new DirectConnection({
33
+ ...this.options,
34
+ host,
35
+ port,
36
+ protocol: proxyIsSsl ? 'https:' : 'http:',
37
+ });
38
+ try {
39
+ return await directConnection.connect();
40
+ }
41
+ catch (error) {
42
+ const err = error;
43
+ throw new SerializableError(`Failed to connect to proxy: ${err.message}`, err.code ? Number(err.code) : 112);
44
+ }
45
+ }
46
+ }
47
+ //# sourceMappingURL=ProxyConnection.js.map