diff --git a/config/config.js b/config/config.js index d0b833a..3045080 100644 --- a/config/config.js +++ b/config/config.js @@ -1,7 +1,8 @@ export default { server_port:"44444", - akaze_microservice_url:"http://localhost:33333", - nn_microservice_url:"http://localhost:33334", - hist_microservice_url:"http://localhost:33335", - phash_microservice_url:"http://localhost:33336", + local_features_microservice_url:"http://127.0.0.1:33333", + global_features_microservice_url:"http://127.0.0.1:33334", + color_microservice_url:"http://127.0.0.1:33335", + phash_microservice_url:"http://127.0.0.1:33336", + text_microservice_url:"http://127.0.0.1:33339", } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 68116da..426e98b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,11 @@ "requires": true, "packages": { "": { + "name": "ambience", "version": "1.0.0", "license": "ISC", "dependencies": { + "@types/multiparty": "^0.0.33", "@types/node": "^15.3.0", "axios": "^0.21.1", "cross-env": "^7.0.3", @@ -16,7 +18,9 @@ "fastify-multipart": "^4.0.7", "fastify-reply-from": "^6.0.1", "form-data": "^4.0.0", - "json-schema-to-ts": "^1.6.4" + "json-schema-to-ts": "^1.6.4", + "multiparty": "^4.2.3", + "typescript": "^4.6.4" } }, "node_modules/@fastify/ajv-compiler": { @@ -32,6 +36,14 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, + "node_modules/@types/multiparty": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/multiparty/-/multiparty-0.0.33.tgz", + "integrity": "sha512-Il6cJUpSqgojT7NxbVJUvXkCblm50/yEJYtblISDsNIeNYf4yMAhdizzidUk6h8pJ8yhwK/3Fkb+3Dwcgtwl8w==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "15.3.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz", @@ -332,31 +344,6 @@ "node": ">=12.18" } }, - "node_modules/fastify-reply-from/node_modules/http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fastify-reply-from/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/fastify-reply-from/node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, "node_modules/fastify-warning": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", @@ -375,25 +362,6 @@ "node": ">= 6" } }, - "node_modules/fastify/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/fastify/node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -477,10 +445,25 @@ "node": ">=8" } }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -534,25 +517,6 @@ "node": ">= 6" } }, - "node_modules/light-my-request/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/light-my-request/node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -591,6 +555,19 @@ "node": ">= 0.6" } }, + "node_modules/multiparty": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", + "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", + "dependencies": { + "http-errors": "~1.8.1", + "safe-buffer": "5.2.1", + "uid-safe": "2.1.5" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -681,6 +658,14 @@ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==" }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ret": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", @@ -703,6 +688,25 @@ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-regex2": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", @@ -740,6 +744,11 @@ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==" }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -806,9 +815,9 @@ } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } @@ -818,6 +827,29 @@ "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==" }, + "node_modules/typescript": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", + "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/undici": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/undici/-/undici-4.3.1.tgz", @@ -878,6 +910,14 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, + "@types/multiparty": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/multiparty/-/multiparty-0.0.33.tgz", + "integrity": "sha512-Il6cJUpSqgojT7NxbVJUvXkCblm50/yEJYtblISDsNIeNYf4yMAhdizzidUk6h8pJ8yhwK/3Fkb+3Dwcgtwl8w==", + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "15.3.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz", @@ -1071,11 +1111,6 @@ "util-deprecate": "^1.0.1" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -1148,30 +1183,6 @@ "semver": "^7.3.5", "tiny-lru": "^7.0.6", "undici": "^4.0.0" - }, - "dependencies": { - "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - } } }, "fastify-warning": { @@ -1228,10 +1239,22 @@ "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==" }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ipaddr.js": { "version": "1.9.1", @@ -1279,11 +1302,6 @@ "util-deprecate": "^1.0.1" } }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -1315,6 +1333,16 @@ "mime-db": "1.47.0" } }, + "multiparty": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", + "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", + "requires": { + "http-errors": "~1.8.1", + "safe-buffer": "5.2.1", + "uid-safe": "2.1.5" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1379,6 +1407,11 @@ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "ret": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", @@ -1394,6 +1427,11 @@ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, "safe-regex2": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", @@ -1425,6 +1463,11 @@ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==" }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1473,15 +1516,28 @@ "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==" }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "ts-toolbelt": { "version": "6.15.5", "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==" }, + "typescript": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", + "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==" + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "undici": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/undici/-/undici-4.3.1.tgz", diff --git a/package.json b/package.json index e6ad209..481bddb 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ }, "homepage": "https://github.com/qwertyforce/ambience#readme", "dependencies": { + "@types/multiparty": "^0.0.33", "@types/node": "^15.3.0", "axios": "^0.21.1", "cross-env": "^7.0.3", @@ -27,6 +28,8 @@ "fastify-multipart": "^4.0.7", "fastify-reply-from": "^6.0.1", "form-data": "^4.0.0", - "json-schema-to-ts": "^1.6.4" + "json-schema-to-ts": "^1.6.4", + "multiparty": "^4.2.3", + "typescript": "^4.6.4" } } diff --git a/server/helpers/image_ops.ts b/server/helpers/image_ops.ts index cc9d690..e302f31 100644 --- a/server/helpers/image_ops.ts +++ b/server/helpers/image_ops.ts @@ -5,7 +5,7 @@ import axios from 'axios' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// async function calculate_phash_features(image_id: number, image: Buffer) { - const form = new FormData(); + const form = new FormData() form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data form.append('image_id', image_id.toString()) const status = await axios.post(`${config.phash_microservice_url}/calculate_phash_features`, form.getBuffer(), { @@ -18,11 +18,11 @@ async function calculate_phash_features(image_id: number, image: Buffer) { return status.data } -async function calculate_akaze_features(image_id: number, image: Buffer) { - const form = new FormData(); +async function calculate_local_features(image_id: number, image: Buffer) { + const form = new FormData() form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data form.append('image_id', image_id.toString()) - const status = await axios.post(`${config.akaze_microservice_url}/calculate_akaze_features`, form.getBuffer(), { + const status = await axios.post(`${config.local_features_microservice_url}/calculate_local_features`, form.getBuffer(), { maxContentLength: Infinity, maxBodyLength: Infinity, headers: { @@ -31,11 +31,11 @@ async function calculate_akaze_features(image_id: number, image: Buffer) { }) return status.data } -async function calculate_nn_features(image_id: number, image: Buffer) { - const form = new FormData(); +async function calculate_global_features(image_id: number, image: Buffer) { + const form = new FormData() form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data form.append('image_id', image_id.toString()) - const status = await axios.post(`${config.nn_microservice_url}/calculate_nn_features`, form.getBuffer(), { + const status = await axios.post(`${config.global_features_microservice_url}/calculate_global_features`, form.getBuffer(), { maxContentLength: Infinity, maxBodyLength: Infinity, headers: { @@ -45,11 +45,11 @@ async function calculate_nn_features(image_id: number, image: Buffer) { return status.data } -async function calculate_hist_features(image_id: number, image: Buffer) { - const form = new FormData(); +async function calculate_color_features(image_id: number, image: Buffer) { + const form = new FormData() form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data form.append('image_id', image_id.toString()) - const status = await axios.post(`${config.hist_microservice_url}/calculate_hist_features`, form.getBuffer(), { + const status = await axios.post(`${config.color_microservice_url}/calculate_color_features`, form.getBuffer(), { maxContentLength: Infinity, maxBodyLength: Infinity, headers: { @@ -59,57 +59,214 @@ async function calculate_hist_features(image_id: number, image: Buffer) { return status.data } -async function phash_reverse_search(image: Buffer) { +interface ImageSearchProps{ + image:Buffer, + k?:number, + distance_threshold?:number + k_clusters?:number + min_matches?:number + matching_threshold?:number + aqe_n?:number + aqe_alpha?:number + use_snn_matching?:number + snn_match_threshold?:number + use_ransac?:number +} + +async function phash_get_similar_images_by_image_buffer({image,k,distance_threshold}:ImageSearchProps) { try { - const form = new FormData(); + const form = new FormData() + if(k){ + form.append('k', k.toString()) + }else if(distance_threshold){ + form.append('distance_threshold', distance_threshold.toString()) + } + form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data - const status = await axios.post(`${config.phash_microservice_url}/phash_reverse_search`, form.getBuffer(), { + const res = await axios.post(`${config.phash_microservice_url}/phash_get_similar_images_by_image_buffer`, form.getBuffer(), { maxContentLength: Infinity, maxBodyLength: Infinity, headers: { ...form.getHeaders() } }) - return status.data + return res.data } catch (err) { console.log(err) return [] } } -async function akaze_reverse_search(image: Buffer) { +async function global_features_get_similar_images_by_image_buffer({image,k,distance_threshold,aqe_n,aqe_alpha}:ImageSearchProps) { try { - const form = new FormData(); + const form = new FormData() + if(k){ + form.append('k', k.toString()) + }else if(distance_threshold){ + form.append('distance_threshold', distance_threshold.toString()) + } + if(aqe_n){ + form.append('aqe_n', aqe_n.toString()) + } + if(aqe_alpha){ + form.append('aqe_alpha', aqe_alpha.toString()) + } form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data - const status = await axios.post(`${config.akaze_microservice_url}/akaze_reverse_search`, form.getBuffer(), { + const res = await axios.post(`${config.global_features_microservice_url}/global_features_get_similar_images_by_image_buffer`, form.getBuffer(), { maxContentLength: Infinity, maxBodyLength: Infinity, headers: { ...form.getHeaders() } }) - return status.data + return res.data } catch (err) { console.log(err) return [] } } + +async function color_get_similar_images_by_image_buffer({image,k,distance_threshold}:ImageSearchProps) { + try { + const form = new FormData() + if(k){ + form.append('k', k.toString()) + }else if(distance_threshold){ + form.append('distance_threshold', distance_threshold.toString()) + } + + form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data + const res = await axios.post(`${config.color_microservice_url}/color_get_similar_images_by_image_buffer`, form.getBuffer(), { + maxContentLength: Infinity, + maxBodyLength: Infinity, + headers: { + ...form.getHeaders() + } + }) + return res.data + } catch (err) { + console.log(err) + return [] + } +} + +async function local_features_get_similar_images_by_image_buffer({image, + k,k_clusters,min_matches,matching_threshold,use_snn_matching,snn_match_threshold,use_ransac}:ImageSearchProps) { + try { + const form = new FormData() + if(k){ + form.append('k', k.toString()) + } + if(k_clusters){ + form.append('k_clusters', k_clusters.toString()) + } + if(min_matches){ + form.append('min_matches', min_matches.toString()) + } + if(matching_threshold){ + form.append('matching_threshold', matching_threshold.toString()) + } + if(use_snn_matching){ + form.append('use_snn_matching', use_snn_matching.toString()) + } + if(snn_match_threshold){ + form.append('snn_match_threshold', snn_match_threshold.toString()) + } + if(use_ransac){ + form.append('use_ransac', use_ransac.toString()) + } + + form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data + const res = await axios.post(`${config.local_features_microservice_url}/local_features_get_similar_images_by_image_buffer`, form.getBuffer(), { + maxContentLength: Infinity, + maxBodyLength: Infinity, + headers: { + ...form.getHeaders() + } + }) + return res.data + } catch (err) { + console.log(err) + return [] + } +} + +async function text_get_similar_images_by_image_buffer({image,k,distance_threshold}:ImageSearchProps) { + try { + const form = new FormData() + if(k){ + form.append('k', k.toString()) + }else if(distance_threshold){ + form.append('distance_threshold', distance_threshold.toString()) + } + + form.append('image', image, { filename: 'document' }) //hack to make nodejs buffer work with form-data + const res = await axios.post(`${config.text_microservice_url}/text_get_similar_images_by_image_buffer`, form.getBuffer(), { + maxContentLength: Infinity, + maxBodyLength: Infinity, + headers: { + ...form.getHeaders() + } + }) + return res.data + } catch (err) { + console.log(err) + return [] + } +} + +async function get_similar_images(image: Buffer) { + const phash_res = await phash_get_similar_images_by_image_buffer({image:image,k:200}) + const global_features_res = await global_features_get_similar_images_by_image_buffer({image:image,k:200}) + const local_features_res = await local_features_get_similar_images_by_image_buffer({ + image:image,k:200, k_clusters:10, + min_matches:4, matching_threshold:1.1, + use_snn_matching:1, use_ransac:1}) + const color_res = await color_get_similar_images_by_image_buffer({image:image,k:200}) + const text_res = await text_get_similar_images_by_image_buffer({image:image,k:200}) + + console.log("==================") + console.log("phash") + console.log(local_features_res) + console.log("==================") + + console.log("==================") + console.log("phash") + console.log(phash_res) + console.log("==================") + + console.log("==================") + console.log("nn") + console.log(global_features_res) + console.log("==================") + + console.log("==================") + console.log("color") + console.log(color_res) + console.log("==================") + + console.log("==================") + console.log("text") + console.log(text_res) + console.log("==================") + return {phash:phash_res,global_features:global_features_res,local_features:local_features_res,color:color_res,text:text_res} +} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////// -async function delete_akaze_features_by_id(image_id: number) { - const status = await axios.post(`${config.akaze_microservice_url}/delete_akaze_features`, { image_id: image_id }) +async function delete_local_features_by_id(image_id: number) { + const status = await axios.post(`${config.local_features_microservice_url}/delete_local_features`, { image_id: image_id }) return status.data } -async function delete_nn_features_by_id(image_id: number) { - const status = await axios.post(`${config.nn_microservice_url}/delete_nn_features`, { image_id: image_id }) +async function delete_global_features_by_id(image_id: number) { + const status = await axios.post(`${config.global_features_microservice_url}/delete_global_features`, { image_id: image_id }) return status.data } -async function delete_hist_features_by_id(image_id: number) { - const status = await axios.post(`${config.hist_microservice_url}/delete_hist_features`, { image_id: image_id }) +async function delete_color_features_by_id(image_id: number) { + const status = await axios.post(`${config.color_microservice_url}/delete_color_features`, { image_id: image_id }) return status.data } @@ -123,20 +280,20 @@ async function delete_phash_features_by_id(image_id: number) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// async function calculate_all_image_features(image_id: number, image_buffer: Buffer) { return Promise.allSettled([ - calculate_akaze_features(image_id, image_buffer), - calculate_nn_features(image_id, image_buffer), - calculate_hist_features(image_id, image_buffer), + calculate_global_features(image_id, image_buffer), + calculate_local_features(image_id, image_buffer), + calculate_color_features(image_id, image_buffer), calculate_phash_features(image_id, image_buffer), ]) } async function delete_all_image_features(image_id: number) { return Promise.allSettled([ - delete_akaze_features_by_id(image_id), - delete_nn_features_by_id(image_id), - delete_hist_features_by_id(image_id), + delete_global_features_by_id(image_id), + delete_local_features_by_id(image_id), + delete_color_features_by_id(image_id), delete_phash_features_by_id(image_id) ]) } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -export default { calculate_all_image_features, delete_all_image_features, phash_reverse_search, akaze_reverse_search } \ No newline at end of file +export default { calculate_all_image_features, delete_all_image_features, get_similar_images} \ No newline at end of file diff --git a/server/index.ts b/server/index.ts index 51cc4ae..edfbab1 100644 --- a/server/index.ts +++ b/server/index.ts @@ -3,7 +3,20 @@ import fastifyMultipart from 'fastify-multipart' import fastify from 'fastify' import formBodyPlugin from 'fastify-formbody' import fastifyReplyFrom from 'fastify-reply-from' -const server = fastify() +// import fastifyCors from '@fastify/cors' +// import multiparty from 'multiparty' +const server = fastify({logger:false}) + +// server.addHook('preHandler', function (req, _reply, done) { +// var form = new multiparty.Form({autoFiles:true,uploadDir:"./uploads/"}) +// form.parse(req.raw) +// done() +// }) + +// server.register(fastifyCors, { +// "origin": "*", +// "methods": "GET,HEAD,PUT,PATCH,POST,DELETE", +// }) const port = config.server_port function combineURLs(baseURL: string, relativeURL: string) { //https://stackoverflow.com/a/49966753 @@ -36,42 +49,51 @@ server.register(async function (app) { }) ///////////////////////////////////////////////////////////////////////////////////////////////PROXY -server.register(fastifyReplyFrom) +server.register(fastifyReplyFrom,{http: {agentOptions: {keepAliveMsecs: 10 * 60 * 1000},requestOptions: {timeout: 10 * 60 * 1000 }}}) server.addContentTypeParser('multipart/form-data', function (_request, payload, done) { done(null, payload) //https://github.com/fastify/help/issues/67 }) -const akaze_routes = ['/akaze_reverse_search', '/calculate_akaze_features', '/delete_akaze_features'] -akaze_routes.forEach((r) => server.post(r, async (_req, res) => { +const local_features_routes = ['/local_features_get_similar_images_by_image_buffer','/local_features_get_similar_images_by_id', '/calculate_local_features', '/delete_local_features'] +local_features_routes.forEach((r) => server.post(r, async (_req, res) => { try { - res.from(combineURLs(config.akaze_microservice_url, r)) + res.from(combineURLs(config.local_features_microservice_url, r)) } catch (err) { console.log(err) - res.status(500).send('Akaze microservice is down') + res.status(500).send('Local features microservice is down') } })) -const nn_routes = ['/nn_get_similar_images_by_image_buffer', '/nn_get_similar_images_by_text', - '/nn_get_similar_images_by_id', '/calculate_nn_features', '/delete_nn_features', '/nn_get_image_tags_by_image_buffer'] -nn_routes.forEach((r) => server.post(r, async (_req, res) => { +const global_features_routes = ['/global_features_get_similar_images_by_image_buffer', '/global_features_get_similar_images_by_id', '/calculate_global_features', '/delete_global_features'] +global_features_routes.forEach((r) => server.post(r, async (_req, res) => { try { - res.from(combineURLs(config.nn_microservice_url, r)) + res.from(combineURLs(config.global_features_microservice_url, r)) } catch (err) { console.log(err) - res.status(500).send('NN microservice is down') + res.status(500).send('Global features microservice is down') } })) -const hist_routes = ['/hist_get_similar_images_by_image_buffer', '/hist_get_similar_images_by_id', '/calculate_hist_features', '/delete_hist_features'] -hist_routes.forEach((r) => server.post(r, async (_req, res) => { +const color_routes = ['/color_get_similar_images_by_image_buffer', '/color_get_similar_images_by_id', '/calculate_color_features', '/delete_color_features'] +color_routes.forEach((r) => server.post(r, async (_req, res) => { try { - res.from(combineURLs(config.hist_microservice_url, r)) + res.from(combineURLs(config.color_microservice_url, r)) } catch (err) { console.log(err) - res.status(500).send('HIST microservice is down') + res.status(500).send('Color features microservice is down') } })) -const phash_routes = ['/phash_reverse_search', '/calculate_phash_features', '/delete_phash_features'] +const text_routes = ['/text_get_similar_images_by_image_buffer', '/text_get_similar_images_by_id', '/calculate_text_features', '/delete_text_features'] +text_routes.forEach((r) => server.post(r, async (_req, res) => { + try { + res.from(combineURLs(config.text_microservice_url, r)) + } catch (err) { + console.log(err) + res.status(500).send('Text features microservice is down') + } +})) + +const phash_routes = ['/phash_get_similar_images_by_image_buffer', '/calculate_phash_features', '/delete_phash_features'] phash_routes.forEach((r) => server.post(r, async (_req, res) => { try { res.from(combineURLs(config.phash_microservice_url, r)) diff --git a/server/routes/reverse_search.ts b/server/routes/reverse_search.ts index d53b902..0734ad5 100644 --- a/server/routes/reverse_search.ts +++ b/server/routes/reverse_search.ts @@ -16,13 +16,8 @@ async function reverse_search(req: FastifyRequest<{ Body: FromSchema