@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,379 @@
1
+ import { test } from '@japa/runner'
2
+ import net from 'net'
3
+ import {
4
+ ConnectionManager,
5
+ ConnectionOptions,
6
+ ProxyConnectionOptions,
7
+ TunnelConnectionOptions,
8
+ } from '../../../../../src/runtime/http-engine/connections/ConnectionManager.js'
9
+ import { DirectConnection } from '../../../../../src/runtime/http-engine/connections/DirectConnection.js'
10
+ import { ProxyConnection } from '../../../../../src/runtime/http-engine/connections/ProxyConnection.js'
11
+ import { TunnelConnection } from '../../../../../src/runtime/http-engine/connections/TunnelConnection.js'
12
+ import { createLogger, type Logger, type ILogObj } from '../../../../../src/lib/logging/index.js'
13
+ import { type RequestStats, type HttpEngineOptions } from '../../../../../src/runtime/http-engine/CoreEngine.js'
14
+ import { HttpCertificate } from '../../../../../src/models/ClientCertificate.js'
15
+
16
+ test.group('ConnectionManager', (group) => {
17
+ let connectionManager: ConnectionManager
18
+ let logger: Logger<ILogObj>
19
+ let stats: RequestStats
20
+ let createdSockets: net.Socket[] = []
21
+
22
+ group.each.setup(() => {
23
+ logger = createLogger()
24
+ stats = {}
25
+ connectionManager = new ConnectionManager(logger, stats)
26
+ createdSockets = []
27
+ })
28
+
29
+ group.each.teardown(() => {
30
+ // Clean up any sockets created during tests
31
+ for (const socket of createdSockets) {
32
+ if (!socket.destroyed) {
33
+ socket.destroy()
34
+ }
35
+ }
36
+ createdSockets = []
37
+ })
38
+
39
+ test('createDirectConnection should return DirectConnection instance', ({ assert }) => {
40
+ const options = {
41
+ host: 'example.com',
42
+ port: 80,
43
+ protocol: 'http:',
44
+ logger,
45
+ stats,
46
+ }
47
+
48
+ const connection = connectionManager.createDirectConnection(options)
49
+ assert.instanceOf(connection, DirectConnection, 'creates DirectConnection instance')
50
+ })
51
+
52
+ test('createProxyConnection should return ProxyConnection instance', ({ assert }) => {
53
+ const options = {
54
+ host: 'example.com',
55
+ port: 80,
56
+ protocol: 'http:',
57
+ proxy: '127.0.0.1:8080',
58
+ proxyIsSsl: false,
59
+ targetUrl: 'http://example.com:80',
60
+ logger,
61
+ stats,
62
+ }
63
+
64
+ const connection = connectionManager.createProxyConnection(options)
65
+ assert.instanceOf(connection, ProxyConnection, 'creates ProxyConnection instance')
66
+ })
67
+
68
+ test('createTunnelConnection should return TunnelConnection instance', ({ assert }) => {
69
+ const options = {
70
+ host: 'example.com',
71
+ port: 443,
72
+ protocol: 'https:',
73
+ proxy: '127.0.0.1:8080',
74
+ proxyIsSsl: false,
75
+ targetUrl: 'https://example.com:443',
76
+ targetHost: 'example.com',
77
+ targetPort: 443,
78
+ logger,
79
+ stats,
80
+ }
81
+
82
+ const connection = connectionManager.createTunnelConnection(options)
83
+ assert.instanceOf(connection, TunnelConnection, 'creates TunnelConnection instance')
84
+ })
85
+
86
+ test('should create direct connection when no proxy is configured', async ({ assert }) => {
87
+ const mockSocket = new net.Socket()
88
+ createdSockets.push(mockSocket)
89
+
90
+ // Mock DirectConnection.connect to return our mock socket
91
+ const originalCreateDirectConnection = connectionManager.createDirectConnection
92
+ let capturedOptions: ConnectionOptions | undefined
93
+
94
+ connectionManager.createDirectConnection = (options) => {
95
+ capturedOptions = options
96
+ return {
97
+ connect: async () => mockSocket,
98
+ } as DirectConnection
99
+ }
100
+
101
+ const engineOptions: HttpEngineOptions = {
102
+ timeout: 5000,
103
+ validateCertificates: true,
104
+ }
105
+
106
+ const result = await connectionManager.createConnection('example.com', 80, 'http:', engineOptions)
107
+
108
+ assert.deepEqual(result, mockSocket, 'returns the socket from DirectConnection')
109
+ assert.equal(capturedOptions!.host, 'example.com', 'passes correct host')
110
+ assert.equal(capturedOptions!.port, 80, 'passes correct port')
111
+ assert.equal(capturedOptions!.protocol, 'http:', 'passes correct protocol')
112
+ assert.equal(capturedOptions!.timeout, 5000, 'passes timeout option')
113
+ assert.equal(capturedOptions!.validateCertificates, true, 'passes certificate validation option')
114
+ assert.equal(capturedOptions!.logger, logger, 'passes logger')
115
+ assert.equal(capturedOptions!.stats, stats, 'passes stats')
116
+
117
+ // Restore original method
118
+ connectionManager.createDirectConnection = originalCreateDirectConnection
119
+ })
120
+
121
+ test('should create proxy connection for HTTP through proxy', async ({ assert }) => {
122
+ const mockSocket = new net.Socket()
123
+ createdSockets.push(mockSocket)
124
+
125
+ // Mock ProxyConnection.connect to return our mock socket
126
+ const originalCreateProxyConnection = connectionManager.createProxyConnection
127
+ let capturedOptions: ProxyConnectionOptions | undefined
128
+
129
+ connectionManager.createProxyConnection = (options) => {
130
+ capturedOptions = options
131
+ return {
132
+ connect: async () => mockSocket,
133
+ } as ProxyConnection
134
+ }
135
+
136
+ const engineOptions: HttpEngineOptions = {
137
+ proxy: '127.0.0.1:8080',
138
+ timeout: 5000,
139
+ validateCertificates: false,
140
+ proxyUsername: 'user',
141
+ proxyPassword: 'pass',
142
+ proxyAuthorization: 'Basic',
143
+ }
144
+
145
+ const result = await connectionManager.createConnection('example.com', 80, 'http:', engineOptions)
146
+
147
+ assert.equal(result, mockSocket, 'returns the socket from ProxyConnection')
148
+ assert.equal(capturedOptions!.host, 'example.com', 'passes correct host')
149
+ assert.equal(capturedOptions!.port, 80, 'passes correct port')
150
+ assert.equal(capturedOptions!.protocol, 'http:', 'passes correct protocol')
151
+ assert.equal(capturedOptions!.proxy, '127.0.0.1:8080', 'passes proxy configuration')
152
+ assert.equal(capturedOptions!.proxyIsSsl, false, 'detects non-SSL proxy')
153
+ assert.equal(capturedOptions!.targetUrl, 'http://example.com:80', 'constructs target URL')
154
+ assert.equal(capturedOptions!.proxyUsername, 'user', 'passes proxy username')
155
+ assert.equal(capturedOptions!.proxyPassword, 'pass', 'passes proxy password')
156
+ assert.equal(capturedOptions!.proxyAuthorization, 'Basic', 'passes proxy authorization')
157
+
158
+ // Restore original method
159
+ connectionManager.createProxyConnection = originalCreateProxyConnection
160
+ })
161
+
162
+ test('should create tunnel connection for HTTPS through proxy', async ({ assert }) => {
163
+ const mockSocket = new net.Socket()
164
+ createdSockets.push(mockSocket)
165
+
166
+ // Mock TunnelConnection.connect to return our mock socket
167
+ const originalCreateTunnelConnection = connectionManager.createTunnelConnection
168
+ let capturedOptions: TunnelConnectionOptions | undefined
169
+
170
+ connectionManager.createTunnelConnection = (options) => {
171
+ capturedOptions = options
172
+ return {
173
+ connect: async () => mockSocket,
174
+ } as TunnelConnection
175
+ }
176
+
177
+ const engineOptions: HttpEngineOptions = {
178
+ proxy: 'https://proxy.example.com:8443',
179
+ timeout: 10000,
180
+ validateCertificates: true,
181
+ proxyUsername: 'admin',
182
+ proxyPassword: 'secret',
183
+ }
184
+
185
+ const result = await connectionManager.createConnection('secure.example.com', 443, 'https:', engineOptions)
186
+
187
+ assert.equal(result, mockSocket, 'returns the socket from TunnelConnection')
188
+ assert.equal(capturedOptions!.host, 'secure.example.com', 'passes correct host')
189
+ assert.equal(capturedOptions!.port, 443, 'passes correct port')
190
+ assert.equal(capturedOptions!.protocol, 'https:', 'passes correct protocol')
191
+ assert.equal(capturedOptions!.proxy, 'https://proxy.example.com:8443', 'passes proxy configuration')
192
+ assert.equal(capturedOptions!.proxyIsSsl, true, 'detects SSL proxy')
193
+ assert.equal(capturedOptions!.targetUrl, 'https://secure.example.com:443', 'constructs target URL')
194
+ assert.equal(capturedOptions!.targetHost, 'secure.example.com', 'passes target host')
195
+ assert.equal(capturedOptions!.targetPort, 443, 'passes target port')
196
+ assert.equal(capturedOptions!.proxyUsername, 'admin', 'passes proxy username')
197
+ assert.equal(capturedOptions!.proxyPassword, 'secret', 'passes proxy password')
198
+
199
+ // Restore original method
200
+ connectionManager.createTunnelConnection = originalCreateTunnelConnection
201
+ })
202
+
203
+ test('should detect SSL proxy correctly with https: scheme', async ({ assert }) => {
204
+ const mockSocket = new net.Socket()
205
+ createdSockets.push(mockSocket)
206
+
207
+ const originalCreateProxyConnection = connectionManager.createProxyConnection
208
+ let capturedOptions: ProxyConnectionOptions | undefined
209
+
210
+ connectionManager.createProxyConnection = (options) => {
211
+ capturedOptions = options
212
+ return {
213
+ connect: async () => mockSocket,
214
+ } as ProxyConnection
215
+ }
216
+
217
+ const engineOptions: HttpEngineOptions = {
218
+ proxy: 'https://secure-proxy.example.com:8443',
219
+ }
220
+
221
+ await connectionManager.createConnection('example.com', 80, 'http:', engineOptions)
222
+
223
+ assert.equal(capturedOptions!.proxyIsSsl, true, 'correctly identifies SSL proxy')
224
+
225
+ // Restore original method
226
+ connectionManager.createProxyConnection = originalCreateProxyConnection
227
+ })
228
+
229
+ test('should detect non-SSL proxy correctly without https: scheme', async ({ assert }) => {
230
+ const mockSocket = new net.Socket()
231
+ createdSockets.push(mockSocket)
232
+
233
+ const originalCreateProxyConnection = connectionManager.createProxyConnection
234
+ let capturedOptions: ProxyConnectionOptions | undefined
235
+
236
+ connectionManager.createProxyConnection = (options) => {
237
+ capturedOptions = options
238
+ return {
239
+ connect: async () => mockSocket,
240
+ } as ProxyConnection
241
+ }
242
+
243
+ const engineOptions: HttpEngineOptions = {
244
+ proxy: '192.168.1.100:3128',
245
+ }
246
+
247
+ const socket = await connectionManager.createConnection('example.com', 80, 'http:', engineOptions)
248
+ createdSockets.push(socket)
249
+
250
+ assert.equal(capturedOptions!.proxyIsSsl, false, 'correctly identifies non-SSL proxy')
251
+
252
+ // Restore original method
253
+ connectionManager.createProxyConnection = originalCreateProxyConnection
254
+ })
255
+
256
+ test('should pass client certificates to connection options', async ({ assert }) => {
257
+ const mockSocket = new net.Socket()
258
+ createdSockets.push(mockSocket)
259
+ const mockCertificates: HttpCertificate[] = [
260
+ {
261
+ key: 'abcd1234',
262
+ kind: 'Core#Certificate',
263
+ name: 'test-cert',
264
+ cert: { data: Buffer.from('cert-data') },
265
+ certKey: { data: Buffer.from('key-data'), passphrase: 'secret' },
266
+ type: 'pem',
267
+ },
268
+ ]
269
+
270
+ const originalCreateDirectConnection = connectionManager.createDirectConnection
271
+ let capturedOptions: ConnectionOptions | undefined
272
+
273
+ connectionManager.createDirectConnection = (options) => {
274
+ capturedOptions = options
275
+ return {
276
+ connect: async () => mockSocket,
277
+ } as DirectConnection
278
+ }
279
+
280
+ const engineOptions: HttpEngineOptions = {
281
+ certificates: mockCertificates,
282
+ validateCertificates: false,
283
+ }
284
+
285
+ await connectionManager.createConnection('client-cert.example.com', 443, 'https:', engineOptions)
286
+
287
+ assert.equal(capturedOptions!.certificates, mockCertificates, 'passes client certificates')
288
+ assert.equal(capturedOptions!.validateCertificates, false, 'passes certificate validation setting')
289
+
290
+ // Restore original method
291
+ connectionManager.createDirectConnection = originalCreateDirectConnection
292
+ })
293
+
294
+ test('should handle undefined optional parameters', async ({ assert }) => {
295
+ const mockSocket = new net.Socket()
296
+ createdSockets.push(mockSocket)
297
+
298
+ const originalCreateDirectConnection = connectionManager.createDirectConnection
299
+ let capturedOptions: ConnectionOptions | undefined
300
+
301
+ connectionManager.createDirectConnection = (options) => {
302
+ capturedOptions = options
303
+ return {
304
+ connect: async () => mockSocket,
305
+ } as DirectConnection
306
+ }
307
+
308
+ const engineOptions: HttpEngineOptions = {}
309
+
310
+ await connectionManager.createConnection('example.com', 80, 'http:', engineOptions)
311
+
312
+ assert.isUndefined(capturedOptions!.timeout, 'handles undefined timeout')
313
+ assert.isUndefined(capturedOptions!.validateCertificates, 'handles undefined certificate validation')
314
+ assert.isUndefined(capturedOptions!.certificates, 'handles undefined certificates')
315
+
316
+ // Restore original method
317
+ connectionManager.createDirectConnection = originalCreateDirectConnection
318
+ })
319
+
320
+ test('should handle custom ports correctly', async ({ assert }) => {
321
+ const mockSocket = new net.Socket()
322
+ createdSockets.push(mockSocket)
323
+
324
+ const originalCreateProxyConnection = connectionManager.createProxyConnection
325
+ let capturedOptions: ProxyConnectionOptions | undefined
326
+
327
+ connectionManager.createProxyConnection = (options) => {
328
+ capturedOptions = options
329
+ return {
330
+ connect: async () => mockSocket,
331
+ } as ProxyConnection
332
+ }
333
+
334
+ const engineOptions: HttpEngineOptions = {
335
+ proxy: '127.0.0.1:8080',
336
+ }
337
+
338
+ await connectionManager.createConnection('api.example.com', 8090, 'http:', engineOptions)
339
+
340
+ assert.equal(capturedOptions!.targetUrl, 'http://api.example.com:8090', 'constructs URL with custom port')
341
+
342
+ // Restore original method
343
+ connectionManager.createProxyConnection = originalCreateProxyConnection
344
+ })
345
+
346
+ test('should create working connection through proxy', async ({ assert, httpConfig }) => {
347
+ const engineOptions: HttpEngineOptions = {
348
+ proxy: `127.0.0.1:${httpConfig.proxyHttpPort}`,
349
+ timeout: 5000,
350
+ validateCertificates: false,
351
+ }
352
+
353
+ // Try to create a real connection through the proxy
354
+ const socket = await connectionManager.createConnection('httpbin.org', 80, 'http:', engineOptions)
355
+ createdSockets.push(socket)
356
+
357
+ assert.ok(socket, 'creates a real socket')
358
+ assert.instanceOf(socket, net.Socket, 'returns a net.Socket instance')
359
+
360
+ // Note: socket will be cleaned up in teardown
361
+ }).timeout(10000)
362
+
363
+ test('should create working HTTPS tunnel through proxy', async ({ assert, httpConfig }) => {
364
+ const engineOptions: HttpEngineOptions = {
365
+ proxy: `https://127.0.0.1:${httpConfig.proxyHttpsPort}`,
366
+ timeout: 5000,
367
+ validateCertificates: false,
368
+ }
369
+
370
+ // Try to create a real HTTPS tunnel through the proxy
371
+ const socket = await connectionManager.createConnection('httpbin.org', 443, 'https:', engineOptions)
372
+ createdSockets.push(socket)
373
+
374
+ assert.ok(socket, 'creates a real socket')
375
+ assert.instanceOf(socket, net.Socket, 'returns a net.Socket instance')
376
+
377
+ // Note: socket will be cleaned up in teardown
378
+ }).timeout(10000)
379
+ })
@@ -0,0 +1,164 @@
1
+ import { test } from '@japa/runner'
2
+ import { DigestAuthHandler } from '../../../../../src/runtime/http-engine/connections/DigestAuthHandler.js'
3
+ import { createLogger, type Logger, type ILogObj } from '../../../../../src/lib/logging/index.js'
4
+
5
+ test.group('DigestAuthHandler', (group) => {
6
+ let handler: DigestAuthHandler
7
+ let logger: Logger<ILogObj>
8
+
9
+ group.each.setup(() => {
10
+ logger = createLogger()
11
+ handler = new DigestAuthHandler('testuser', 'testpass', logger)
12
+ })
13
+
14
+ test('should parse a basic Digest challenge', ({ assert }) => {
15
+ const challenge = handler.parseChallenge(
16
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", algorithm=MD5'
17
+ )
18
+
19
+ assert.equal(challenge.realm, 'testrealm')
20
+ assert.equal(challenge.nonce, 'dcd98b7102dd2f0e8b11d0f600bfb0c093')
21
+ assert.equal(challenge.algorithm, 'MD5')
22
+ })
23
+
24
+ test('should parse a challenge with qop', ({ assert }) => {
25
+ const challenge = handler.parseChallenge(
26
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", qop="auth"'
27
+ )
28
+
29
+ assert.equal(challenge.realm, 'testrealm')
30
+ assert.equal(challenge.nonce, 'dcd98b7102dd2f0e8b11d0f600bfb0c093')
31
+ assert.equal(challenge.qop, 'auth')
32
+ })
33
+
34
+ test('should throw error for non-Digest challenge', ({ assert }) => {
35
+ assert.throws(() => {
36
+ handler.parseChallenge('Basic realm="testrealm"')
37
+ }, 'Not a Digest authentication challenge')
38
+ })
39
+
40
+ test('should throw error for invalid challenge', ({ assert }) => {
41
+ assert.throws(() => {
42
+ handler.parseChallenge('Digest realm="testrealm"')
43
+ }, 'Invalid Digest challenge: missing realm or nonce')
44
+ })
45
+
46
+ test('should generate response without qop', ({ assert }) => {
47
+ const challenge = handler.parseChallenge(
48
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", algorithm=MD5'
49
+ )
50
+
51
+ const response = handler.generateResponse(challenge, 'CONNECT', '/')
52
+
53
+ assert.include(response, 'Digest')
54
+ assert.include(response, 'username="testuser"')
55
+ assert.include(response, 'realm="testrealm"')
56
+ assert.include(response, 'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"')
57
+ assert.include(response, 'uri="/"')
58
+ assert.include(response, 'response=')
59
+ assert.include(response, 'algorithm="MD5"')
60
+ })
61
+
62
+ test('should generate response with qop', ({ assert }) => {
63
+ const challenge = handler.parseChallenge(
64
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", qop="auth", algorithm=MD5'
65
+ )
66
+
67
+ const response = handler.generateResponse(challenge, 'CONNECT', '/')
68
+
69
+ assert.include(response, 'Digest')
70
+ assert.include(response, 'username="testuser"')
71
+ assert.include(response, 'realm="testrealm"')
72
+ assert.include(response, 'nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"')
73
+ assert.include(response, 'uri="/"')
74
+ assert.include(response, 'response=')
75
+ assert.include(response, 'qop="auth"')
76
+ assert.include(response, 'nc=')
77
+ assert.include(response, 'cnonce=')
78
+ })
79
+
80
+ test('should handle opaque parameter', ({ assert }) => {
81
+ const challenge = handler.parseChallenge(
82
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", ' +
83
+ 'opaque="5ccc069c403ebaf9f0171e9517f40e41"'
84
+ )
85
+
86
+ const response = handler.generateResponse(challenge, 'CONNECT', '/')
87
+
88
+ assert.include(response, 'opaque="5ccc069c403ebaf9f0171e9517f40e41"')
89
+ })
90
+
91
+ test('should throw error for unsupported qop', ({ assert }) => {
92
+ const challenge = handler.parseChallenge(
93
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", qop="auth-int"'
94
+ )
95
+
96
+ assert.throws(() => {
97
+ handler.generateResponse(challenge, 'CONNECT', '/')
98
+ }, 'Unsupported qop value: auth-int')
99
+ })
100
+
101
+ test('should increment nonce count for each request', ({ assert }) => {
102
+ const challenge = handler.parseChallenge(
103
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", qop="auth"'
104
+ )
105
+
106
+ const response1 = handler.generateResponse(challenge, 'CONNECT', '/')
107
+ const response2 = handler.generateResponse(challenge, 'CONNECT', '/')
108
+
109
+ // Extract nc values
110
+ const nc1Match = response1.match(/nc="([^"]+)"/)
111
+ const nc2Match = response2.match(/nc="([^"]+)"/)
112
+
113
+ assert.isNotNull(nc1Match)
114
+ assert.isNotNull(nc2Match)
115
+ assert.equal(nc1Match![1], '00000001')
116
+ assert.equal(nc2Match![1], '00000002')
117
+ })
118
+
119
+ test('should reset nonce count and generate new cnonce', ({ assert }) => {
120
+ const challenge = handler.parseChallenge(
121
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", qop="auth"'
122
+ )
123
+
124
+ const response1 = handler.generateResponse(challenge, 'CONNECT', '/')
125
+ handler.reset()
126
+ const response2 = handler.generateResponse(challenge, 'CONNECT', '/')
127
+
128
+ // Extract nc and cnonce values
129
+ const nc1Match = response1.match(/nc="([^"]+)"/)
130
+ const nc2Match = response2.match(/nc="([^"]+)"/)
131
+ const cnonce1Match = response1.match(/cnonce="([^"]+)"/)
132
+ const cnonce2Match = response2.match(/cnonce="([^"]+)"/)
133
+
134
+ assert.equal(nc1Match![1], '00000001')
135
+ assert.equal(nc2Match![1], '00000001') // Reset to 1
136
+ assert.notEqual(cnonce1Match![1], cnonce2Match![1]) // Different cnonce
137
+ })
138
+
139
+ test('should detect stale challenges', ({ assert }) => {
140
+ const staleChallenge = handler.parseChallenge(
141
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", stale=true'
142
+ )
143
+
144
+ const freshChallenge = handler.parseChallenge(
145
+ 'Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", stale=false'
146
+ )
147
+
148
+ assert.isTrue(handler.isStale(staleChallenge))
149
+ assert.isFalse(handler.isStale(freshChallenge))
150
+ })
151
+
152
+ test('should calculate correct HA1', ({ assert }) => {
153
+ // This test verifies the MD5 calculation is correct
154
+ // HA1 = MD5(username:realm:password)
155
+ const challenge = handler.parseChallenge('Digest realm="testrealm", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"')
156
+
157
+ const response = handler.generateResponse(challenge, 'CONNECT', '/')
158
+ const responseMatch = response.match(/response="([^"]+)"/)
159
+
160
+ assert.isNotNull(responseMatch)
161
+ // The response should be a valid MD5 hash
162
+ assert.match(responseMatch![1], /^[a-f0-9]{32}$/)
163
+ })
164
+ })