diff --git a/dist/server/config/default.json b/dist/server/config/default.json index 5ee4cf1..a7bd97f 100644 --- a/dist/server/config/default.json +++ b/dist/server/config/default.json @@ -2,9 +2,10 @@ "server": { "port": 3333, + "host": "127.0.0.1", "logRequests": false, "logQueries": false, "logTimings": false } } - \ No newline at end of file + diff --git a/dist/server/mongodb-proxy.js b/dist/server/mongodb-proxy.js index a3fc84e..0e68c95 100644 --- a/dist/server/mongodb-proxy.js +++ b/dist/server/mongodb-proxy.js @@ -1,3 +1,5 @@ +var parser = require('mongodb-query-parser'); +var escapeStringRegexp = require('escape-string-regexp'); var express = require('express'); var bodyParser = require('body-parser'); var _ = require('lodash'); @@ -128,8 +130,8 @@ app.all('/query', function(req, res, next) setCORSHeaders(res); // Parse query string in target - substitutions = { "$from" : new Date(req.body.range.from), - "$to" : new Date(req.body.range.to), + substitutions = { "$from" : req.body.range.from, + "$to" : req.body.range.to, "$dateBucketCount" : getBucketCount(req.body.range.from, req.body.range.to, req.body.intervalMs) } @@ -172,7 +174,7 @@ app.use(function(error, req, res, next) // Get config from server/default.json var serverConfig = config.get('server'); -app.listen(serverConfig.port); +app.listen(serverConfig.port, serverConfig.host); console.log("Server is listening on port " + serverConfig.port); @@ -232,7 +234,7 @@ function parseQuery(query, substitutions) } // Args is the rest up to the last bracket - var closeBracketIndex = query.indexOf(')', openBracketIndex) + var closeBracketIndex = query.lastIndexOf(')') if (closeBracketIndex == -1) { queryErrors.push("Can't find last bracket") @@ -244,7 +246,13 @@ function parseQuery(query, substitutions) { // Wrap args in array syntax so we can check for optional options arg args = '[' + args + ']' - docs = JSON.parse(args) + //docs = JSON.parse(args) + // Replace with substitutions + for (var key in substitutions) { + var regex = new RegExp(escapeStringRegexp(key), 'g') + args = args.replace(regex, substitutions[key]) + } + docs = parser(args) // First Arg is pipeline doc.pipeline = docs[0] // If we have 2 top level args, second is agg options @@ -253,7 +261,7 @@ function parseQuery(query, substitutions) doc.agg_options = docs[1] } // Replace with substitutions - for ( var i = 0; i < doc.pipeline.length; i++) + /*for ( var i = 0; i < doc.pipeline.length; i++) { var stage = doc.pipeline[i] forIn(stage, function (obj, key, value) @@ -266,7 +274,7 @@ function parseQuery(query, substitutions) } } }) - } + }*/ } else { @@ -525,4 +533,4 @@ function getBucketCount(from, to, intervalMs) } return count -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 610f63e..dcb5408 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,18 @@ { "name": "grafana-mongodb", - "version": "0.7.0", + "version": "0.8.1", "lockfileVersion": 1, "requires": true, "dependencies": { + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -1029,6 +1038,11 @@ "integrity": "sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ==", "dev": true }, + "context-eval": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/context-eval/-/context-eval-0.1.0.tgz", + "integrity": "sha1-P8pxfX3wI6l4XwjGWkGJo93wP6s=" + }, "continuable-cache": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", @@ -1197,6 +1211,11 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, + "duplexer": { + "version": "0.1.1", + "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -1340,6 +1359,20 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", + "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", + "requires": { + "duplexer": "^0.1.1", + "from": "^0.1.7", + "map-stream": "0.0.7", + "pause-stream": "^0.0.11", + "split": "^1.0.1", + "stream-combiner": "^0.2.2", + "through": "^2.3.8" + } + }, "eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", @@ -1595,6 +1628,11 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, "fs": { "version": "0.0.1-security", "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", @@ -2102,6 +2140,11 @@ "number-is-nan": "^1.0.0" } }, + "is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha1-a+Fm0USCihMdaGiRuYPfYsOUkf8=" + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -2132,6 +2175,11 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, + "javascript-stringify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", + "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=" + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -2210,6 +2258,11 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -2293,6 +2346,16 @@ "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.transform": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", + "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=" + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -2317,12 +2380,26 @@ "signal-exit": "^3.0.0" } }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" + }, "maxmin": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", @@ -2493,6 +2570,88 @@ "require_optional": "^1.0.1" } }, + "mongodb-extended-json": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/mongodb-extended-json/-/mongodb-extended-json-1.10.1.tgz", + "integrity": "sha512-2J+MMnahqaqBXSIVYwEUV9qwJKRtkOlr6qEKPs4aHKvOpyfucjdBWORXinn/Ez1Nwa5sVXak+r8lfGliXd2UPg==", + "requires": { + "JSONStream": "^1.1.1", + "async": "^2.0.1", + "bson": "^1.0.1", + "event-stream": "^4.0.1", + "lodash.isfunction": "^3.0.6", + "lodash.transform": "^4.6.0", + "moment": "^2.10.6", + "raf": "^3.1.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "mongodb-language-model": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mongodb-language-model/-/mongodb-language-model-1.3.0.tgz", + "integrity": "sha512-Sl2aR66C/JxUzC/KX0itD68das6U4D71v9/VeON3vVLuCU/EyXnqZ18JePvEXYVYFQVOVB9ui+CNxn08oAHhDA==", + "requires": { + "bson": "^1.0.1", + "debug": "^2.2.0", + "lodash": "^3.0.1", + "pegjs": "^0.10.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + } + } + }, + "mongodb-query-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/mongodb-query-parser/-/mongodb-query-parser-1.2.1.tgz", + "integrity": "sha512-bepEJZs0qBQNhMwdmf7DDc4hWx//kdgJg50G/qcW1NN7mhI64l2cpCZnUYDZlkffdL9msrYmrxvoAkIyRxV6ZA==", + "requires": { + "bson": "^1.0.9", + "context-eval": "^0.1.0", + "debug": "^3.1.0", + "is-json": "^2.0.1", + "javascript-stringify": "^1.6.0", + "lodash": "^4.17.4", + "lru-cache": "^4.1.1", + "mongodb-extended-json": "^1.10.0", + "mongodb-language-model": "^1.3.0", + "ms": "^2.0.0" + }, + "dependencies": { + "bson": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.0.tgz", + "integrity": "sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA==" + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2683,6 +2842,19 @@ "pinkie-promise": "^2.0.0" } }, + "pause-stream": { + "version": "0.0.11", + "resolved": "http://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "~2.3" + } + }, + "pegjs": { + "version": "0.10.0", + "resolved": "http://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -2760,6 +2932,11 @@ "integrity": "sha512-nLpTxQCqaKzdpzA344aK8u1wpVcnT0OD9oruH281TeqkqnxCWW4dD8Vn65mQWlfwPO8yWFyeK2h2qcw2N7hveA==", "dev": true }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -2777,6 +2954,14 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } + }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -3115,6 +3300,14 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2" + } + }, "sprintf-js": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", @@ -3161,6 +3354,15 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "http://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "requires": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, "string-template": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", @@ -3247,6 +3449,11 @@ "uglify-js": "^2.6.1" } }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, "tiny-lr": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", @@ -3591,6 +3798,11 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", diff --git a/package.json b/package.json index 5e63bd8..aee4b57 100644 --- a/package.json +++ b/package.json @@ -46,12 +46,14 @@ "babel-preset-es2015": "^6.24.1", "body-parser": "^1.18.3", "config": "^1.30.0", + "escape-string-regexp": "^1.0.5", "express": "^4.16.3", "fs": "0.0.1-security", "lodash": "^4.17.10", "mocha": "^5.2.0", "moment": "^2.22.1", "mongodb": "^3.0.8", + "mongodb-query-parser": "^1.2.1", "statman-stopwatch": "^2.7.0" }, "homepage": "https://github.com/JamesOsgood/mongodb-grafana#readme" diff --git a/server/config/default.json b/server/config/default.json index 5ee4cf1..a7bd97f 100644 --- a/server/config/default.json +++ b/server/config/default.json @@ -2,9 +2,10 @@ "server": { "port": 3333, + "host": "127.0.0.1", "logRequests": false, "logQueries": false, "logTimings": false } } - \ No newline at end of file + diff --git a/server/mongodb-proxy.js b/server/mongodb-proxy.js index a3fc84e..0e68c95 100644 --- a/server/mongodb-proxy.js +++ b/server/mongodb-proxy.js @@ -1,3 +1,5 @@ +var parser = require('mongodb-query-parser'); +var escapeStringRegexp = require('escape-string-regexp'); var express = require('express'); var bodyParser = require('body-parser'); var _ = require('lodash'); @@ -128,8 +130,8 @@ app.all('/query', function(req, res, next) setCORSHeaders(res); // Parse query string in target - substitutions = { "$from" : new Date(req.body.range.from), - "$to" : new Date(req.body.range.to), + substitutions = { "$from" : req.body.range.from, + "$to" : req.body.range.to, "$dateBucketCount" : getBucketCount(req.body.range.from, req.body.range.to, req.body.intervalMs) } @@ -172,7 +174,7 @@ app.use(function(error, req, res, next) // Get config from server/default.json var serverConfig = config.get('server'); -app.listen(serverConfig.port); +app.listen(serverConfig.port, serverConfig.host); console.log("Server is listening on port " + serverConfig.port); @@ -232,7 +234,7 @@ function parseQuery(query, substitutions) } // Args is the rest up to the last bracket - var closeBracketIndex = query.indexOf(')', openBracketIndex) + var closeBracketIndex = query.lastIndexOf(')') if (closeBracketIndex == -1) { queryErrors.push("Can't find last bracket") @@ -244,7 +246,13 @@ function parseQuery(query, substitutions) { // Wrap args in array syntax so we can check for optional options arg args = '[' + args + ']' - docs = JSON.parse(args) + //docs = JSON.parse(args) + // Replace with substitutions + for (var key in substitutions) { + var regex = new RegExp(escapeStringRegexp(key), 'g') + args = args.replace(regex, substitutions[key]) + } + docs = parser(args) // First Arg is pipeline doc.pipeline = docs[0] // If we have 2 top level args, second is agg options @@ -253,7 +261,7 @@ function parseQuery(query, substitutions) doc.agg_options = docs[1] } // Replace with substitutions - for ( var i = 0; i < doc.pipeline.length; i++) + /*for ( var i = 0; i < doc.pipeline.length; i++) { var stage = doc.pipeline[i] forIn(stage, function (obj, key, value) @@ -266,7 +274,7 @@ function parseQuery(query, substitutions) } } }) - } + }*/ } else { @@ -525,4 +533,4 @@ function getBucketCount(from, to, intervalMs) } return count -} \ No newline at end of file +}