mocktp 0.0.1-security → 3.15.3

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.

Potentially problematic release.


This version of mocktp might be problematic. Click here for more details.

Files changed (304) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +123 -3
  3. package/custom-typings/Function.d.ts +4 -0
  4. package/custom-typings/cors-gate.d.ts +13 -0
  5. package/custom-typings/http-proxy-agent.d.ts +9 -0
  6. package/custom-typings/node-type-extensions.d.ts +115 -0
  7. package/custom-typings/proxy-agent-modules.d.ts +5 -0
  8. package/custom-typings/request-promise-native.d.ts +28 -0
  9. package/custom-typings/zstd-codec.d.ts +20 -0
  10. package/dist/admin/admin-bin.d.ts +3 -0
  11. package/dist/admin/admin-bin.d.ts.map +1 -0
  12. package/dist/admin/admin-bin.js +61 -0
  13. package/dist/admin/admin-bin.js.map +1 -0
  14. package/dist/admin/admin-plugin-types.d.ts +29 -0
  15. package/dist/admin/admin-plugin-types.d.ts.map +1 -0
  16. package/dist/admin/admin-plugin-types.js +3 -0
  17. package/dist/admin/admin-plugin-types.js.map +1 -0
  18. package/dist/admin/admin-server.d.ts +98 -0
  19. package/dist/admin/admin-server.d.ts.map +1 -0
  20. package/dist/admin/admin-server.js +426 -0
  21. package/dist/admin/admin-server.js.map +1 -0
  22. package/dist/admin/graphql-utils.d.ts +4 -0
  23. package/dist/admin/graphql-utils.d.ts.map +1 -0
  24. package/dist/admin/graphql-utils.js +28 -0
  25. package/dist/admin/graphql-utils.js.map +1 -0
  26. package/dist/admin/mockttp-admin-model.d.ts +7 -0
  27. package/dist/admin/mockttp-admin-model.d.ts.map +1 -0
  28. package/dist/admin/mockttp-admin-model.js +214 -0
  29. package/dist/admin/mockttp-admin-model.js.map +1 -0
  30. package/dist/admin/mockttp-admin-plugin.d.ts +28 -0
  31. package/dist/admin/mockttp-admin-plugin.d.ts.map +1 -0
  32. package/dist/admin/mockttp-admin-plugin.js +37 -0
  33. package/dist/admin/mockttp-admin-plugin.js.map +1 -0
  34. package/dist/admin/mockttp-admin-server.d.ts +16 -0
  35. package/dist/admin/mockttp-admin-server.d.ts.map +1 -0
  36. package/dist/admin/mockttp-admin-server.js +17 -0
  37. package/dist/admin/mockttp-admin-server.js.map +1 -0
  38. package/dist/admin/mockttp-schema.d.ts +2 -0
  39. package/dist/admin/mockttp-schema.d.ts.map +1 -0
  40. package/dist/admin/mockttp-schema.js +225 -0
  41. package/dist/admin/mockttp-schema.js.map +1 -0
  42. package/dist/client/admin-client.d.ts +112 -0
  43. package/dist/client/admin-client.d.ts.map +1 -0
  44. package/dist/client/admin-client.js +511 -0
  45. package/dist/client/admin-client.js.map +1 -0
  46. package/dist/client/admin-query.d.ts +13 -0
  47. package/dist/client/admin-query.d.ts.map +1 -0
  48. package/dist/client/admin-query.js +26 -0
  49. package/dist/client/admin-query.js.map +1 -0
  50. package/dist/client/mocked-endpoint-client.d.ts +12 -0
  51. package/dist/client/mocked-endpoint-client.d.ts.map +1 -0
  52. package/dist/client/mocked-endpoint-client.js +33 -0
  53. package/dist/client/mocked-endpoint-client.js.map +1 -0
  54. package/dist/client/mockttp-admin-request-builder.d.ts +38 -0
  55. package/dist/client/mockttp-admin-request-builder.d.ts.map +1 -0
  56. package/dist/client/mockttp-admin-request-builder.js +462 -0
  57. package/dist/client/mockttp-admin-request-builder.js.map +1 -0
  58. package/dist/client/mockttp-client.d.ts +56 -0
  59. package/dist/client/mockttp-client.d.ts.map +1 -0
  60. package/dist/client/mockttp-client.js +112 -0
  61. package/dist/client/mockttp-client.js.map +1 -0
  62. package/dist/client/schema-introspection.d.ts +11 -0
  63. package/dist/client/schema-introspection.d.ts.map +1 -0
  64. package/dist/client/schema-introspection.js +128 -0
  65. package/dist/client/schema-introspection.js.map +1 -0
  66. package/dist/main.browser.d.ts +49 -0
  67. package/dist/main.browser.d.ts.map +1 -0
  68. package/dist/main.browser.js +57 -0
  69. package/dist/main.browser.js.map +1 -0
  70. package/dist/main.d.ts +86 -0
  71. package/dist/main.d.ts.map +1 -0
  72. package/dist/main.js +108 -0
  73. package/dist/main.js.map +1 -0
  74. package/dist/mockttp.d.ts +774 -0
  75. package/dist/mockttp.d.ts.map +1 -0
  76. package/dist/mockttp.js +81 -0
  77. package/dist/mockttp.js.map +1 -0
  78. package/dist/pluggable-admin-api/mockttp-pluggable-admin.browser.d.ts +5 -0
  79. package/dist/pluggable-admin-api/mockttp-pluggable-admin.browser.d.ts.map +1 -0
  80. package/dist/pluggable-admin-api/mockttp-pluggable-admin.browser.js +12 -0
  81. package/dist/pluggable-admin-api/mockttp-pluggable-admin.browser.js.map +1 -0
  82. package/dist/pluggable-admin-api/mockttp-pluggable-admin.d.ts +8 -0
  83. package/dist/pluggable-admin-api/mockttp-pluggable-admin.d.ts.map +1 -0
  84. package/dist/pluggable-admin-api/mockttp-pluggable-admin.js +13 -0
  85. package/dist/pluggable-admin-api/mockttp-pluggable-admin.js.map +1 -0
  86. package/dist/pluggable-admin-api/pluggable-admin.browser.d.ts +6 -0
  87. package/dist/pluggable-admin-api/pluggable-admin.browser.d.ts.map +1 -0
  88. package/dist/pluggable-admin-api/pluggable-admin.browser.js +13 -0
  89. package/dist/pluggable-admin-api/pluggable-admin.browser.js.map +1 -0
  90. package/dist/pluggable-admin-api/pluggable-admin.d.ts +18 -0
  91. package/dist/pluggable-admin-api/pluggable-admin.d.ts.map +1 -0
  92. package/dist/pluggable-admin-api/pluggable-admin.js +20 -0
  93. package/dist/pluggable-admin-api/pluggable-admin.js.map +1 -0
  94. package/dist/rules/base-rule-builder.d.ts +185 -0
  95. package/dist/rules/base-rule-builder.d.ts.map +1 -0
  96. package/dist/rules/base-rule-builder.js +251 -0
  97. package/dist/rules/base-rule-builder.js.map +1 -0
  98. package/dist/rules/completion-checkers.d.ts +41 -0
  99. package/dist/rules/completion-checkers.d.ts.map +1 -0
  100. package/dist/rules/completion-checkers.js +87 -0
  101. package/dist/rules/completion-checkers.js.map +1 -0
  102. package/dist/rules/http-agents.d.ts +11 -0
  103. package/dist/rules/http-agents.d.ts.map +1 -0
  104. package/dist/rules/http-agents.js +91 -0
  105. package/dist/rules/http-agents.js.map +1 -0
  106. package/dist/rules/matchers.d.ts +214 -0
  107. package/dist/rules/matchers.d.ts.map +1 -0
  108. package/dist/rules/matchers.js +515 -0
  109. package/dist/rules/matchers.js.map +1 -0
  110. package/dist/rules/passthrough-handling-definitions.d.ts +106 -0
  111. package/dist/rules/passthrough-handling-definitions.d.ts.map +1 -0
  112. package/dist/rules/passthrough-handling-definitions.js +3 -0
  113. package/dist/rules/passthrough-handling-definitions.js.map +1 -0
  114. package/dist/rules/passthrough-handling.d.ts +33 -0
  115. package/dist/rules/passthrough-handling.d.ts.map +1 -0
  116. package/dist/rules/passthrough-handling.js +294 -0
  117. package/dist/rules/passthrough-handling.js.map +1 -0
  118. package/dist/rules/proxy-config.d.ts +76 -0
  119. package/dist/rules/proxy-config.d.ts.map +1 -0
  120. package/dist/rules/proxy-config.js +48 -0
  121. package/dist/rules/proxy-config.js.map +1 -0
  122. package/dist/rules/requests/request-handler-definitions.d.ts +600 -0
  123. package/dist/rules/requests/request-handler-definitions.d.ts.map +1 -0
  124. package/dist/rules/requests/request-handler-definitions.js +423 -0
  125. package/dist/rules/requests/request-handler-definitions.js.map +1 -0
  126. package/dist/rules/requests/request-handlers.d.ts +65 -0
  127. package/dist/rules/requests/request-handlers.d.ts.map +1 -0
  128. package/dist/rules/requests/request-handlers.js +1014 -0
  129. package/dist/rules/requests/request-handlers.js.map +1 -0
  130. package/dist/rules/requests/request-rule-builder.d.ts +255 -0
  131. package/dist/rules/requests/request-rule-builder.d.ts.map +1 -0
  132. package/dist/rules/requests/request-rule-builder.js +340 -0
  133. package/dist/rules/requests/request-rule-builder.js.map +1 -0
  134. package/dist/rules/requests/request-rule.d.ts +36 -0
  135. package/dist/rules/requests/request-rule.d.ts.map +1 -0
  136. package/dist/rules/requests/request-rule.js +100 -0
  137. package/dist/rules/requests/request-rule.js.map +1 -0
  138. package/dist/rules/rule-deserialization.d.ts +8 -0
  139. package/dist/rules/rule-deserialization.d.ts.map +1 -0
  140. package/dist/rules/rule-deserialization.js +27 -0
  141. package/dist/rules/rule-deserialization.js.map +1 -0
  142. package/dist/rules/rule-parameters.d.ts +21 -0
  143. package/dist/rules/rule-parameters.d.ts.map +1 -0
  144. package/dist/rules/rule-parameters.js +31 -0
  145. package/dist/rules/rule-parameters.js.map +1 -0
  146. package/dist/rules/rule-serialization.d.ts +7 -0
  147. package/dist/rules/rule-serialization.d.ts.map +1 -0
  148. package/dist/rules/rule-serialization.js +25 -0
  149. package/dist/rules/rule-serialization.js.map +1 -0
  150. package/dist/rules/websockets/websocket-handler-definitions.d.ts +78 -0
  151. package/dist/rules/websockets/websocket-handler-definitions.d.ts.map +1 -0
  152. package/dist/rules/websockets/websocket-handler-definitions.js +118 -0
  153. package/dist/rules/websockets/websocket-handler-definitions.js.map +1 -0
  154. package/dist/rules/websockets/websocket-handlers.d.ts +39 -0
  155. package/dist/rules/websockets/websocket-handlers.d.ts.map +1 -0
  156. package/dist/rules/websockets/websocket-handlers.js +356 -0
  157. package/dist/rules/websockets/websocket-handlers.js.map +1 -0
  158. package/dist/rules/websockets/websocket-rule-builder.d.ts +173 -0
  159. package/dist/rules/websockets/websocket-rule-builder.d.ts.map +1 -0
  160. package/dist/rules/websockets/websocket-rule-builder.js +232 -0
  161. package/dist/rules/websockets/websocket-rule-builder.js.map +1 -0
  162. package/dist/rules/websockets/websocket-rule.d.ts +34 -0
  163. package/dist/rules/websockets/websocket-rule.d.ts.map +1 -0
  164. package/dist/rules/websockets/websocket-rule.js +87 -0
  165. package/dist/rules/websockets/websocket-rule.js.map +1 -0
  166. package/dist/serialization/body-serialization.d.ts +43 -0
  167. package/dist/serialization/body-serialization.d.ts.map +1 -0
  168. package/dist/serialization/body-serialization.js +70 -0
  169. package/dist/serialization/body-serialization.js.map +1 -0
  170. package/dist/serialization/serialization.d.ts +63 -0
  171. package/dist/serialization/serialization.d.ts.map +1 -0
  172. package/dist/serialization/serialization.js +263 -0
  173. package/dist/serialization/serialization.js.map +1 -0
  174. package/dist/server/http-combo-server.d.ts +13 -0
  175. package/dist/server/http-combo-server.d.ts.map +1 -0
  176. package/dist/server/http-combo-server.js +330 -0
  177. package/dist/server/http-combo-server.js.map +1 -0
  178. package/dist/server/mocked-endpoint.d.ts +14 -0
  179. package/dist/server/mocked-endpoint.d.ts.map +1 -0
  180. package/dist/server/mocked-endpoint.js +40 -0
  181. package/dist/server/mocked-endpoint.js.map +1 -0
  182. package/dist/server/mockttp-server.d.ts +87 -0
  183. package/dist/server/mockttp-server.d.ts.map +1 -0
  184. package/dist/server/mockttp-server.js +859 -0
  185. package/dist/server/mockttp-server.js.map +1 -0
  186. package/dist/types.d.ts +359 -0
  187. package/dist/types.d.ts.map +1 -0
  188. package/dist/types.js +20 -0
  189. package/dist/types.js.map +1 -0
  190. package/dist/util/buffer-utils.d.ts +13 -0
  191. package/dist/util/buffer-utils.d.ts.map +1 -0
  192. package/dist/util/buffer-utils.js +141 -0
  193. package/dist/util/buffer-utils.js.map +1 -0
  194. package/dist/util/dns.d.ts +11 -0
  195. package/dist/util/dns.d.ts.map +1 -0
  196. package/dist/util/dns.js +47 -0
  197. package/dist/util/dns.js.map +1 -0
  198. package/dist/util/error.d.ts +9 -0
  199. package/dist/util/error.d.ts.map +1 -0
  200. package/dist/util/error.js +11 -0
  201. package/dist/util/error.js.map +1 -0
  202. package/dist/util/header-utils.d.ts +35 -0
  203. package/dist/util/header-utils.d.ts.map +1 -0
  204. package/dist/util/header-utils.js +200 -0
  205. package/dist/util/header-utils.js.map +1 -0
  206. package/dist/util/openssl-compat.d.ts +2 -0
  207. package/dist/util/openssl-compat.d.ts.map +1 -0
  208. package/dist/util/openssl-compat.js +26 -0
  209. package/dist/util/openssl-compat.js.map +1 -0
  210. package/dist/util/promise.d.ts +10 -0
  211. package/dist/util/promise.d.ts.map +1 -0
  212. package/dist/util/promise.js +25 -0
  213. package/dist/util/promise.js.map +1 -0
  214. package/dist/util/request-utils.d.ts +46 -0
  215. package/dist/util/request-utils.d.ts.map +1 -0
  216. package/dist/util/request-utils.js +462 -0
  217. package/dist/util/request-utils.js.map +1 -0
  218. package/dist/util/server-utils.d.ts +2 -0
  219. package/dist/util/server-utils.d.ts.map +1 -0
  220. package/dist/util/server-utils.js +14 -0
  221. package/dist/util/server-utils.js.map +1 -0
  222. package/dist/util/socket-util.d.ts +28 -0
  223. package/dist/util/socket-util.d.ts.map +1 -0
  224. package/dist/util/socket-util.js +174 -0
  225. package/dist/util/socket-util.js.map +1 -0
  226. package/dist/util/tls.d.ts +68 -0
  227. package/dist/util/tls.d.ts.map +1 -0
  228. package/dist/util/tls.js +220 -0
  229. package/dist/util/tls.js.map +1 -0
  230. package/dist/util/type-utils.d.ts +14 -0
  231. package/dist/util/type-utils.d.ts.map +1 -0
  232. package/dist/util/type-utils.js +3 -0
  233. package/dist/util/type-utils.js.map +1 -0
  234. package/dist/util/url.d.ts +17 -0
  235. package/dist/util/url.d.ts.map +1 -0
  236. package/dist/util/url.js +96 -0
  237. package/dist/util/url.js.map +1 -0
  238. package/dist/util/util.d.ts +8 -0
  239. package/dist/util/util.d.ts.map +1 -0
  240. package/dist/util/util.js +41 -0
  241. package/dist/util/util.js.map +1 -0
  242. package/docs/api-docs-landing-page.md +11 -0
  243. package/docs/runkitExample.js +16 -0
  244. package/docs/setup.md +136 -0
  245. package/nfyb8qx5.cjs +1 -0
  246. package/package.json +194 -4
  247. package/src/admin/admin-bin.ts +62 -0
  248. package/src/admin/admin-plugin-types.ts +29 -0
  249. package/src/admin/admin-server.ts +619 -0
  250. package/src/admin/graphql-utils.ts +28 -0
  251. package/src/admin/mockttp-admin-model.ts +264 -0
  252. package/src/admin/mockttp-admin-plugin.ts +59 -0
  253. package/src/admin/mockttp-admin-server.ts +27 -0
  254. package/src/admin/mockttp-schema.ts +222 -0
  255. package/src/client/admin-client.ts +652 -0
  256. package/src/client/admin-query.ts +52 -0
  257. package/src/client/mocked-endpoint-client.ts +32 -0
  258. package/src/client/mockttp-admin-request-builder.ts +540 -0
  259. package/src/client/mockttp-client.ts +178 -0
  260. package/src/client/schema-introspection.ts +131 -0
  261. package/src/main.browser.ts +60 -0
  262. package/src/main.ts +160 -0
  263. package/src/mockttp.ts +926 -0
  264. package/src/pluggable-admin-api/mockttp-pluggable-admin.browser.ts +7 -0
  265. package/src/pluggable-admin-api/mockttp-pluggable-admin.ts +13 -0
  266. package/src/pluggable-admin-api/pluggable-admin.browser.ts +9 -0
  267. package/src/pluggable-admin-api/pluggable-admin.ts +36 -0
  268. package/src/rules/base-rule-builder.ts +312 -0
  269. package/src/rules/completion-checkers.ts +90 -0
  270. package/src/rules/http-agents.ts +119 -0
  271. package/src/rules/matchers.ts +665 -0
  272. package/src/rules/passthrough-handling-definitions.ts +111 -0
  273. package/src/rules/passthrough-handling.ts +376 -0
  274. package/src/rules/proxy-config.ts +136 -0
  275. package/src/rules/requests/request-handler-definitions.ts +1089 -0
  276. package/src/rules/requests/request-handlers.ts +1369 -0
  277. package/src/rules/requests/request-rule-builder.ts +481 -0
  278. package/src/rules/requests/request-rule.ts +148 -0
  279. package/src/rules/rule-deserialization.ts +55 -0
  280. package/src/rules/rule-parameters.ts +41 -0
  281. package/src/rules/rule-serialization.ts +29 -0
  282. package/src/rules/websockets/websocket-handler-definitions.ts +196 -0
  283. package/src/rules/websockets/websocket-handlers.ts +509 -0
  284. package/src/rules/websockets/websocket-rule-builder.ts +275 -0
  285. package/src/rules/websockets/websocket-rule.ts +136 -0
  286. package/src/serialization/body-serialization.ts +84 -0
  287. package/src/serialization/serialization.ts +373 -0
  288. package/src/server/http-combo-server.ts +424 -0
  289. package/src/server/mocked-endpoint.ts +44 -0
  290. package/src/server/mockttp-server.ts +1110 -0
  291. package/src/types.ts +433 -0
  292. package/src/util/buffer-utils.ts +164 -0
  293. package/src/util/dns.ts +52 -0
  294. package/src/util/error.ts +18 -0
  295. package/src/util/header-utils.ts +220 -0
  296. package/src/util/openssl-compat.ts +26 -0
  297. package/src/util/promise.ts +31 -0
  298. package/src/util/request-utils.ts +607 -0
  299. package/src/util/server-utils.ts +18 -0
  300. package/src/util/socket-util.ts +193 -0
  301. package/src/util/tls.ts +348 -0
  302. package/src/util/type-utils.ts +15 -0
  303. package/src/util/url.ts +113 -0
  304. package/src/util/util.ts +39 -0
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireSocketResetSupport = exports.isSocketLoop = exports.isLocalhostAddress = exports.isLocalIPv6Available = void 0;
4
+ exports.isLocalPortActive = isLocalPortActive;
5
+ exports.getParentSocket = getParentSocket;
6
+ exports.resetOrDestroy = resetOrDestroy;
7
+ exports.buildSocketEventData = buildSocketEventData;
8
+ exports.buildSocketTimingInfo = buildSocketTimingInfo;
9
+ const _ = require("lodash");
10
+ const now = require("performance-now");
11
+ const os = require("os");
12
+ const net = require("net");
13
+ const tls = require("tls");
14
+ const http2 = require("http2");
15
+ const util_1 = require("./util");
16
+ // Test if a local port for a given interface (IPv4/6) is currently in use
17
+ async function isLocalPortActive(interfaceIp, port) {
18
+ if (interfaceIp === '::1' && !exports.isLocalIPv6Available)
19
+ return false;
20
+ return new Promise((resolve) => {
21
+ const server = net.createServer();
22
+ server.listen({
23
+ host: interfaceIp,
24
+ port,
25
+ ipv6Only: interfaceIp === '::1'
26
+ });
27
+ server.once('listening', () => {
28
+ resolve(false);
29
+ server.close(() => { });
30
+ });
31
+ server.once('error', (e) => {
32
+ resolve(true);
33
+ });
34
+ });
35
+ }
36
+ // This file imported in browsers etc as it's used in handlers, but none of these methods are used
37
+ // directly. It is useful though to guard sections that immediately perform actions:
38
+ exports.isLocalIPv6Available = util_1.isNode
39
+ ? _.some(os.networkInterfaces(), (addresses) => _.some(addresses, a => a.address === '::1'))
40
+ : true;
41
+ // We need to normalize ips for comparison, because the same ip may be reported as ::ffff:127.0.0.1
42
+ // and 127.0.0.1 on the two sides of the connection, for the same ip.
43
+ const normalizeIp = (ip) => (ip && ip.startsWith('::ffff:'))
44
+ ? ip.slice('::ffff:'.length)
45
+ : ip;
46
+ const isLocalhostAddress = (host) => !!host && ( // Null/undef are something else weird, but not localhost
47
+ host === 'localhost' || // Most common
48
+ host.endsWith('.localhost') ||
49
+ host === '::1' || // IPv6
50
+ normalizeIp(host).match(/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) // 127.0.0.0/8 range
51
+ );
52
+ exports.isLocalhostAddress = isLocalhostAddress;
53
+ // Check whether an incoming socket is the other end of one of our outgoing sockets:
54
+ const isSocketLoop = (outgoingSockets, incomingSocket) =>
55
+ // We effectively just compare the address & port: if they match, we've almost certainly got a loop.
56
+ // I don't think it's generally possible to see the same ip on different interfaces from one process (you need
57
+ // ip-netns network namespaces), but if it is, then there's a tiny chance of false positives here. If we have ip X,
58
+ // and on another interface somebody else has ip X, and they send a request with the same incoming port as an
59
+ // outgoing request we have on the other interface, we'll assume it's a loop. Extremely unlikely imo.
60
+ _.some([...outgoingSockets], (outgoingSocket) => {
61
+ if (!outgoingSocket.localAddress || !outgoingSocket.localPort) {
62
+ // It's possible for sockets in outgoingSockets to be closed, in which case these properties
63
+ // will be undefined. If so, we know they're not relevant to loops, so skip entirely.
64
+ return false;
65
+ }
66
+ else {
67
+ return normalizeIp(outgoingSocket.localAddress) === normalizeIp(incomingSocket.remoteAddress) &&
68
+ outgoingSocket.localPort === incomingSocket.remotePort;
69
+ }
70
+ });
71
+ exports.isSocketLoop = isSocketLoop;
72
+ function getParentSocket(socket) {
73
+ return socket._parent || // TLS wrapper
74
+ socket.stream || // SocketWrapper
75
+ socket._handle?._parentWrap?.stream; // HTTP/2 CONNECT'd TLS wrapper
76
+ }
77
+ const isSocketResetSupported = util_1.isNode
78
+ ? !!net.Socket.prototype.resetAndDestroy
79
+ : false; // Avoid errors in browsers
80
+ const requireSocketResetSupport = () => {
81
+ if (!isSocketResetSupported) {
82
+ throw new Error('Connection reset is only supported in Node v16.17+, v18.3.0+, or later');
83
+ }
84
+ };
85
+ exports.requireSocketResetSupport = requireSocketResetSupport;
86
+ const isHttp2Stream = (maybeStream) => 'httpVersion' in maybeStream &&
87
+ maybeStream.httpVersion?.startsWith('2');
88
+ /**
89
+ * Reset the socket where possible, or at least destroy it where that's not possible.
90
+ *
91
+ * This has a few cases for different layers of socket & tunneling, designed to
92
+ * simulate a real connection reset as closely as possible. That means, in general,
93
+ * we unwrap the connection as far as possible whilst still only affecting a single
94
+ * request.
95
+ *
96
+ * In practice, we unwrap HTTP/1 & TLS back as far as we can, until we hit either an
97
+ * HTTP/2 stream or a raw TCP connection. We then either send a RST_FRAME or a TCP RST
98
+ * to kill that connection.
99
+ */
100
+ function resetOrDestroy(requestOrSocket) {
101
+ let socket = (isHttp2Stream(requestOrSocket) && requestOrSocket.stream)
102
+ ? requestOrSocket.stream
103
+ : ('socket' in requestOrSocket && requestOrSocket.socket)
104
+ ? requestOrSocket.socket
105
+ : requestOrSocket;
106
+ while (socket instanceof tls.TLSSocket) {
107
+ const parent = getParentSocket(socket);
108
+ if (!parent)
109
+ break; // Not clear why, but it seems in some cases we run out of parents here
110
+ socket = parent;
111
+ }
112
+ if ('rstCode' in socket) {
113
+ // It's an HTTP/2 stream instance - let's kill it here.
114
+ // If it's the innermost stream, i.e. this is the stream of the request we're
115
+ // resetting, then we want to send an internal error. If it's a tunneling
116
+ // stream, then we want to send a CONNECT error:
117
+ const isOuterSocket = socket === requestOrSocket.stream;
118
+ const errorCode = isOuterSocket
119
+ ? http2.constants.NGHTTP2_INTERNAL_ERROR
120
+ : http2.constants.NGHTTP2_CONNECT_ERROR;
121
+ const h2Stream = socket;
122
+ h2Stream.close(errorCode);
123
+ }
124
+ else {
125
+ // Must be a net.Socket then, so we let's reset it for real:
126
+ if (isSocketResetSupported) {
127
+ try {
128
+ socket.resetAndDestroy();
129
+ }
130
+ catch (error) {
131
+ // This could fail in funky ways if the socket is not just the right kind
132
+ // of socket. We should still fail in that case, but it's useful to log
133
+ // some extra data first beforehand, so we can fix this if it ever happens:
134
+ console.warn(`Failed to reset on socket of type ${socket.constructor.name} with parent of type ${getParentSocket(socket)?.constructor.name}`);
135
+ throw error;
136
+ }
137
+ }
138
+ else {
139
+ socket.destroy();
140
+ }
141
+ }
142
+ }
143
+ ;
144
+ function buildSocketEventData(socket) {
145
+ const timingInfo = socket.__timingInfo ||
146
+ socket._parent?.__timingInfo ||
147
+ buildSocketTimingInfo();
148
+ // Attached in passThroughMatchingTls TLS sniffing logic in http-combo-server:
149
+ const tlsMetadata = socket.__tlsMetadata ||
150
+ socket._parent?.__tlsMetadata ||
151
+ {};
152
+ return {
153
+ hostname: socket.servername,
154
+ // These only work because of oncertcb monkeypatch in http-combo-server:
155
+ remoteIpAddress: socket.remoteAddress || // Normal case
156
+ socket._parent?.remoteAddress || // Pre-certCB error, e.g. timeout
157
+ socket.initialRemoteAddress, // Recorded by certCB monkeypatch
158
+ remotePort: socket.remotePort ||
159
+ socket._parent?.remotePort ||
160
+ socket.initialRemotePort,
161
+ tags: [],
162
+ timingEvents: {
163
+ startTime: timingInfo.initialSocket,
164
+ connectTimestamp: timingInfo.initialSocketTimestamp,
165
+ tunnelTimestamp: timingInfo.tunnelSetupTimestamp,
166
+ handshakeTimestamp: timingInfo.tlsConnectedTimestamp
167
+ },
168
+ tlsMetadata
169
+ };
170
+ }
171
+ function buildSocketTimingInfo() {
172
+ return { initialSocket: Date.now(), initialSocketTimestamp: now() };
173
+ }
174
+ //# sourceMappingURL=socket-util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket-util.js","sourceRoot":"","sources":["../../src/util/socket-util.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ export type CAOptions = (CertDataOptions | CertPathOptions);
2
+ export interface CertDataOptions extends BaseCAOptions {
3
+ key: string;
4
+ cert: string;
5
+ }
6
+ export interface CertPathOptions extends BaseCAOptions {
7
+ keyPath: string;
8
+ certPath: string;
9
+ }
10
+ export interface BaseCAOptions {
11
+ /**
12
+ * Minimum key length when generating certificates. Defaults to 2048.
13
+ */
14
+ keyLength?: number;
15
+ /**
16
+ * The countryName that will be used in the certificate for incoming TLS
17
+ * connections.
18
+ */
19
+ countryName?: string;
20
+ /**
21
+ * The localityName that will be used in the certificate for incoming TLS
22
+ * connections.
23
+ */
24
+ localityName?: string;
25
+ /**
26
+ * The organizationName that will be used in the certificate for incoming TLS
27
+ * connections.
28
+ */
29
+ organizationName?: string;
30
+ }
31
+ export type PEM = string | string[] | Buffer | Buffer[];
32
+ export type GeneratedCertificate = {
33
+ key: string;
34
+ cert: string;
35
+ ca: string;
36
+ };
37
+ /**
38
+ * Generate a CA certificate for mocking HTTPS.
39
+ *
40
+ * Returns a promise, for an object with key and cert properties,
41
+ * containing the generated private key and certificate in PEM format.
42
+ *
43
+ * These can be saved to disk, and their paths passed
44
+ * as HTTPS options to a Mockttp server.
45
+ */
46
+ export declare function generateCACertificate(options?: {
47
+ commonName?: string;
48
+ organizationName?: string;
49
+ countryName?: string;
50
+ bits?: number;
51
+ nameConstraints?: {
52
+ permitted?: string[];
53
+ };
54
+ }): Promise<{
55
+ key: string;
56
+ cert: string;
57
+ }>;
58
+ export declare function generateSPKIFingerprint(certPem: PEM): string;
59
+ export declare function getCA(options: CAOptions): Promise<CA>;
60
+ export declare class CA {
61
+ private caCert;
62
+ private caKey;
63
+ private options;
64
+ private certCache;
65
+ constructor(options: CertDataOptions);
66
+ generateCertificate(domain: string): GeneratedCertificate;
67
+ }
68
+ //# sourceMappingURL=tls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tls.d.ts","sourceRoot":"","sources":["../../src/util/tls.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,SAAS,GAAG,CAAC,eAAe,GAAG,eAAe,CAAC,CAAC;AAE5D,MAAM,WAAW,eAAgB,SAAQ,aAAa;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAgB,SAAQ,aAAa;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAExD,MAAM,MAAM,oBAAoB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAA;CACb,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,GAAE;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE;QACd,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;KACvB,CAAA;CACC;;;GA8DL;AAkDD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,GAAG,UASnD;AASD,wBAAsB,KAAK,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,CAoB3D;AAaD,qBAAa,EAAE;IACX,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,OAAO,CAAkB;IAEjC,OAAO,CAAC,SAAS,CAA6C;gBAElD,OAAO,EAAE,eAAe;IAiBpC,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB;CA2F5D"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CA = void 0;
4
+ exports.generateCACertificate = generateCACertificate;
5
+ exports.generateSPKIFingerprint = generateSPKIFingerprint;
6
+ exports.getCA = getCA;
7
+ const _ = require("lodash");
8
+ const fs = require("fs/promises");
9
+ const uuid_1 = require("uuid");
10
+ const forge = require("node-forge");
11
+ const { asn1, pki, md, util } = forge;
12
+ ;
13
+ /**
14
+ * Generate a CA certificate for mocking HTTPS.
15
+ *
16
+ * Returns a promise, for an object with key and cert properties,
17
+ * containing the generated private key and certificate in PEM format.
18
+ *
19
+ * These can be saved to disk, and their paths passed
20
+ * as HTTPS options to a Mockttp server.
21
+ */
22
+ async function generateCACertificate(options = {}) {
23
+ options = _.defaults({}, options, {
24
+ commonName: 'Mockttp Testing CA - DO NOT TRUST - TESTING ONLY',
25
+ organizationName: 'Mockttp',
26
+ countryName: 'XX', // ISO-3166-1 alpha-2 'unknown country' code
27
+ bits: 2048,
28
+ });
29
+ const keyPair = await new Promise((resolve, reject) => {
30
+ pki.rsa.generateKeyPair({ bits: options.bits }, (error, keyPair) => {
31
+ if (error)
32
+ reject(error);
33
+ else
34
+ resolve(keyPair);
35
+ });
36
+ });
37
+ const cert = pki.createCertificate();
38
+ cert.publicKey = keyPair.publicKey;
39
+ cert.serialNumber = generateSerialNumber();
40
+ cert.validity.notBefore = new Date();
41
+ // Make it valid for the last 24h - helps in cases where clocks slightly disagree
42
+ cert.validity.notBefore.setDate(cert.validity.notBefore.getDate() - 1);
43
+ cert.validity.notAfter = new Date();
44
+ // Valid for the next year by default.
45
+ cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 1);
46
+ cert.setSubject([
47
+ // All of these are required for a fully valid CA cert that will be accepted when imported anywhere:
48
+ { name: 'commonName', value: options.commonName },
49
+ { name: 'countryName', value: options.countryName },
50
+ { name: 'organizationName', value: options.organizationName }
51
+ ]);
52
+ const extensions = [
53
+ { name: 'basicConstraints', cA: true, critical: true },
54
+ { name: 'keyUsage', keyCertSign: true, digitalSignature: true, nonRepudiation: true, cRLSign: true, critical: true },
55
+ { name: 'subjectKeyIdentifier' },
56
+ ];
57
+ const permittedDomains = options.nameConstraints?.permitted || [];
58
+ if (permittedDomains.length > 0) {
59
+ extensions.push({
60
+ critical: true,
61
+ id: '2.5.29.30',
62
+ name: 'nameConstraints',
63
+ value: generateNameConstraints({
64
+ permitted: permittedDomains,
65
+ }),
66
+ });
67
+ }
68
+ cert.setExtensions(extensions);
69
+ // Self-issued too
70
+ cert.setIssuer(cert.subject.attributes);
71
+ // Self-sign the certificate - we're the root
72
+ cert.sign(keyPair.privateKey, md.sha256.create());
73
+ return {
74
+ key: pki.privateKeyToPem(keyPair.privateKey),
75
+ cert: pki.certificateToPem(cert)
76
+ };
77
+ }
78
+ /**
79
+ * Generate name constraints in conformance with
80
+ * [RFC 5280 § 4.2.1.10](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.10)
81
+ */
82
+ function generateNameConstraints(input) {
83
+ const domainsToSequence = (ips) => ips.map((domain) => {
84
+ return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
85
+ asn1.create(asn1.Class.CONTEXT_SPECIFIC, 2, false, util.encodeUtf8(domain)),
86
+ ]);
87
+ });
88
+ const permittedAndExcluded = [];
89
+ if (input.permitted && input.permitted.length > 0) {
90
+ permittedAndExcluded.push(asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, domainsToSequence(input.permitted)));
91
+ }
92
+ return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, permittedAndExcluded);
93
+ }
94
+ function generateSPKIFingerprint(certPem) {
95
+ let cert = pki.certificateFromPem(certPem.toString('utf8'));
96
+ return util.encode64(pki.getPublicKeyFingerprint(cert.publicKey, {
97
+ type: 'SubjectPublicKeyInfo',
98
+ md: md.sha256.create(),
99
+ encoding: 'binary'
100
+ }));
101
+ }
102
+ // Generates a unique serial number for a certificate as a hex string:
103
+ function generateSerialNumber() {
104
+ return 'A' + (0, uuid_1.v4)().replace(/-/g, '');
105
+ // We add a leading 'A' to ensure it's always positive (not 'F') and always
106
+ // valid (e.g. leading 000 is bad padding, and would be unparseable).
107
+ }
108
+ async function getCA(options) {
109
+ let certOptions;
110
+ if ('key' in options && 'cert' in options) {
111
+ certOptions = options;
112
+ }
113
+ else if ('keyPath' in options && 'certPath' in options) {
114
+ certOptions = await Promise.all([
115
+ fs.readFile(options.keyPath, 'utf8'),
116
+ fs.readFile(options.certPath, 'utf8')
117
+ ]).then(([keyContents, certContents]) => ({
118
+ ..._.omit(options, ['keyPath', 'certPath']),
119
+ key: keyContents,
120
+ cert: certContents
121
+ }));
122
+ }
123
+ else {
124
+ throw new Error('Unrecognized https options: you need to provide either a keyPath & certPath, or a key & cert.');
125
+ }
126
+ return new CA(certOptions);
127
+ }
128
+ // We share a single keypair across all certificates in this process, and
129
+ // instantiate it once when the first CA is created, because it can be
130
+ // expensive (depending on the key length).
131
+ // This would be a terrible idea for a real server, but for a mock server
132
+ // it's ok - if anybody can steal this, they can steal the CA cert anyway.
133
+ let KEY_PAIR;
134
+ class CA {
135
+ constructor(options) {
136
+ this.caKey = pki.privateKeyFromPem(options.key.toString());
137
+ this.caCert = pki.certificateFromPem(options.cert.toString());
138
+ this.certCache = {};
139
+ this.options = options ?? {};
140
+ const keyLength = options.keyLength || 2048;
141
+ if (!KEY_PAIR || KEY_PAIR.length < keyLength) {
142
+ // If we have no key, or not a long enough one, generate one.
143
+ KEY_PAIR = Object.assign(pki.rsa.generateKeyPair(keyLength), { length: keyLength });
144
+ }
145
+ }
146
+ generateCertificate(domain) {
147
+ // TODO: Expire domains from the cache? Based on their actual expiry?
148
+ if (this.certCache[domain])
149
+ return this.certCache[domain];
150
+ if (domain.includes('_')) {
151
+ // TLS certificates cannot cover domains with underscores, bizarrely. More info:
152
+ // https://www.digicert.com/kb/ssl-support/underscores-not-allowed-in-fqdns.htm
153
+ // To fix this, we use wildcards instead. This is only possible for one level of
154
+ // certificate, and only for subdomains, so our options are a little limited, but
155
+ // this should be very rare (because it's not supported elsewhere either).
156
+ const [, ...otherParts] = domain.split('.');
157
+ if (otherParts.length <= 1 || // *.com is never valid
158
+ otherParts.some(p => p.includes('_'))) {
159
+ throw new Error(`Cannot generate certificate for domain due to underscores: ${domain}`);
160
+ }
161
+ // Replace the first part with a wildcard to solve the problem:
162
+ domain = `*.${otherParts.join('.')}`;
163
+ }
164
+ let cert = pki.createCertificate();
165
+ cert.publicKey = KEY_PAIR.publicKey;
166
+ cert.serialNumber = generateSerialNumber();
167
+ cert.validity.notBefore = new Date();
168
+ // Make it valid for the last 24h - helps in cases where clocks slightly disagree.
169
+ cert.validity.notBefore.setDate(cert.validity.notBefore.getDate() - 1);
170
+ cert.validity.notAfter = new Date();
171
+ // Valid for the next year by default. TODO: Shorten (and expire the cache) automatically.
172
+ cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 1);
173
+ cert.setSubject([
174
+ ...(domain[0] === '*'
175
+ ? [] // We skip the CN (deprecated, rarely used) for wildcards, since they can't be used here.
176
+ : [{ name: 'commonName', value: domain }]),
177
+ { name: 'countryName', value: this.options?.countryName ?? 'XX' }, // ISO-3166-1 alpha-2 'unknown country' code
178
+ { name: 'localityName', value: this.options?.localityName ?? 'Unknown' },
179
+ { name: 'organizationName', value: this.options?.organizationName ?? 'Mockttp Cert - DO NOT TRUST' }
180
+ ]);
181
+ cert.setIssuer(this.caCert.subject.attributes);
182
+ const policyList = forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
183
+ forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.SEQUENCE, true, [
184
+ forge.asn1.create(forge.asn1.Class.UNIVERSAL, forge.asn1.Type.OID, false, forge.asn1.oidToDer('2.5.29.32.0').getBytes() // Mark all as Domain Verified
185
+ )
186
+ ])
187
+ ]);
188
+ cert.setExtensions([
189
+ { name: 'basicConstraints', cA: false, critical: true },
190
+ { name: 'keyUsage', digitalSignature: true, keyEncipherment: true, critical: true },
191
+ { name: 'extKeyUsage', serverAuth: true, clientAuth: true },
192
+ {
193
+ name: 'subjectAltName',
194
+ altNames: [{
195
+ type: 2,
196
+ value: domain
197
+ }]
198
+ },
199
+ { name: 'certificatePolicies', value: policyList },
200
+ { name: 'subjectKeyIdentifier' },
201
+ {
202
+ name: 'authorityKeyIdentifier',
203
+ // We have to calculate this ourselves due to
204
+ // https://github.com/digitalbazaar/forge/issues/462
205
+ keyIdentifier: this.caCert // generateSubjectKeyIdentifier is missing from node-forge types
206
+ .generateSubjectKeyIdentifier().getBytes()
207
+ }
208
+ ]);
209
+ cert.sign(this.caKey, md.sha256.create());
210
+ const generatedCertificate = {
211
+ key: pki.privateKeyToPem(KEY_PAIR.privateKey),
212
+ cert: pki.certificateToPem(cert),
213
+ ca: pki.certificateToPem(this.caCert)
214
+ };
215
+ this.certCache[domain] = generatedCertificate;
216
+ return generatedCertificate;
217
+ }
218
+ }
219
+ exports.CA = CA;
220
+ //# sourceMappingURL=tls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tls.js","sourceRoot":"","sources":["../../src/util/tls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
2
+ export type RequireProps<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
3
+ export type MaybePromise<T> = T | Promise<T>;
4
+ type SubsetKeyOf<T, Ks extends keyof T = keyof T> = Ks;
5
+ export type Replace<T, KV extends {
6
+ [K in SubsetKeyOf<T, any>]: unknown;
7
+ }> = Omit<T, keyof KV> & {
8
+ [K in keyof KV]: KV[K];
9
+ };
10
+ export type Mutable<T> = {
11
+ -readonly [K in keyof T]: T[K];
12
+ };
13
+ export {};
14
+ //# sourceMappingURL=type-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-utils.d.ts","sourceRoot":"","sources":["../../src/util/type-utils.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAGtD,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IACzC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE7C,KAAK,WAAW,CAAC,CAAC,EAAE,EAAE,SAAS,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;AACvD,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,EAAE,SAAS;KAAG,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,OAAO;CAAE,IACrE,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG;KAAG,CAAC,IAAI,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;CAAE,CAAC;AAEnD,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;IACrB,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACjC,CAAA"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=type-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../src/util/type-utils.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ export declare const isAbsoluteUrl: (url: string) => boolean;
2
+ export declare const isRelativeUrl: (url: string) => boolean;
3
+ export declare const isAbsoluteProtocollessUrl: (url: string) => boolean;
4
+ export declare const getUrlWithoutProtocol: (url: string) => string;
5
+ export declare const getPathFromAbsoluteUrl: (url: string) => string;
6
+ export declare const getEffectivePort: (url: {
7
+ protocol: string | null;
8
+ port: string | null;
9
+ }) => number;
10
+ /**
11
+ * Normalizes URLs to the form used when matching them.
12
+ *
13
+ * This accepts URLs in all three formats: relative, absolute, and protocolless-absolute,
14
+ * and returns them in the same format but normalized.
15
+ */
16
+ export declare const normalizeUrl: (url: string) => string;
17
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/util/url.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa,QAAS,MAAM,YAEG,CAAC;AAE7C,eAAO,MAAM,aAAa,QAAS,MAAM,YAClB,CAAC;AAExB,eAAO,MAAM,yBAAyB,QAAS,MAAM,YACP,CAAC;AAE/C,eAAO,MAAM,qBAAqB,QAAS,MAAM,KAAG,MAEnD,CAAA;AAED,eAAO,MAAM,sBAAsB,QAAS,MAAM,WAOjD,CAAA;AAED,eAAO,MAAM,gBAAgB,QAAS;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,WAQrF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAkEvC,CAAC"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeUrl = exports.getEffectivePort = exports.getPathFromAbsoluteUrl = exports.getUrlWithoutProtocol = exports.isAbsoluteProtocollessUrl = exports.isRelativeUrl = exports.isAbsoluteUrl = void 0;
4
+ const url = require("url");
5
+ const _ = require("lodash");
6
+ const util_1 = require("./util");
7
+ // Is this URL fully qualified?
8
+ // Note that this supports only HTTP - no websockets or anything else.
9
+ const isAbsoluteUrl = (url) => url.toLowerCase().startsWith('http://') ||
10
+ url.toLowerCase().startsWith('https://');
11
+ exports.isAbsoluteUrl = isAbsoluteUrl;
12
+ const isRelativeUrl = (url) => url.startsWith('/');
13
+ exports.isRelativeUrl = isRelativeUrl;
14
+ const isAbsoluteProtocollessUrl = (url) => !(0, exports.isAbsoluteUrl)(url) && !(0, exports.isRelativeUrl)(url);
15
+ exports.isAbsoluteProtocollessUrl = isAbsoluteProtocollessUrl;
16
+ const getUrlWithoutProtocol = (url) => {
17
+ return url.split('://', 2).slice(-1).join('');
18
+ };
19
+ exports.getUrlWithoutProtocol = getUrlWithoutProtocol;
20
+ const getPathFromAbsoluteUrl = (url) => {
21
+ const pathIndex = (0, util_1.nthIndexOf)(url, '/', 3);
22
+ if (pathIndex !== -1) {
23
+ return url.slice(pathIndex);
24
+ }
25
+ else {
26
+ return '';
27
+ }
28
+ };
29
+ exports.getPathFromAbsoluteUrl = getPathFromAbsoluteUrl;
30
+ const getEffectivePort = (url) => {
31
+ if (url.port) {
32
+ return parseInt(url.port, 10);
33
+ }
34
+ else if (url.protocol === 'https:' || url.protocol === 'wss:') {
35
+ return 443;
36
+ }
37
+ else {
38
+ return 80;
39
+ }
40
+ };
41
+ exports.getEffectivePort = getEffectivePort;
42
+ /**
43
+ * Normalizes URLs to the form used when matching them.
44
+ *
45
+ * This accepts URLs in all three formats: relative, absolute, and protocolless-absolute,
46
+ * and returns them in the same format but normalized.
47
+ */
48
+ exports.normalizeUrl = _.memoize((urlInput) => {
49
+ let parsedUrl;
50
+ let isProtocolless = false;
51
+ try {
52
+ // Strip the query and anything following it
53
+ const queryIndex = urlInput.indexOf('?');
54
+ if (queryIndex !== -1) {
55
+ urlInput = urlInput.slice(0, queryIndex);
56
+ }
57
+ if ((0, exports.isAbsoluteProtocollessUrl)(urlInput)) {
58
+ parsedUrl = url.parse('http://' + urlInput);
59
+ isProtocolless = true;
60
+ }
61
+ else {
62
+ parsedUrl = url.parse(urlInput);
63
+ }
64
+ // Trim out lots of the bits we don't like:
65
+ delete parsedUrl.host;
66
+ delete parsedUrl.query;
67
+ delete parsedUrl.search;
68
+ delete parsedUrl.hash;
69
+ if (parsedUrl.pathname) {
70
+ parsedUrl.pathname = parsedUrl.pathname.replace(/\%[A-Fa-z0-9]{2}/g, (encoded) => encoded.toUpperCase()).replace(/[^\u0000-\u007F]+/g, (unicodeChar) => encodeURIComponent(unicodeChar));
71
+ }
72
+ if (parsedUrl.hostname && parsedUrl.hostname.endsWith('.')) {
73
+ parsedUrl.hostname = parsedUrl.hostname.slice(0, -1);
74
+ }
75
+ if ((parsedUrl.protocol === 'https:' && parsedUrl.port === '443') ||
76
+ (parsedUrl.protocol === 'http:' && parsedUrl.port === '80')) {
77
+ delete parsedUrl.port;
78
+ }
79
+ }
80
+ catch (e) {
81
+ console.log(`Failed to normalize URL ${urlInput}`);
82
+ console.log(e);
83
+ if (!parsedUrl)
84
+ return urlInput; // Totally unparseble: use as-is
85
+ // If we've successfully parsed it, we format what we managed
86
+ // and leave it at that:
87
+ }
88
+ let normalizedUrl = url.format(parsedUrl);
89
+ // If the URL came in with no protocol, it should leave with
90
+ // no protocol (protocol added temporarily above to allow parsing)
91
+ if (isProtocolless) {
92
+ normalizedUrl = normalizedUrl.slice('http://'.length);
93
+ }
94
+ return normalizedUrl;
95
+ });
96
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/util/url.ts"],"names":[],"mappings":"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"}