From 8135b5bec11beaf95d3529001f52231f665f9695 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Fri, 11 Nov 2022 17:41:01 -0500 Subject: [PATCH 1/9] feat: dnslink support --- README.md | 9 +- package-lock.json | 527 +++++++++++++++++++++++++----------------- package.json | 1 + src/bzz-link.ts | 53 ++++- src/config.ts | 10 + src/server.ts | 34 ++- test/bzz-link.spec.ts | 25 +- 7 files changed, 421 insertions(+), 238 deletions(-) diff --git a/README.md b/README.md index 5d6f9cc8..821962b4 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,9 @@ allows to have better security model for your web applications. In order to use Bzz.link, set the `HOSTNAME` environment variable, and either or both of `CID_SUBDOMAINS` and `ENS_SUBDOMAINS` according to your requirements. You may also need to set up DNS with wildcard subdomain support. +Another option to use Bzz.link, set the `DNSLINK` environment variable, and `DOMAIN_LOOKUP` according to the domain with +the TXT record settings. + ### Reupload pinned content It can reupload existing pinned content that appear as not retrievable. To enable this, provide `REAUPLOAD_PERIOD` @@ -144,8 +147,10 @@ npm run start | POSTAGE_USAGE_MAX | 0.9 | Usage percentage at which existing postage stamp should not be considered viable ( values 0 to 1). | | POSTAGE_TTL_MIN | `autobuy`: 5 \* POSTAGE_REFRESH_PERIOD. `extends TTL`: undefined | In `autobuy`, Minimal time to live for the postage stamps to still be considered for upload (in seconds). In `extends TTL` is mandatory and required to be above 60 seconds | | POSTAGE_REFRESH_PERIOD | 60 | How frequently are the postage stamps checked in seconds. | -| CID_SUBDOMAINS | false | Enables Bzz.link subdomain translation functionality for CIDs. | -| ENS_SUBDOMAINS | false | Enables Bzz.link subdomain translation functionality for ENS. | +| CID_SUBDOMAINS | false | Enables Bzz.link subdomain translation functionality for CIDs. | +| ENS_SUBDOMAINS | false | Enables Bzz.link subdomain translation functionality for ENS. | +| DNSLINK | false | Enables Bzz.link that uses TXT records of a certain domain | +| DOMAIN_LOOKUP | undefined | Set the domain that holds the TXT records with the `dnslink` settings. | | REMOVE_PIN_HEADER | true | Removes swarm-pin header on all proxy requests. | | `LOG_LEVEL` | info | Log level that is outputted (values: `critical`, `error`, `warn`, `info`, `verbose`, `debug`) | | POSTAGE_EXTENDSTTL | false | Enables extends TTL feature. Works along with POSTAGE_AMOUNT | diff --git a/package-lock.json b/package-lock.json index 4b32050a..a9c8d58b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.6.0", "license": "BSD-3-Clause", "dependencies": { + "@dnslink/js": "^0.13.0", "@ethersphere/bee-js": "^5.0.0", "@ethersphere/swarm-cid": "^0.1.0", "express": "^4.18.1", @@ -48,7 +49,7 @@ "typescript": "^4.8.3" }, "engines": { - "bee": "1.6.0-6ceadd35", + "bee": "1.7.0-bbf13011", "node": ">=12.0.0", "npm": ">=6.0.0" } @@ -57,7 +58,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -70,7 +70,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -83,7 +82,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -95,7 +93,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.1.tgz", "integrity": "sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -104,7 +101,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.1.tgz", "integrity": "sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -134,7 +130,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -146,18 +141,16 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", - "dev": true, + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.4.tgz", + "integrity": "sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==", "dependencies": { - "@babel/types": "^7.19.0", + "@babel/types": "^7.20.2", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -169,7 +162,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz", "integrity": "sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.19.1", "@babel/helper-validator-option": "^7.18.6", @@ -187,7 +179,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -196,7 +187,6 @@ "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -205,7 +195,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, "dependencies": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" @@ -218,7 +207,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, @@ -230,7 +218,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, @@ -239,19 +226,18 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", - "dev": true, + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", + "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -261,18 +247,16 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", - "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -282,7 +266,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, "dependencies": { "@babel/types": "^7.18.6" }, @@ -291,10 +274,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", - "dev": true, + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "engines": { "node": ">=6.9.0" } @@ -303,7 +285,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -312,7 +293,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -321,7 +301,6 @@ "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", - "dev": true, "dependencies": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.0", @@ -335,7 +314,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -349,7 +327,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -361,7 +338,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -375,7 +351,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -383,14 +358,12 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -399,7 +372,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -408,7 +380,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -590,11 +561,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.19.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz", + "integrity": "sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-simple-access": "^7.19.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/template": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.18.10", @@ -608,7 +594,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -617,19 +602,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz", - "integrity": "sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==", - "dev": true, + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz", + "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.0", + "@babel/generator": "^7.20.1", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.1", - "@babel/types": "^7.19.0", + "@babel/parser": "^7.20.1", + "@babel/types": "^7.20.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -638,10 +622,9 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/parser": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", - "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==", - "dev": true, + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", + "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -650,13 +633,12 @@ } }, "node_modules/@babel/types": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", - "dev": true, + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.2.tgz", + "integrity": "sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==", "dependencies": { - "@babel/helper-string-parser": "^7.18.10", - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, "engines": { @@ -949,6 +931,20 @@ "kuler": "^2.0.0" } }, + "node_modules/@dnslink/js": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@dnslink/js/-/js-0.13.0.tgz", + "integrity": "sha512-78v97k58J8SN+iSOrGdU3rSdriO5+EvisSHGldSLRDBkQoZBsoffYPM76CjYV+mf+mCuFPn6pq3AYNYax/X69A==", + "dependencies": { + "@leichtgewicht/esm2umd": "^0.4.0", + "abort-controller": "^3.0.0", + "dns-query": "^0.11.1" + }, + "bin": { + "dnslink": "bin/dnslink", + "dnslink-js": "bin/dnslink-js" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", @@ -1804,7 +1800,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1818,7 +1813,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -1827,7 +1821,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -1835,19 +1828,66 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.15", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@leichtgewicht/base64-codec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz", + "integrity": "sha512-0cgP4lRBzh3F4tlpTfs7F+PJyBN8j5yUC9KrQFWp/bREswgzZVHE8T1rNyRDWgvALwwpPtnJDQfqWUmxI33Epg==" + }, + "node_modules/@leichtgewicht/dns-packet": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@leichtgewicht/dns-packet/-/dns-packet-6.0.3.tgz", + "integrity": "sha512-qmVHhFBFiBvPsk/wJ/EdoWHb+tGkzY4haybmDPukhF6w0+8wpEbrHTIRE9LzeUu2P0bAbmrK8WOXt5V5QN6jQg==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.4", + "bytes.js": "^0.0.2", + "utf8-bytes": "^0.0.1", + "utf8-codec": "^1.0.0", + "utf8-length": "^0.0.1", + "utf8-string-bytes": "^1.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@leichtgewicht/dns-socket": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@leichtgewicht/dns-socket/-/dns-socket-5.0.0.tgz", + "integrity": "sha512-Sbrn/OG0HTTPGSkwIDCHy8/tUI6UglIzFsMNjzZn/Na1/i5owSm6rVi9CfKNNjRcUlYEzICELYW6EoZdjwVY2A==", + "dependencies": { + "@leichtgewicht/dns-packet": "^6.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@leichtgewicht/esm2umd": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@leichtgewicht/esm2umd/-/esm2umd-0.4.0.tgz", + "integrity": "sha512-WM1SxkCfvta2ftweflGE7yEiGvmcMLSm+FiwkKNDLiCZwfVPoAv5lk7ctx1TEgFHxeq1LAd7E3wJY945MqQieA==", + "dependencies": { + "@babel/core": "^7", + "@babel/plugin-transform-modules-commonjs": "^7" + }, + "bin": { + "esm2umd": "bin/esm2umd.mjs" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2960,7 +3000,6 @@ "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3065,6 +3104,11 @@ "node": ">= 0.8" } }, + "node_modules/bytes.js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/bytes.js/-/bytes.js-0.0.2.tgz", + "integrity": "sha512-KrLm4hv5Qs9w6b0U7h1bCdqxrsf+e9QMsfHeyQFzAz94x/5Aqa+FTEUSNBtt5d2VuV3Hfiea3c4ti74RZDDYkg==" + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -3128,7 +3172,6 @@ "version": "1.0.30001412", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3429,7 +3472,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "dependencies": { "safe-buffer": "~5.1.1" } @@ -3437,8 +3479,7 @@ "node_modules/convert-source-map/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/cookie": { "version": "0.5.0", @@ -3585,7 +3626,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -3801,6 +3841,21 @@ "node": ">=8" } }, + "node_modules/dns-query": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/dns-query/-/dns-query-0.11.2.tgz", + "integrity": "sha512-zF8qxQpqCB467o4A63DLpQClo77H642JEKMx0Ra9GFww7Rx0234Fo8NoG0LBoSBZxamWkXfLxhzDG19bTBHvXQ==", + "dependencies": { + "@leichtgewicht/base64-codec": "^1.0.0", + "@leichtgewicht/dns-packet": "^6.0.2", + "@leichtgewicht/dns-socket": "^5.0.0", + "@leichtgewicht/ip-codec": "^2.0.4", + "utf8-codec": "^1.0.0" + }, + "bin": { + "dns-query": "bin/dns-query" + } + }, "node_modules/docker-modem": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.6.tgz", @@ -3883,8 +3938,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.264", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", - "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", - "dev": true + "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -3953,7 +4007,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -4907,7 +4960,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -5022,7 +5074,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -6767,8 +6818,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", @@ -6854,7 +6904,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -6884,7 +6933,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -7466,8 +7514,7 @@ "node_modules/node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, "node_modules/nodemon": { "version": "2.0.20", @@ -7816,8 +7863,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -9209,7 +9255,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -9511,7 +9556,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -9564,6 +9608,26 @@ "node": ">=6.14.2" } }, + "node_modules/utf8-bytes": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/utf8-bytes/-/utf8-bytes-0.0.1.tgz", + "integrity": "sha512-GifWmJAx2qAXT+lZLhbkWhBsy7pr6xWHiPWlVToDiELdWgZwt4Ogjf9tlgvKuALzTFR/d+EPQQI9ogJV3957Jg==" + }, + "node_modules/utf8-codec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utf8-codec/-/utf8-codec-1.0.0.tgz", + "integrity": "sha512-S/QSLezp3qvG4ld5PUfXiH7mCFxLKjSVZRFkB3DOjgwHuJPFDkInAXc/anf7BAbHt/D38ozDzL+QMZ6/7gsI6w==" + }, + "node_modules/utf8-length": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/utf8-length/-/utf8-length-0.0.1.tgz", + "integrity": "sha512-j/XH2ftofBiobnyApxlN/J6j/ixwT89WEjDcjT66d2i0+GIn9RZfzt8lpEXXE4jUe4NsjBSUq70kS2euQ4nnMw==" + }, + "node_modules/utf8-string-bytes": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/utf8-string-bytes/-/utf8-string-bytes-1.0.3.tgz", + "integrity": "sha512-i/I1Omf6lADjVBlwJpQifZOePV15snHny9w04+lc71+3t8PyWuLC/7clyoOSHOBNGXFe2PAGxmTiZ+Z4HWsPyw==" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -9921,7 +9985,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -9931,7 +9994,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -9943,7 +10005,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, "requires": { "@babel/highlight": "^7.18.6" } @@ -9951,14 +10012,12 @@ "@babel/compat-data": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.1.tgz", - "integrity": "sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==", - "dev": true + "integrity": "sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==" }, "@babel/core": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.1.tgz", "integrity": "sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==", - "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -9980,24 +10039,21 @@ "@babel/parser": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", - "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==", - "dev": true + "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==" }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, "@babel/generator": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", - "integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", - "dev": true, + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.4.tgz", + "integrity": "sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==", "requires": { - "@babel/types": "^7.19.0", + "@babel/types": "^7.20.2", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" } @@ -10006,7 +10062,6 @@ "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz", "integrity": "sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==", - "dev": true, "requires": { "@babel/compat-data": "^7.19.1", "@babel/helper-validator-option": "^7.18.6", @@ -10017,22 +10072,19 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, "@babel/helper-environment-visitor": { "version": "7.18.9", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" }, "@babel/helper-function-name": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, "requires": { "@babel/template": "^7.18.10", "@babel/types": "^7.19.0" @@ -10042,7 +10094,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, "requires": { "@babel/types": "^7.18.6" } @@ -10051,74 +10102,65 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, "requires": { "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", - "dev": true, + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz", + "integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==", "requires": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/traverse": "^7.20.1", + "@babel/types": "^7.20.2" } }, "@babel/helper-plugin-utils": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", - "dev": true + "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==" }, "@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", - "dev": true, + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.20.2" } }, "@babel/helper-split-export-declaration": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, "requires": { "@babel/types": "^7.18.6" } }, "@babel/helper-string-parser": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", - "dev": true + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" }, "@babel/helper-validator-identifier": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" }, "@babel/helper-validator-option": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" }, "@babel/helpers": { "version": "7.19.0", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", - "dev": true, "requires": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.19.0", @@ -10129,7 +10171,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", @@ -10140,7 +10181,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -10149,7 +10189,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -10160,7 +10199,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -10168,26 +10206,22 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -10317,11 +10351,20 @@ "@babel/helper-plugin-utils": "^7.18.6" } }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.19.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz", + "integrity": "sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==", + "requires": { + "@babel/helper-module-transforms": "^7.19.6", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-simple-access": "^7.19.4" + } + }, "@babel/template": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", - "dev": true, "requires": { "@babel/code-frame": "^7.18.6", "@babel/parser": "^7.18.10", @@ -10331,45 +10374,41 @@ "@babel/parser": { "version": "7.19.1", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", - "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==", - "dev": true + "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==" } } }, "@babel/traverse": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz", - "integrity": "sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==", - "dev": true, + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.1.tgz", + "integrity": "sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==", "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.0", + "@babel/generator": "^7.20.1", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.19.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.1", - "@babel/types": "^7.19.0", + "@babel/parser": "^7.20.1", + "@babel/types": "^7.20.0", "debug": "^4.1.0", "globals": "^11.1.0" }, "dependencies": { "@babel/parser": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", - "integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==", - "dev": true + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.3.tgz", + "integrity": "sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==" } } }, "@babel/types": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", - "integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", - "dev": true, + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.2.tgz", + "integrity": "sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==", "requires": { - "@babel/helper-string-parser": "^7.18.10", - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } }, @@ -10606,6 +10645,16 @@ "kuler": "^2.0.0" } }, + "@dnslink/js": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@dnslink/js/-/js-0.13.0.tgz", + "integrity": "sha512-78v97k58J8SN+iSOrGdU3rSdriO5+EvisSHGldSLRDBkQoZBsoffYPM76CjYV+mf+mCuFPn6pq3AYNYax/X69A==", + "requires": { + "@leichtgewicht/esm2umd": "^0.4.0", + "abort-controller": "^3.0.0", + "dns-query": "^0.11.1" + } + }, "@eslint/eslintrc": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", @@ -11299,7 +11348,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -11309,31 +11357,67 @@ "@jridgewell/resolve-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { "version": "0.3.15", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", - "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@leichtgewicht/base64-codec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz", + "integrity": "sha512-0cgP4lRBzh3F4tlpTfs7F+PJyBN8j5yUC9KrQFWp/bREswgzZVHE8T1rNyRDWgvALwwpPtnJDQfqWUmxI33Epg==" + }, + "@leichtgewicht/dns-packet": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@leichtgewicht/dns-packet/-/dns-packet-6.0.3.tgz", + "integrity": "sha512-qmVHhFBFiBvPsk/wJ/EdoWHb+tGkzY4haybmDPukhF6w0+8wpEbrHTIRE9LzeUu2P0bAbmrK8WOXt5V5QN6jQg==", + "requires": { + "@leichtgewicht/ip-codec": "^2.0.4", + "bytes.js": "^0.0.2", + "utf8-bytes": "^0.0.1", + "utf8-codec": "^1.0.0", + "utf8-length": "^0.0.1", + "utf8-string-bytes": "^1.0.3" + } + }, + "@leichtgewicht/dns-socket": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@leichtgewicht/dns-socket/-/dns-socket-5.0.0.tgz", + "integrity": "sha512-Sbrn/OG0HTTPGSkwIDCHy8/tUI6UglIzFsMNjzZn/Na1/i5owSm6rVi9CfKNNjRcUlYEzICELYW6EoZdjwVY2A==", + "requires": { + "@leichtgewicht/dns-packet": "^6.0.0" + } + }, + "@leichtgewicht/esm2umd": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@leichtgewicht/esm2umd/-/esm2umd-0.4.0.tgz", + "integrity": "sha512-WM1SxkCfvta2ftweflGE7yEiGvmcMLSm+FiwkKNDLiCZwfVPoAv5lk7ctx1TEgFHxeq1LAd7E3wJY945MqQieA==", + "requires": { + "@babel/core": "^7", + "@babel/plugin-transform-modules-commonjs": "^7" + } + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -12246,7 +12330,6 @@ "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001400", "electron-to-chromium": "^1.4.251", @@ -12308,6 +12391,11 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, + "bytes.js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/bytes.js/-/bytes.js-0.0.2.tgz", + "integrity": "sha512-KrLm4hv5Qs9w6b0U7h1bCdqxrsf+e9QMsfHeyQFzAz94x/5Aqa+FTEUSNBtt5d2VuV3Hfiea3c4ti74RZDDYkg==" + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -12351,8 +12439,7 @@ "caniuse-lite": { "version": "1.0.30001412", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", - "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", - "dev": true + "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==" }, "chalk": { "version": "4.1.2", @@ -12587,7 +12674,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" }, @@ -12595,8 +12681,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -12713,7 +12798,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -12882,6 +12966,18 @@ "path-type": "^4.0.0" } }, + "dns-query": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/dns-query/-/dns-query-0.11.2.tgz", + "integrity": "sha512-zF8qxQpqCB467o4A63DLpQClo77H642JEKMx0Ra9GFww7Rx0234Fo8NoG0LBoSBZxamWkXfLxhzDG19bTBHvXQ==", + "requires": { + "@leichtgewicht/base64-codec": "^1.0.0", + "@leichtgewicht/dns-packet": "^6.0.2", + "@leichtgewicht/dns-socket": "^5.0.0", + "@leichtgewicht/ip-codec": "^2.0.4", + "utf8-codec": "^1.0.0" + } + }, "docker-modem": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.6.tgz", @@ -12948,8 +13044,7 @@ "electron-to-chromium": { "version": "1.4.264", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", - "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", - "dev": true + "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==" }, "elliptic": { "version": "6.5.4", @@ -13008,8 +13103,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-html": { "version": "1.0.3", @@ -13717,8 +13811,7 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-caller-file": { "version": "2.0.5", @@ -13796,8 +13889,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "globby": { "version": "11.1.0", @@ -15211,8 +15303,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.14.1", @@ -15271,8 +15362,7 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-parse-even-better-errors": { "version": "2.3.1", @@ -15295,8 +15385,7 @@ "json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, "jsonfile": { "version": "6.1.0", @@ -15722,8 +15811,7 @@ "node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" }, "nodemon": { "version": "2.0.20", @@ -15980,8 +16068,7 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.1", @@ -17029,8 +17116,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, "to-regex-range": { "version": "5.0.1", @@ -17226,7 +17312,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", - "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -17259,6 +17344,26 @@ "node-gyp-build": "^4.3.0" } }, + "utf8-bytes": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/utf8-bytes/-/utf8-bytes-0.0.1.tgz", + "integrity": "sha512-GifWmJAx2qAXT+lZLhbkWhBsy7pr6xWHiPWlVToDiELdWgZwt4Ogjf9tlgvKuALzTFR/d+EPQQI9ogJV3957Jg==" + }, + "utf8-codec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utf8-codec/-/utf8-codec-1.0.0.tgz", + "integrity": "sha512-S/QSLezp3qvG4ld5PUfXiH7mCFxLKjSVZRFkB3DOjgwHuJPFDkInAXc/anf7BAbHt/D38ozDzL+QMZ6/7gsI6w==" + }, + "utf8-length": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/utf8-length/-/utf8-length-0.0.1.tgz", + "integrity": "sha512-j/XH2ftofBiobnyApxlN/J6j/ixwT89WEjDcjT66d2i0+GIn9RZfzt8lpEXXE4jUe4NsjBSUq70kS2euQ4nnMw==" + }, + "utf8-string-bytes": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/utf8-string-bytes/-/utf8-string-bytes-1.0.3.tgz", + "integrity": "sha512-i/I1Omf6lADjVBlwJpQifZOePV15snHny9w04+lc71+3t8PyWuLC/7clyoOSHOBNGXFe2PAGxmTiZ+Z4HWsPyw==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index ef38c20f..6c2256fa 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "typescript": "^4.8.3" }, "dependencies": { + "@dnslink/js": "^0.13.0", "@ethersphere/bee-js": "^5.0.0", "@ethersphere/swarm-cid": "^0.1.0", "express": "^4.18.1", diff --git a/src/bzz-link.ts b/src/bzz-link.ts index c1bf0c98..aa526ec9 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -1,6 +1,7 @@ import { Request, Response } from 'express' import * as swarmCid from '@ethersphere/swarm-cid' import { logger } from './logger' +import { resolve, Result } from '@dnslink/js' export class NotEnabledError extends Error {} @@ -13,6 +14,8 @@ export class RedirectCidError extends Error { } } +export class NoDNSLinkFoundError extends Error {} + /** * Function that evaluates if the request was made with subdomain. * @@ -23,6 +26,27 @@ export function requestFilter(pathname: string, req: Request): boolean { return req.subdomains.length >= 1 } +/** + * Function that search for DNSLink configuration on TXT records + * + * @param domain + */ +async function dnsLookup(domain: string): Promise { + let result = null + try { + result = await resolve(domain, { + endpoints: ['dns.google'], // required! see more below. + timeout: 1000, // timeout for the operation + retries: 3, // retries in case of transport error + }) + } catch (ex) { + logger.error(`dnslink lookup error`, ex) + throw new NoDNSLinkFoundError(`dnslink lookup error resolving domain ${domain}`) + } + + return result! +} + /** * Closure that routes subdomain CID/ENS to /bzz endpoint. * @@ -30,13 +54,28 @@ export function requestFilter(pathname: string, req: Request): boolean { * @param isCidEnabled * @param isEnsEnabled */ -export function routerClosure(target: string, isCidEnabled: boolean, isEnsEnabled: boolean) { - return (req: Request): string => { - const bzzResource = subdomainToBzz(req, isCidEnabled, isEnsEnabled) - - logger.debug(`bzz link proxy`, { hostname: req.hostname, bzzResource }) - - return `${target}/bzz/${bzzResource}` +export function routerClosure( + target: string, + domain: string, + isCidEnabled: boolean, + isEnsEnabled: boolean, + isDnslinkEnabled: boolean, +): { (req: Request): Promise } | { (req: Request): string } { + return async (req: Request): Promise => { + if (isDnslinkEnabled) { + const result = await dnsLookup(domain) + + const { txtEntries } = result + const bzzResource = JSON.parse(JSON.stringify(txtEntries[0])).value.split('/')[2] + logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) + + return `${target}/bzz/${bzzResource}` + } else { + const bzzResource = subdomainToBzz(req, isCidEnabled, isEnsEnabled) + logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) + + return `${target}/bzz/${bzzResource}` + } } } diff --git a/src/config.ts b/src/config.ts index 6230b410..99606ba5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,8 +3,10 @@ export interface AppConfig { beeDebugApiUrl: string authorization?: string hostname?: string + domainLookup?: string cidSubdomains?: boolean ensSubdomains?: boolean + dnslinkEnabled?: boolean removePinHeader?: boolean exposeHashedIdentity?: boolean } @@ -66,6 +68,10 @@ export type EnvironmentVariables = Partial<{ CID_SUBDOMAINS: string ENS_SUBDOMAINS: string + // DNSLink support + DNSLINK: string + DOMAIN_LOOKUP: string + // Headers manipulation REMOVE_PIN_HEADER: string @@ -108,6 +114,8 @@ export function getAppConfig({ AUTH_SECRET, CID_SUBDOMAINS, ENS_SUBDOMAINS, + DNSLINK, + DOMAIN_LOOKUP, HOSTNAME, REMOVE_PIN_HEADER, EXPOSE_HASHED_IDENTITY, @@ -119,6 +127,8 @@ export function getAppConfig({ authorization: AUTH_SECRET, cidSubdomains: CID_SUBDOMAINS === 'true', ensSubdomains: ENS_SUBDOMAINS === 'true', + dnslinkEnabled: DNSLINK === 'true', + domainLookup: DOMAIN_LOOKUP, removePinHeader: REMOVE_PIN_HEADER ? REMOVE_PIN_HEADER === 'true' : true, exposeHashedIdentity: EXPOSE_HASHED_IDENTITY === 'true', } diff --git a/src/server.ts b/src/server.ts index 918cfa86..5965aef6 100644 --- a/src/server.ts +++ b/src/server.ts @@ -29,6 +29,8 @@ export const createApp = ( authorization, cidSubdomains, ensSubdomains, + dnslinkEnabled, + domainLookup, removePinHeader, exposeHashedIdentity, }: AppConfig, @@ -75,25 +77,39 @@ export const createApp = ( }) } - if (cidSubdomains || ensSubdomains) { - if (!hostname) { - throw new Error('For Bzz.link support you have to configure HOSTNAME env!') - } + if (cidSubdomains || ensSubdomains || dnslinkEnabled) { + if (cidSubdomains || ensSubdomains) { + if (!hostname) { + throw new Error('For Bzz.link support you have to configure HOSTNAME env!') + } + + if (hostname === DEFAULT_HOSTNAME) { + logger.warn(`bzz.link support is enabled but HOSTNAME is set to the default ${DEFAULT_HOSTNAME}`) + } + + if (cidSubdomains) logger.info(`enabling CID subdomain support with hostname ${hostname}`) - if (hostname === DEFAULT_HOSTNAME) { - logger.warn(`bzz.link support is enabled but HOSTNAME is set to the default ${DEFAULT_HOSTNAME}`) + if (ensSubdomains) logger.info(`enabling ENS subdomain support with hostname ${hostname}`) } - if (cidSubdomains) logger.info(`enabling CID subdomain support with hostname ${hostname}`) + if (dnslinkEnabled && !domainLookup) { + throw new Error('For Bzz.link support with dnslink you have to configure DOMAIN_LOOKUP env!') + } - if (ensSubdomains) logger.info(`enabling ENS subdomain support with hostname ${hostname}`) + if (dnslinkEnabled) logger.info(`enabling DNSLINK support with domain ${domainLookup}`) app.get( '*', createProxyMiddleware(bzzLink.requestFilter, { ...commonOptions, cookieDomainRewrite: hostname, - router: bzzLink.routerClosure(beeApiUrl, Boolean(cidSubdomains), Boolean(ensSubdomains)), + router: bzzLink.routerClosure( + beeApiUrl, + domainLookup!, + Boolean(cidSubdomains), + Boolean(ensSubdomains), + Boolean(dnslinkEnabled), + ), }), ) diff --git a/test/bzz-link.spec.ts b/test/bzz-link.spec.ts index bfc0f6fa..66959f6e 100644 --- a/test/bzz-link.spec.ts +++ b/test/bzz-link.spec.ts @@ -2,7 +2,7 @@ import { Application, Request } from 'express' import { Server } from 'http' import { AddressInfo } from 'net' import request from 'supertest' -import { NotEnabledError, RedirectCidError, requestFilter, routerClosure } from '../src/bzz-link' +import { NoDNSLinkFoundError, NotEnabledError, RedirectCidError, requestFilter, routerClosure } from '../src/bzz-link' import { DEFAULT_BEE_DEBUG_API_URL } from '../src/config' import { createApp } from '../src/server' import { createBzzLinkMockServer } from './bzz-link.mockserver' @@ -71,42 +71,42 @@ describe('bzz.link', () => { } it('should translate valid CID', async () => { - const router = routerClosure('http://some.bee', true, true) + const router = routerClosure('http://some.bee', '', true, true, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request expect(router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) }) it('should translate valid CID with ENS disabled', async () => { - const router = routerClosure('http://some.bee', true, false) + const router = routerClosure('http://some.bee', '', true, false, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request expect(router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) }) it('should translate valid ENS', async () => { - const router = routerClosure('http://some.bee', true, true) + const router = routerClosure('http://some.bee', '', true, true, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request expect(router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) }) it('should translate valid ENS with subdomain', async () => { - const router = routerClosure('http://some.bee', true, true) + const router = routerClosure('http://some.bee', '', true, true, false) const req = { hostname: `book.swarm.bzz.link`, subdomains: ['swarm', 'book'] } as Request expect(router(req)).toEqual(`http://some.bee/bzz/book.swarm.eth`) }) it('should translate valid ENS when CID is disabled', async () => { - const router = routerClosure('http://some.bee', false, true) + const router = routerClosure('http://some.bee', '', false, true, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request expect(router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) }) it('should throw redirection error for legacy CID', async () => { - const router = routerClosure('http://some.bee', true, true) + const router = routerClosure('http://some.bee', '', true, true, false) const req = { hostname: `${MANIFEST.legacyCid}.bzz.link`, protocol: 'http', @@ -127,17 +127,24 @@ describe('bzz.link', () => { }) it('should throw when CID support is disabled', async () => { - const router = routerClosure('http://some.bee', false, true) + const router = routerClosure('http://some.bee', '', false, true, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request expect(() => router(req)).toThrow(NotEnabledError) }) it('should throw when ENS support is disabled', async () => { - const router = routerClosure('http://some.bee', true, false) + const router = routerClosure('http://some.bee', '', true, false, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request expect(() => router(req)).toThrow(NotEnabledError) }) + + it('should throw when DNSLINK TXT records are not configured', async () => { + const router = routerClosure('http://some.bee', 'swarm.domain.com', false, false, true) + const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request + + expect(() => router(req)).toThrow(NoDNSLinkFoundError) + }) }) }) From 857e3593a9d6e0c1ec49ffbd5bb2259113543281 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Fri, 11 Nov 2022 19:36:39 -0500 Subject: [PATCH 2/9] fix: unit test modifications and addings --- src/bzz-link.ts | 12 +++++++----- src/config.ts | 1 + test/bzz-link.spec.ts | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/bzz-link.ts b/src/bzz-link.ts index aa526ec9..1ef9dee4 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -2,6 +2,7 @@ import { Request, Response } from 'express' import * as swarmCid from '@ethersphere/swarm-cid' import { logger } from './logger' import { resolve, Result } from '@dnslink/js' +import { DEFAULT_QUERY_DNSLINK_ENDPOINT } from './config' export class NotEnabledError extends Error {} @@ -31,11 +32,11 @@ export function requestFilter(pathname: string, req: Request): boolean { * * @param domain */ -async function dnsLookup(domain: string): Promise { +async function dnsLookup(domain: string, queryDnsLinkEndpoint = DEFAULT_QUERY_DNSLINK_ENDPOINT): Promise { let result = null try { result = await resolve(domain, { - endpoints: ['dns.google'], // required! see more below. + endpoints: [queryDnsLinkEndpoint], timeout: 1000, // timeout for the operation retries: 3, // retries in case of transport error }) @@ -44,7 +45,7 @@ async function dnsLookup(domain: string): Promise { throw new NoDNSLinkFoundError(`dnslink lookup error resolving domain ${domain}`) } - return result! + return result } /** @@ -60,10 +61,11 @@ export function routerClosure( isCidEnabled: boolean, isEnsEnabled: boolean, isDnslinkEnabled: boolean, -): { (req: Request): Promise } | { (req: Request): string } { + dnsQuery?: string, +): { (req: Request): Promise } { return async (req: Request): Promise => { if (isDnslinkEnabled) { - const result = await dnsLookup(domain) + const result = await dnsLookup(domain, dnsQuery) const { txtEntries } = result const bzzResource = JSON.parse(JSON.stringify(txtEntries[0])).value.split('/')[2] diff --git a/src/config.ts b/src/config.ts index 99606ba5..c9c7cb72 100644 --- a/src/config.ts +++ b/src/config.ts @@ -102,6 +102,7 @@ export const DEFAULT_LOG_LEVEL = 'info' export const MINIMAL_EXTENDS_TTL_VALUE = 60 export const READINESS_TIMEOUT_MS = 3000 export const ERROR_NO_STAMP = 'No postage stamp' +export const DEFAULT_QUERY_DNSLINK_ENDPOINT = 'dns.google' export const logLevel = process.env.LOG_LEVEL && SUPPORTED_LEVELS.includes(process.env.LOG_LEVEL as SupportedLevels) diff --git a/test/bzz-link.spec.ts b/test/bzz-link.spec.ts index 66959f6e..e698b584 100644 --- a/test/bzz-link.spec.ts +++ b/test/bzz-link.spec.ts @@ -74,35 +74,35 @@ describe('bzz.link', () => { const router = routerClosure('http://some.bee', '', true, true, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request - expect(router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) + expect(await router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) }) it('should translate valid CID with ENS disabled', async () => { const router = routerClosure('http://some.bee', '', true, false, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request - expect(router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) + expect(await router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) }) it('should translate valid ENS', async () => { const router = routerClosure('http://some.bee', '', true, true, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request - expect(router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) + expect(await router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) }) it('should translate valid ENS with subdomain', async () => { const router = routerClosure('http://some.bee', '', true, true, false) const req = { hostname: `book.swarm.bzz.link`, subdomains: ['swarm', 'book'] } as Request - expect(router(req)).toEqual(`http://some.bee/bzz/book.swarm.eth`) + expect(await router(req)).toEqual(`http://some.bee/bzz/book.swarm.eth`) }) it('should translate valid ENS when CID is disabled', async () => { const router = routerClosure('http://some.bee', '', false, true, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request - expect(router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) + expect(await router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) }) it('should throw redirection error for legacy CID', async () => { @@ -115,7 +115,7 @@ describe('bzz.link', () => { } as Request try { - router(req) + await router(req) throw new Error('Should have thrown an RedirectCidError') } catch (e) { if (!(e instanceof RedirectCidError)) { @@ -130,21 +130,21 @@ describe('bzz.link', () => { const router = routerClosure('http://some.bee', '', false, true, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request - expect(() => router(req)).toThrow(NotEnabledError) + expect(async () => router(req)).rejects.toThrow(NotEnabledError) }) it('should throw when ENS support is disabled', async () => { const router = routerClosure('http://some.bee', '', true, false, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request - expect(() => router(req)).toThrow(NotEnabledError) + expect(async () => router(req)).rejects.toThrow(NotEnabledError) }) it('should throw when DNSLINK TXT records are not configured', async () => { - const router = routerClosure('http://some.bee', 'swarm.domain.com', false, false, true) + const router = routerClosure('http://some.bee', 'swarm.domain.com', false, false, true, 'dns.query') const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request - expect(() => router(req)).toThrow(NoDNSLinkFoundError) + expect(async () => router(req)).rejects.toThrow(NoDNSLinkFoundError) }) }) }) From a49ea967f77f78778f9edc465321125777ebc1bf Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Tue, 15 Nov 2022 00:14:46 -0500 Subject: [PATCH 3/9] fix: change the logic to adjust the requirements and addressed comments --- src/bzz-link.ts | 68 ++++++++++++++++++++++++++++++++++--------------- src/config.ts | 8 +++--- src/server.ts | 8 +++--- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/bzz-link.ts b/src/bzz-link.ts index 1ef9dee4..70a682f2 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -32,52 +32,74 @@ export function requestFilter(pathname: string, req: Request): boolean { * * @param domain */ -async function dnsLookup(domain: string, queryDnsLinkEndpoint = DEFAULT_QUERY_DNSLINK_ENDPOINT): Promise { - let result = null +async function dnsLookup( + req: Request, + domains: string[], + queryDnsLinkEndpoint = DEFAULT_QUERY_DNSLINK_ENDPOINT, +): Promise { + let domain try { - result = await resolve(domain, { - endpoints: [queryDnsLinkEndpoint], - timeout: 1000, // timeout for the operation - retries: 3, // retries in case of transport error - }) + domain = req.headers.host + + if (domain) { + const matches = domain.match(/^([^?#]*)(\?([^#]*))?(#(.*))?:[0-9]*]?/i) // clean host domain string + const host = matches && matches[1] // domain will be null if no match is found + + if (host && domains.includes(host)) { + return await resolve(host, { + endpoints: [queryDnsLinkEndpoint], + timeout: 1000, // timeout for the operation + retries: 3, // retries in case of transport error + }) + } + } } catch (ex) { logger.error(`dnslink lookup error`, ex) throw new NoDNSLinkFoundError(`dnslink lookup error resolving domain ${domain}`) } - - return result } /** - * Closure that routes subdomain CID/ENS to /bzz endpoint. + * Closure that routes subdomain CID/ENS/DNSLINK to /bzz endpoint. * * @param target + * @param dnslinkDomains * @param isCidEnabled * @param isEnsEnabled + * @param isDnslinkEnabled + * @param dnsQuery */ export function routerClosure( target: string, - domain: string, + dnslinkDomains: string[], isCidEnabled: boolean, isEnsEnabled: boolean, isDnslinkEnabled: boolean, dnsQuery?: string, ): { (req: Request): Promise } { return async (req: Request): Promise => { + let bzzResource: string | undefined + if (isDnslinkEnabled) { - const result = await dnsLookup(domain, dnsQuery) + const result = await dnsLookup(req, dnslinkDomains, dnsQuery) - const { txtEntries } = result - const bzzResource = JSON.parse(JSON.stringify(txtEntries[0])).value.split('/')[2] - logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) + if (result) { + const { txtEntries } = result + const txtEntry = JSON.parse(JSON.stringify(txtEntries[0])) - return `${target}/bzz/${bzzResource}` - } else { - const bzzResource = subdomainToBzz(req, isCidEnabled, isEnsEnabled) - logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) + if (txtEntry.value) { + bzzResource = txtEntry.value.split('/')[2] + logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) + } + } + } - return `${target}/bzz/${bzzResource}` + if (!bzzResource) { + bzzResource = subdomainToBzz(req, isCidEnabled, isEnsEnabled) + logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) } + + return `${target}/bzz/${bzzResource}` } } @@ -109,6 +131,12 @@ export function errorHandler(err: Error, req: Request, res: Response, next: (e: return } + if (err instanceof NoDNSLinkFoundError) { + res.sendStatus(403) + + return + } + next(err) } diff --git a/src/config.ts b/src/config.ts index c9c7cb72..a6b9cc66 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,7 +3,7 @@ export interface AppConfig { beeDebugApiUrl: string authorization?: string hostname?: string - domainLookup?: string + domainsLookup?: string[] cidSubdomains?: boolean ensSubdomains?: boolean dnslinkEnabled?: boolean @@ -70,7 +70,7 @@ export type EnvironmentVariables = Partial<{ // DNSLink support DNSLINK: string - DOMAIN_LOOKUP: string + DNSLINK_ALLOWED_DOMAINS: string // Headers manipulation REMOVE_PIN_HEADER: string @@ -116,7 +116,7 @@ export function getAppConfig({ CID_SUBDOMAINS, ENS_SUBDOMAINS, DNSLINK, - DOMAIN_LOOKUP, + DNSLINK_ALLOWED_DOMAINS, HOSTNAME, REMOVE_PIN_HEADER, EXPOSE_HASHED_IDENTITY, @@ -129,7 +129,7 @@ export function getAppConfig({ cidSubdomains: CID_SUBDOMAINS === 'true', ensSubdomains: ENS_SUBDOMAINS === 'true', dnslinkEnabled: DNSLINK === 'true', - domainLookup: DOMAIN_LOOKUP, + domainsLookup: DNSLINK_ALLOWED_DOMAINS ? DNSLINK_ALLOWED_DOMAINS.split(',') : undefined, removePinHeader: REMOVE_PIN_HEADER ? REMOVE_PIN_HEADER === 'true' : true, exposeHashedIdentity: EXPOSE_HASHED_IDENTITY === 'true', } diff --git a/src/server.ts b/src/server.ts index 5965aef6..4da5beeb 100644 --- a/src/server.ts +++ b/src/server.ts @@ -30,7 +30,7 @@ export const createApp = ( cidSubdomains, ensSubdomains, dnslinkEnabled, - domainLookup, + domainsLookup, removePinHeader, exposeHashedIdentity, }: AppConfig, @@ -92,11 +92,11 @@ export const createApp = ( if (ensSubdomains) logger.info(`enabling ENS subdomain support with hostname ${hostname}`) } - if (dnslinkEnabled && !domainLookup) { + if (dnslinkEnabled && !domainsLookup) { throw new Error('For Bzz.link support with dnslink you have to configure DOMAIN_LOOKUP env!') } - if (dnslinkEnabled) logger.info(`enabling DNSLINK support with domain ${domainLookup}`) + if (dnslinkEnabled) logger.info(`enabling DNSLINK support with domains ${domainsLookup}`) app.get( '*', @@ -105,7 +105,7 @@ export const createApp = ( cookieDomainRewrite: hostname, router: bzzLink.routerClosure( beeApiUrl, - domainLookup!, + domainsLookup!, Boolean(cidSubdomains), Boolean(ensSubdomains), Boolean(dnslinkEnabled), From be19f43ba4c4b9a88d4945b590cbadbf6d3768a2 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Tue, 15 Nov 2022 00:19:59 -0500 Subject: [PATCH 4/9] fix: unit test fixes --- test/bzz-link.spec.ts | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/test/bzz-link.spec.ts b/test/bzz-link.spec.ts index e698b584..d8697dca 100644 --- a/test/bzz-link.spec.ts +++ b/test/bzz-link.spec.ts @@ -71,42 +71,42 @@ describe('bzz.link', () => { } it('should translate valid CID', async () => { - const router = routerClosure('http://some.bee', '', true, true, false) + const router = routerClosure('http://some.bee', [], true, true, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request expect(await router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) }) it('should translate valid CID with ENS disabled', async () => { - const router = routerClosure('http://some.bee', '', true, false, false) + const router = routerClosure('http://some.bee', [], true, false, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request expect(await router(req)).toEqual(`http://some.bee/bzz/${MANIFEST.reference}`) }) it('should translate valid ENS', async () => { - const router = routerClosure('http://some.bee', '', true, true, false) + const router = routerClosure('http://some.bee', [], true, true, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request expect(await router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) }) it('should translate valid ENS with subdomain', async () => { - const router = routerClosure('http://some.bee', '', true, true, false) + const router = routerClosure('http://some.bee', [], true, true, false) const req = { hostname: `book.swarm.bzz.link`, subdomains: ['swarm', 'book'] } as Request expect(await router(req)).toEqual(`http://some.bee/bzz/book.swarm.eth`) }) it('should translate valid ENS when CID is disabled', async () => { - const router = routerClosure('http://some.bee', '', false, true, false) + const router = routerClosure('http://some.bee', [], false, true, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request expect(await router(req)).toEqual(`http://some.bee/bzz/some-ens-domain.eth`) }) it('should throw redirection error for legacy CID', async () => { - const router = routerClosure('http://some.bee', '', true, true, false) + const router = routerClosure('http://some.bee', [], true, true, false) const req = { hostname: `${MANIFEST.legacyCid}.bzz.link`, protocol: 'http', @@ -127,21 +127,28 @@ describe('bzz.link', () => { }) it('should throw when CID support is disabled', async () => { - const router = routerClosure('http://some.bee', '', false, true, false) + const router = routerClosure('http://some.bee', [], false, true, false) const req = { hostname: `${MANIFEST.cid}.bzz.link`, subdomains: [MANIFEST.cid] } as Request expect(async () => router(req)).rejects.toThrow(NotEnabledError) }) it('should throw when ENS support is disabled', async () => { - const router = routerClosure('http://some.bee', '', true, false, false) + const router = routerClosure('http://some.bee', [], true, false, false) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request expect(async () => router(req)).rejects.toThrow(NotEnabledError) }) it('should throw when DNSLINK TXT records are not configured', async () => { - const router = routerClosure('http://some.bee', 'swarm.domain.com', false, false, true, 'dns.query') + const router = routerClosure( + 'http://some.bee', + ['swarm.domain.com', 'some-ens-domain.bzz.link'], + false, + false, + true, + 'dns.query', + ) const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request expect(async () => router(req)).rejects.toThrow(NoDNSLinkFoundError) From 2afa4cfbcf93bd9a0088f457cbc7f6bd72006d32 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Tue, 15 Nov 2022 18:37:56 -0500 Subject: [PATCH 5/9] fix: modularize even more the different components of dnslink --- src/bzz-link.ts | 67 ++++++++++++++++++++++++++----------------- test/bzz-link.spec.ts | 6 +++- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/bzz-link.ts b/src/bzz-link.ts index 70a682f2..ee889212 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -27,38 +27,53 @@ export function requestFilter(pathname: string, req: Request): boolean { return req.subdomains.length >= 1 } +function getDomain(req: Request, dnslinkDomains: string[]): string { + const host = req.headers.host + + if (host) { + const matches = host.match(/^([^?#]*)(\?([^#]*))?(#(.*))?:[0-9]*]?/i) // clean host domain string + const match = matches && matches[1] // domain will be null if no match is found + + // if the domain is not on list of domains configured it will take anything + const domain = match && validateDomain(match, dnslinkDomains) ? match : req.headers.host! + + return domain + } + + return req.headers.host! +} + +function validateDomain(host: string, domains: string[]) { + return domains.includes(host) +} + /** * Function that search for DNSLink configuration on TXT records * * @param domain */ async function dnsLookup( - req: Request, - domains: string[], + domain: string, queryDnsLinkEndpoint = DEFAULT_QUERY_DNSLINK_ENDPOINT, ): Promise { - let domain try { - domain = req.headers.host - - if (domain) { - const matches = domain.match(/^([^?#]*)(\?([^#]*))?(#(.*))?:[0-9]*]?/i) // clean host domain string - const host = matches && matches[1] // domain will be null if no match is found - - if (host && domains.includes(host)) { - return await resolve(host, { - endpoints: [queryDnsLinkEndpoint], - timeout: 1000, // timeout for the operation - retries: 3, // retries in case of transport error - }) - } - } + console.log('domain', domain) + + return await resolve(domain, { + endpoints: [queryDnsLinkEndpoint], + timeout: 1000, // timeout for the operation + retries: 3, // retries in case of transport error + }) } catch (ex) { logger.error(`dnslink lookup error`, ex) throw new NoDNSLinkFoundError(`dnslink lookup error resolving domain ${domain}`) } } +function getBzzRoute(target: string, bzzResource: string) { + return `${target}/bzz/${bzzResource}` +} + /** * Closure that routes subdomain CID/ENS/DNSLINK to /bzz endpoint. * @@ -78,28 +93,28 @@ export function routerClosure( dnsQuery?: string, ): { (req: Request): Promise } { return async (req: Request): Promise => { - let bzzResource: string | undefined - if (isDnslinkEnabled) { - const result = await dnsLookup(req, dnslinkDomains, dnsQuery) + const domain = getDomain(req, dnslinkDomains) + + const result = await dnsLookup(domain, dnsQuery) if (result) { const { txtEntries } = result const txtEntry = JSON.parse(JSON.stringify(txtEntries[0])) if (txtEntry.value) { - bzzResource = txtEntry.value.split('/')[2] + const bzzResource = txtEntry.value.split('/')[2] logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) + + return getBzzRoute(target, bzzResource) } } } - if (!bzzResource) { - bzzResource = subdomainToBzz(req, isCidEnabled, isEnsEnabled) - logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) - } + const bzzResource = subdomainToBzz(req, isCidEnabled, isEnsEnabled) + logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) - return `${target}/bzz/${bzzResource}` + return getBzzRoute(target, bzzResource) } } diff --git a/test/bzz-link.spec.ts b/test/bzz-link.spec.ts index d8697dca..d310aff6 100644 --- a/test/bzz-link.spec.ts +++ b/test/bzz-link.spec.ts @@ -149,7 +149,11 @@ describe('bzz.link', () => { true, 'dns.query', ) - const req = { hostname: `some-ens-domain.bzz.link`, subdomains: ['some-ens-domain'] } as Request + const req = { + hostname: `some-ens-domain.bzz.link`, + subdomains: ['some-ens-domain'], + headers: { host: 'swarm.url.com' }, + } as Request expect(async () => router(req)).rejects.toThrow(NoDNSLinkFoundError) }) From 6da4aedad3f25fcdf72863ee9038bc4c558b83cd Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Tue, 15 Nov 2022 20:13:18 -0500 Subject: [PATCH 6/9] fix: remove of unnecesary console.log --- src/bzz-link.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bzz-link.ts b/src/bzz-link.ts index ee889212..c13b9990 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -57,8 +57,6 @@ async function dnsLookup( queryDnsLinkEndpoint = DEFAULT_QUERY_DNSLINK_ENDPOINT, ): Promise { try { - console.log('domain', domain) - return await resolve(domain, { endpoints: [queryDnsLinkEndpoint], timeout: 1000, // timeout for the operation From 68758a57802e068095e75a90401267432a81d8e1 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Fri, 18 Nov 2022 12:29:20 -0500 Subject: [PATCH 7/9] chore: added unit tests and modified the code to be more readable --- src/bzz-link.ts | 53 +++++++++++++++++++++++-------------------- test/bzz-link.spec.ts | 30 +++++++++++++++++++++++- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/src/bzz-link.ts b/src/bzz-link.ts index c13b9990..f63dd5ff 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -27,24 +27,19 @@ export function requestFilter(pathname: string, req: Request): boolean { return req.subdomains.length >= 1 } -function getDomain(req: Request, dnslinkDomains: string[]): string { - const host = req.headers.host - - if (host) { - const matches = host.match(/^([^?#]*)(\?([^#]*))?(#(.*))?:[0-9]*]?/i) // clean host domain string +export function getDomain(req: Request): string | undefined { + try { + const matches = req.headers.host!.match(/^([^?#]*)(\?([^#]*))?(#(.*))?:[0-9]*]?/i) // clean host domain string const match = matches && matches[1] // domain will be null if no match is found - // if the domain is not on list of domains configured it will take anything - const domain = match && validateDomain(match, dnslinkDomains) ? match : req.headers.host! - - return domain + if (match) return match + } finally { + return req.headers.host } - - return req.headers.host! } -function validateDomain(host: string, domains: string[]) { - return domains.includes(host) +export function validateDomain(host: string, domains: string[]): boolean { + return domains.includes(host!) } /** @@ -68,7 +63,21 @@ async function dnsLookup( } } -function getBzzRoute(target: string, bzzResource: string) { +function getDnslinkBzzRoute(hostname: string, target: string, result: Result | undefined): string | undefined { + if (result) { + const { txtEntries } = result + const txtEntry = JSON.parse(JSON.stringify(txtEntries[0])) + + if (txtEntry.value) { + const bzzResource = txtEntry.value.split('/')[2] + logger.info(`bzz link proxy`, { hostname, bzzResource }) + + return getBzzRoute(target, bzzResource) + } + } +} + +function getBzzRoute(target: string, bzzResource: string): string { return `${target}/bzz/${bzzResource}` } @@ -92,20 +101,14 @@ export function routerClosure( ): { (req: Request): Promise } { return async (req: Request): Promise => { if (isDnslinkEnabled) { - const domain = getDomain(req, dnslinkDomains) - - const result = await dnsLookup(domain, dnsQuery) + const domain = getDomain(req) - if (result) { - const { txtEntries } = result - const txtEntry = JSON.parse(JSON.stringify(txtEntries[0])) + if (domain && validateDomain(domain, dnslinkDomains)) { + const result = await dnsLookup(domain!, dnsQuery) - if (txtEntry.value) { - const bzzResource = txtEntry.value.split('/')[2] - logger.info(`bzz link proxy`, { hostname: req.hostname, bzzResource }) + const bzzRoute = getDnslinkBzzRoute(req.hostname, target, result) - return getBzzRoute(target, bzzResource) - } + if (bzzRoute) return bzzRoute } } diff --git a/test/bzz-link.spec.ts b/test/bzz-link.spec.ts index d310aff6..1819f0e2 100644 --- a/test/bzz-link.spec.ts +++ b/test/bzz-link.spec.ts @@ -2,7 +2,15 @@ import { Application, Request } from 'express' import { Server } from 'http' import { AddressInfo } from 'net' import request from 'supertest' -import { NoDNSLinkFoundError, NotEnabledError, RedirectCidError, requestFilter, routerClosure } from '../src/bzz-link' +import { + getDomain, + NoDNSLinkFoundError, + NotEnabledError, + RedirectCidError, + requestFilter, + routerClosure, + validateDomain, +} from '../src/bzz-link' import { DEFAULT_BEE_DEBUG_API_URL } from '../src/config' import { createApp } from '../src/server' import { createBzzLinkMockServer } from './bzz-link.mockserver' @@ -140,6 +148,26 @@ describe('bzz.link', () => { expect(async () => router(req)).rejects.toThrow(NotEnabledError) }) + it('should return false for domain not found on allowed domains', () => { + const req = { + hostname: `some-ens-domain.bzz.link`, + subdomains: ['some-ens-domain'], + headers: { host: 'swarm.url.com' }, + } as Request + const dnsAllowedDomains = ['swarm.domain.com', 'some-ens-domain.bzz.link'] + expect(validateDomain(req.headers.host!, dnsAllowedDomains)).toBe(false) + }) + + it('should return the domain specified on header-host', () => { + const domain = 'swarm.url.com' + const req = { + hostname: `some-ens-domain.bzz.link`, + subdomains: ['some-ens-domain'], + headers: { host: `${domain}:3000` }, + } as Request + expect(getDomain(req)).toEqual(domain) + }) + it('should throw when DNSLINK TXT records are not configured', async () => { const router = routerClosure( 'http://some.bee', From 893451c083c84590ef40996db3d05d789d4b1b14 Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Fri, 18 Nov 2022 12:40:50 -0500 Subject: [PATCH 8/9] chore: changes to get the right domain ore effectively --- src/bzz-link.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/bzz-link.ts b/src/bzz-link.ts index f63dd5ff..d16e0dda 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -33,7 +33,7 @@ export function getDomain(req: Request): string | undefined { const match = matches && matches[1] // domain will be null if no match is found if (match) return match - } finally { + } catch { return req.headers.host } } @@ -101,10 +101,15 @@ export function routerClosure( ): { (req: Request): Promise } { return async (req: Request): Promise => { if (isDnslinkEnabled) { - const domain = getDomain(req) + let domain = getDomain(req) - if (domain && validateDomain(domain, dnslinkDomains)) { - const result = await dnsLookup(domain!, dnsQuery) + // in case domain is not on the list of allowed domains then it uses anything on headers-host + if (!(domain && validateDomain(domain, dnslinkDomains))) { + domain = req.headers.host + } + + if (domain) { + const result = await dnsLookup(domain, dnsQuery) const bzzRoute = getDnslinkBzzRoute(req.hostname, target, result) From 8158ffadc8eb77962df520be5ecd8c0b706403fc Mon Sep 17 00:00:00 2001 From: Luis Ricardo Sanchez Date: Fri, 18 Nov 2022 12:56:04 -0500 Subject: [PATCH 9/9] chore: remove unnecessary code --- src/bzz-link.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bzz-link.ts b/src/bzz-link.ts index d16e0dda..a3f087ef 100644 --- a/src/bzz-link.ts +++ b/src/bzz-link.ts @@ -39,7 +39,7 @@ export function getDomain(req: Request): string | undefined { } export function validateDomain(host: string, domains: string[]): boolean { - return domains.includes(host!) + return domains.includes(host) } /**