From b1d7306c745c6aa8bc64a6b0ef5a61e68c74edfb Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Wed, 8 Oct 2014 10:12:52 +0200 Subject: [PATCH 01/76] Have ./configure tolerate unknown options --- configure | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/configure b/configure index cbf3e9ee..3ae5ca06 100755 --- a/configure +++ b/configure @@ -20,9 +20,8 @@ while test -n "$1"; do PGPORT=`echo "$1" | cut -d= -f2` ;; *) - echo "Unknown option '$1'" >&2 - usage >&2 - exit 1 + echo "Unused option '$1'" >&2 + ;; esac shift done From 085abb3446479be30f6fd5a03a209c7d0701c9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Mon, 1 Aug 2016 11:48:11 +0200 Subject: [PATCH 02/76] Removed duplicated config --- test/acceptance/batch.test.js | 13 +++---------- test/acceptance/job.callback-template.test.js | 11 ++--------- test/acceptance/job.fallback.test.js | 11 ++--------- test/acceptance/job.timing.test.js | 11 ++--------- test/acceptance/job.use-case-1.test.js | 11 ++--------- test/acceptance/job.use-case-10.test.js | 11 ++--------- test/acceptance/job.use-case-2.test.js | 11 ++--------- test/acceptance/job.use-case-3.test.js | 11 ++--------- test/acceptance/job.use-case-4.test.js | 11 ++--------- test/acceptance/job.use-case-5.test.js | 11 ++--------- test/acceptance/job.use-case-6.test.js | 11 ++--------- test/acceptance/job.use-case-7.test.js | 11 ++--------- test/acceptance/job.use-case-8.test.js | 11 ++--------- test/acceptance/job.use-case-9.test.js | 11 ++--------- test/integration/batch/batch.multiquery.test.js | 14 +++----------- test/integration/batch/job_backend.test.js | 12 ++---------- test/integration/batch/job_canceller.test.js | 12 ++---------- test/integration/batch/job_publisher.test.js | 13 +++---------- test/integration/batch/job_runner.test.js | 11 ++--------- test/integration/batch/job_service.test.js | 12 ++---------- test/support/redis_utils.js | 4 ++++ 21 files changed, 47 insertions(+), 187 deletions(-) diff --git a/test/acceptance/batch.test.js b/test/acceptance/batch.test.js index d1cffa68..122ffe00 100644 --- a/test/acceptance/batch.test.js +++ b/test/acceptance/batch.test.js @@ -12,19 +12,12 @@ var JobBackend = require('../../batch/job_backend'); var JobService = require('../../batch/job_service'); var UserDatabaseMetadataService = require('../../batch/user_database_metadata_service'); var JobCanceller = require('../../batch/job_canceller'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); describe('batch module', function() { var dbInstance = 'localhost'; var username = 'vizzuality'; - var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); + var redisPoolPublisher = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-publisher'})); var jobPublisher = new JobPublisher(redisPoolPublisher); var jobQueue = new JobQueue(metadataBackend, jobPublisher); var userIndexer = new UserIndexer(metadataBackend); @@ -33,7 +26,7 @@ describe('batch module', function() { var jobCanceller = new JobCanceller(userDatabaseMetadataService); var jobService = new JobService(jobBackend, jobCanceller); - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.callback-template.test.js b/test/acceptance/job.callback-template.test.js index 39cfc593..272beb30 100644 --- a/test/acceptance/job.callback-template.test.js +++ b/test/acceptance/job.callback-template.test.js @@ -4,14 +4,7 @@ var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var app = require(global.settings.app_root + '/app/app')(); var querystring = require('qs'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); var jobStatus = require('../../batch/job_status'); @@ -95,7 +88,7 @@ describe('Batch API callback templates', function () { assert.equal(actual.onerror, expected.onerror); } - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.fallback.test.js b/test/acceptance/job.fallback.test.js index 71e6e8e6..4185222e 100644 --- a/test/acceptance/job.fallback.test.js +++ b/test/acceptance/job.fallback.test.js @@ -4,14 +4,7 @@ var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var app = require(global.settings.app_root + '/app/app')(); var querystring = require('qs'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); var jobStatus = require('../../batch/job_status'); @@ -36,7 +29,7 @@ describe('Batch API fallback job', function () { assert.equal(actual.onerror, expected.onerror); } - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.timing.test.js b/test/acceptance/job.timing.test.js index 610ae446..52bd9e33 100644 --- a/test/acceptance/job.timing.test.js +++ b/test/acceptance/job.timing.test.js @@ -4,14 +4,7 @@ var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var app = require(global.settings.app_root + '/app/app')(); var querystring = require('qs'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); var jobStatus = require('../../batch/job_status'); @@ -72,7 +65,7 @@ describe('Batch API query timing', function () { assert.equal(actual.onerror, expected.onerror); } - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-1.test.js b/test/acceptance/job.use-case-1.test.js index 53ee9596..c34d08e0 100644 --- a/test/acceptance/job.use-case-1.test.js +++ b/test/acceptance/job.use-case-1.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 1: cancel and modify a done job', function () { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-10.test.js b/test/acceptance/job.use-case-10.test.js index df80dff8..1b08fa87 100644 --- a/test/acceptance/job.use-case-10.test.js +++ b/test/acceptance/job.use-case-10.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 10: cancel and modify a done multiquery job', function () { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-2.test.js b/test/acceptance/job.use-case-2.test.js index 8896bbaa..9090bc64 100644 --- a/test/acceptance/job.use-case-2.test.js +++ b/test/acceptance/job.use-case-2.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 2: cancel a running job', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-3.test.js b/test/acceptance/job.use-case-3.test.js index dc35346c..54635823 100644 --- a/test/acceptance/job.use-case-3.test.js +++ b/test/acceptance/job.use-case-3.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 3: cancel a pending job', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-4.test.js b/test/acceptance/job.use-case-4.test.js index 570e5358..793c9def 100644 --- a/test/acceptance/job.use-case-4.test.js +++ b/test/acceptance/job.use-case-4.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 4: modify a pending job', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-5.test.js b/test/acceptance/job.use-case-5.test.js index 31c55874..843a8c30 100644 --- a/test/acceptance/job.use-case-5.test.js +++ b/test/acceptance/job.use-case-5.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 5: modify a running job', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-6.test.js b/test/acceptance/job.use-case-6.test.js index b6116d4b..fe770b01 100644 --- a/test/acceptance/job.use-case-6.test.js +++ b/test/acceptance/job.use-case-6.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 6: modify a done job', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-7.test.js b/test/acceptance/job.use-case-7.test.js index e9364ea4..df711c2c 100644 --- a/test/acceptance/job.use-case-7.test.js +++ b/test/acceptance/job.use-case-7.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 7: cancel a job with quotes', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-8.test.js b/test/acceptance/job.use-case-8.test.js index 109f9f73..75f98251 100644 --- a/test/acceptance/job.use-case-8.test.js +++ b/test/acceptance/job.use-case-8.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 8: cancel a running multiquery job', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/acceptance/job.use-case-9.test.js b/test/acceptance/job.use-case-9.test.js index 8e3212df..19c9cefe 100644 --- a/test/acceptance/job.use-case-9.test.js +++ b/test/acceptance/job.use-case-9.test.js @@ -18,18 +18,11 @@ var app = require(global.settings.app_root + '/app/app')(); var assert = require('../support/assert'); var redisUtils = require('../support/redis_utils'); var querystring = require('querystring'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var batchFactory = require('../../batch'); describe('Use case 9: modify a pending multiquery job', function() { - var batch = batchFactory(metadataBackend, redisConfig); + var batch = batchFactory(metadataBackend, redisUtils.getConfig()); before(function (done) { batch.start(); diff --git a/test/integration/batch/batch.multiquery.test.js b/test/integration/batch/batch.multiquery.test.js index 11583035..e26c274e 100644 --- a/test/integration/batch/batch.multiquery.test.js +++ b/test/integration/batch/batch.multiquery.test.js @@ -5,15 +5,7 @@ var assert = require('../../support/assert'); var redisUtils = require('../../support/redis_utils'); var queue = require('queue-async'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; - -var metadataBackend = require('cartodb-redis')(redisConfig); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); var StatsD = require('node-statsd').StatsD; var statsdClient = new StatsD(global.settings.statsd); @@ -30,7 +22,7 @@ var UserIndexer = require(BATCH_SOURCE + 'user_indexer'); var JobBackend = require(BATCH_SOURCE + 'job_backend'); var JobFactory = require(BATCH_SOURCE + 'models/job_factory'); -var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); +var redisPoolPublisher = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-publisher'})); var jobPublisher = new JobPublisher(redisPoolPublisher); var jobQueue = new JobQueue(metadataBackend, jobPublisher); var userIndexer = new UserIndexer(metadataBackend); @@ -69,7 +61,7 @@ function assertJob(job, expectedStatus, done) { } describe('batch multiquery', function() { - var batch = batchFactory(metadataBackend, redisConfig, statsdClient); + var batch = batchFactory(metadataBackend, redisUtils.getConfig(), statsdClient); before(function (done) { batch.start(); diff --git a/test/integration/batch/job_backend.test.js b/test/integration/batch/job_backend.test.js index bdd0b1f2..b32e87d9 100644 --- a/test/integration/batch/job_backend.test.js +++ b/test/integration/batch/job_backend.test.js @@ -16,16 +16,8 @@ var JobPublisher = require(BATCH_SOURCE + 'job_publisher'); var JobFactory = require(BATCH_SOURCE + 'models/job_factory'); var jobStatus = require(BATCH_SOURCE + 'job_status'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; - -var metadataBackend = require('cartodb-redis')(redisConfig); -var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); +var redisPoolPublisher = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-publisher'})); var jobPublisher = new JobPublisher(redisPoolPublisher); var jobQueue = new JobQueue(metadataBackend, jobPublisher); var userIndexer = new UserIndexer(metadataBackend); diff --git a/test/integration/batch/job_canceller.test.js b/test/integration/batch/job_canceller.test.js index 5d704567..a0cab6ff 100644 --- a/test/integration/batch/job_canceller.test.js +++ b/test/integration/batch/job_canceller.test.js @@ -18,16 +18,8 @@ var UserDatabaseMetadataService = require(BATCH_SOURCE + 'user_database_metadata var JobCanceller = require(BATCH_SOURCE + 'job_canceller'); var PSQL = require('cartodb-psql'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; - -var metadataBackend = require('cartodb-redis')(redisConfig); -var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); +var redisPoolPublisher = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-publisher'})); var jobPublisher = new JobPublisher(redisPoolPublisher); var jobQueue = new JobQueue(metadataBackend, jobPublisher); var userIndexer = new UserIndexer(metadataBackend); diff --git a/test/integration/batch/job_publisher.test.js b/test/integration/batch/job_publisher.test.js index d6690247..57daf733 100644 --- a/test/integration/batch/job_publisher.test.js +++ b/test/integration/batch/job_publisher.test.js @@ -8,19 +8,12 @@ var assert = require('../../support/assert'); var _ = require('underscore'); var RedisPool = require('redis-mpool'); +var redisUtils = require('../../support/redis_utils'); var JobPublisher = require(BATCH_SOURCE + 'job_publisher'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; - -var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); -var redisPoolSubscriber = new RedisPool(_.extend(redisConfig, { name: 'batch-subscriber'})); +var redisPoolPublisher = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-publisher'})); +var redisPoolSubscriber = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-subscriber'})); var HOST = 'wadus'; var CHANNEL = 'batch:hosts'; diff --git a/test/integration/batch/job_runner.test.js b/test/integration/batch/job_runner.test.js index 0fbbee4c..0a1ab13d 100644 --- a/test/integration/batch/job_runner.test.js +++ b/test/integration/batch/job_runner.test.js @@ -20,16 +20,9 @@ var JobService = require(BATCH_SOURCE + 'job_service'); var JobRunner = require(BATCH_SOURCE + 'job_runner'); var QueryRunner = require(BATCH_SOURCE + 'query_runner'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; -var metadataBackend = require('cartodb-redis')(redisConfig); -var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); +var redisPoolPublisher = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-publisher'})); var jobPublisher = new JobPublisher(redisPoolPublisher); var jobQueue = new JobQueue(metadataBackend, jobPublisher); var userIndexer = new UserIndexer(metadataBackend); diff --git a/test/integration/batch/job_service.test.js b/test/integration/batch/job_service.test.js index 60b131e0..2c520623 100644 --- a/test/integration/batch/job_service.test.js +++ b/test/integration/batch/job_service.test.js @@ -19,16 +19,8 @@ var JobCanceller = require(BATCH_SOURCE + 'job_canceller'); var JobService = require(BATCH_SOURCE + 'job_service'); var PSQL = require('cartodb-psql'); -var redisConfig = { - host: global.settings.redis_host, - port: global.settings.redis_port, - max: global.settings.redisPool, - idleTimeoutMillis: global.settings.redisIdleTimeoutMillis, - reapIntervalMillis: global.settings.redisReapIntervalMillis -}; - -var metadataBackend = require('cartodb-redis')(redisConfig); -var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); +var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); +var redisPoolPublisher = new RedisPool(_.extend(redisUtils.getConfig(), { name: 'batch-publisher'})); var jobPublisher = new JobPublisher(redisPoolPublisher); var jobQueue = new JobQueue(metadataBackend, jobPublisher); var userIndexer = new UserIndexer(metadataBackend); diff --git a/test/support/redis_utils.js b/test/support/redis_utils.js index ec0a8043..7d6396d2 100644 --- a/test/support/redis_utils.js +++ b/test/support/redis_utils.js @@ -18,3 +18,7 @@ module.exports.clean = function clean(pattern, callback) { metadataBackend.redisCmd(5, 'DEL', keys, callback); }); }; + +module.exports.getConfig = function getConfig() { + return redisConfig; +}; From 94eb758c18d4887cc798b1339181f93593483156 Mon Sep 17 00:00:00 2001 From: csobier Date: Tue, 13 Sep 2016 08:48:13 -0400 Subject: [PATCH 03/76] added another best practice to batch queries content --- .DS_Store | Bin 0 -> 6148 bytes doc/batch_queries.md | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9f3c7cfcfa748fe73d553d74fe1246bd0679700a GIT binary patch literal 6148 zcmeHK&1xGl5SDDG+4Wwww1Ge`x)ywJaGYGXZgMObHYAj$xVzn@7Az~{UB?t-*mEBv z{mU!l9NKs2qx9ApNj5faZ>7{>21eg#G$UD`jAq3c2%;fey;K|l6g8_Nxi&~d7`F0 zHOZ6WGBopD$fO(&{Js7-y@J$!l&9yikg?2U`QC9|*Kr5_{%qFibX%g+J({<~?D)9d z5{I3m`P{#CoF`Aa&tAM7%|Bd!{Pg+D*PFX<<_tLeU9~*2xPb3qSURr4ah|FC9e5Ve zizq^3fEXYKwwwWbtvTM7?}L6mF+dFbeFpG;5TJ;G#mb<*I-tSNM;vb;qJWKW2}EHr zuvi&{5fE-t0Zl5mPYiC-!7prFV6if2(izt)!#s9nZeJ)|uMU2p!x;|@QcDaF1M3Xb zP1nczfBNV5|9TSjhyh~YUNOKMC*esCwq$GT#^$ir3eY#8C>U26T&94bOEJV^Dc%Rw a0)Bx8U|_K_2p$mn5YRMGLk#>=27UpYT4N*t literal 0 HcmV?d00001 diff --git a/doc/batch_queries.md b/doc/batch_queries.md index cbb96649..cee5d8d3 100644 --- a/doc/batch_queries.md +++ b/doc/batch_queries.md @@ -482,6 +482,8 @@ In some scenarios, you may need to fetch the output of a job. If that is the cas For best practices, follow these recommended usage notes when using Batch Queries: +- Batch Queries are recommended for INSERT, UPDATE, and CREATE queries that manipulate and create new data, such as creating expensive indexes, applying updates over large tables, and creating tables from complex queries. Batch queries will **not** improve processing times for SELECT queries that retrieve data but do not store the results in a table + - Batch Queries are not intended for large query payloads (e.g: inserting thousands of rows), use the [Import API](https://carto.com/docs/carto-engine/import-api/) for this type of data management - There is a limit of 8kb per job. The following error message appears if your job exceeds this size: From f0e790fe6e7c24098084b921c7c50fb4c0bf0b1a Mon Sep 17 00:00:00 2001 From: csobier Date: Tue, 13 Sep 2016 10:01:31 -0400 Subject: [PATCH 04/76] applied edits --- .DS_Store | Bin 6148 -> 6148 bytes doc/batch_queries.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.DS_Store b/.DS_Store index 9f3c7cfcfa748fe73d553d74fe1246bd0679700a..120629ae41f27364822ec7e686119e2bdaf07665 100644 GIT binary patch delta 94 zcmV-k0HObcFoZCWVFUVNaI-N3rvZ~N6aQEFd*DFnxUxxd;dwDK$Y&S#W)dqNAjxrl+XH#*_O39|6a+8w2YEvj+(M4~y?0 A6#xJL delta 93 zcmV-j0HXhdFoZCWVFUSMaI--JrvZ~N6aKeJmh* zH#aaWAT%>JeSHwQ2nZV~H9<{TaD9rRqok##r>Milll%f70mic&1M38{1_=HSd(t2K diff --git a/doc/batch_queries.md b/doc/batch_queries.md index cee5d8d3..46c6bdf5 100644 --- a/doc/batch_queries.md +++ b/doc/batch_queries.md @@ -482,7 +482,7 @@ In some scenarios, you may need to fetch the output of a job. If that is the cas For best practices, follow these recommended usage notes when using Batch Queries: -- Batch Queries are recommended for INSERT, UPDATE, and CREATE queries that manipulate and create new data, such as creating expensive indexes, applying updates over large tables, and creating tables from complex queries. Batch queries will **not** improve processing times for SELECT queries that retrieve data but do not store the results in a table +- Batch Queries are recommended for INSERT, UPDATE, and CREATE queries that manipulate and create new data, such as creating expensive indexes, applying updates over large tables, and creating tables from complex queries. Batch queries have no effect for SELECT queries that retrieve data but do not store the results in a table. For example, running a batch query using `SELECT * from my_dataset` will not produce any results - Batch Queries are not intended for large query payloads (e.g: inserting thousands of rows), use the [Import API](https://carto.com/docs/carto-engine/import-api/) for this type of data management From 80445c7d49da503cdfc71f1c8c2e86a98d77edb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Tue, 13 Sep 2016 16:54:29 +0200 Subject: [PATCH 05/76] Removed unneeded file --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 120629ae41f27364822ec7e686119e2bdaf07665..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!A{#i5Zz7E){ZZ(S|m^}z9Qvd+5%S-=n*NB5eNZFZEQ6wS>7mih^i=(&;1N2 zw79z*i5#`% zFi(oZP|vp~lCsxz7dnIV1X4Rup6-f5#3B>rcgwbI%kH{M8ED);>;J-gtc- z?A0}YGI1|0>%;Qu#`b=H^5gXE=lR92-&fcA5IFo_mAo@Jg&QyoA1C1;&t(1$Jk#iD z6d^G{3=jj)n*npHS4B-9Xfg%P5D~;;vfCfJwalCfrZOIOBmvYKZ}2V3vWp z?z&k2zx@0CKbu57Vt^QUQ4H|LR=CxMEt%Rnw>hk}9_Uw46pX7h-lu?}N-@M@DP9Cs a0)7t-z`$Uo5j-IDA)siWh8TEM2JQeF++$Aw From 0626d80e24fd4bffd9917816fae1a145c28c2178 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 14 Sep 2016 19:22:31 +0200 Subject: [PATCH 06/76] Removes support for optional rollbar logging --- NEWS.md | 5 ++- app.js | 7 ---- app/models/log4js_rollbar.js | 51 ----------------------- config/environments/production.js.example | 8 ---- config/environments/staging.js.example | 8 ---- npm-shrinkwrap.json | 23 ++-------- package.json | 1 - 7 files changed, 7 insertions(+), 96 deletions(-) delete mode 100644 app/models/log4js_rollbar.js diff --git a/NEWS.md b/NEWS.md index 5d6e1ddc..ea43ca50 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ -1.34.3 - 2016-mm-dd +1.35.0 - 2016-mm-dd ------------------- +Announcements: + * Removes support for optional rollbar logging. + 1.34.2 - 2016-08-30 ------------------- diff --git a/app.js b/app.js index e62e040f..36b76c95 100755 --- a/app.js +++ b/app.js @@ -60,13 +60,6 @@ if ( env.log_filename ) { ); } -if ( global.settings.rollbar ) { - log4js_config.appenders.push({ - type: __dirname + "/app/models/log4js_rollbar.js", - options: global.settings.rollbar - }); -} - global.log4js.configure(log4js_config, { cwd: __dirname }); global.logger = global.log4js.getLogger(); diff --git a/app/models/log4js_rollbar.js b/app/models/log4js_rollbar.js deleted file mode 100644 index c26e1eb6..00000000 --- a/app/models/log4js_rollbar.js +++ /dev/null @@ -1,51 +0,0 @@ -var rollbar = require("rollbar"); - -/** - * Rollbar Appender. Sends logging events to Rollbar using node-rollbar - * - * @param config object with rollbar configuration data - * { - * token: 'your-secret-token', - * options: node-rollbar options - * } - */ -function rollbarAppender(config) { - - var opt = config.options; - rollbar.init(opt.token, opt.options); - - return function(loggingEvent) { -/* -For logger.trace('one','two','three'): -{ startTime: Wed Mar 12 2014 16:27:40 GMT+0100 (CET), - categoryName: '[default]', - data: [ 'one', 'two', 'three' ], - level: { level: 5000, levelStr: 'TRACE' }, - logger: { category: '[default]', _events: { log: [Object] } } } -*/ - - // Levels: - // TRACE 5000 - // DEBUG 10000 - // INFO 20000 - // WARN 30000 - // ERROR 40000 - // FATAL 50000 - // - // We only log error and higher errors - // - if ( loggingEvent.level.level < 40000 ) { - return; - } - - rollbar.reportMessage(loggingEvent.data); - }; -} - -function configure(config) { - return rollbarAppender(config); -} - -exports.name = "rollbar"; -exports.appender = rollbarAppender; -exports.configure = configure; diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 778cc348..96683a51 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -64,14 +64,6 @@ module.exports.tableCacheMaxAge = 1000*60*10; module.exports.tmpDir = '/tmp'; // change ogr2ogr command or path module.exports.ogr2ogrCommand = 'ogr2ogr'; -// Optional rollbar support -module.exports.rollbar = { - token: 'secret', - // See http://github.com/rollbar/node_rollbar#configuration-reference - options: { - handler: 'inline' - } -} // Optional statsd support module.exports.statsd = { host: 'localhost', diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index e26193d2..123e56fd 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -64,14 +64,6 @@ module.exports.tableCacheMaxAge = 1000*60*10; module.exports.tmpDir = '/tmp'; // change ogr2ogr command or path module.exports.ogr2ogrCommand = 'ogr2ogr'; -// Optional rollbar support -module.exports.rollbar = { - token: 'secret', - // See http://github.com/rollbar/node_rollbar#configuration-reference - options: { - handler: 'inline' - } -} // Optional statsd support module.exports.statsd = { host: 'localhost', diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a46873e6..2e2cd17b 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.34.2", + "version": "1.34.3", "dependencies": { "cartodb-psql": { "version": "0.6.1", @@ -120,9 +120,9 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { - "version": "2.0.1", + "version": "2.0.3", "from": "inherits@>=2.0.1 <2.1.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" } } }, @@ -204,23 +204,6 @@ } } }, - "rollbar": { - "version": "0.3.13", - "from": "rollbar@>=0.3.2 <0.4.0", - "resolved": "https://registry.npmjs.org/rollbar/-/rollbar-0.3.13.tgz", - "dependencies": { - "lru-cache": { - "version": "2.2.4", - "from": "lru-cache@>=2.2.1 <2.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz" - }, - "json-stringify-safe": { - "version": "5.0.1", - "from": "json-stringify-safe@>=5.0.0 <5.1.0", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" - } - } - }, "step": { "version": "0.0.6", "from": "step@>=0.0.5 <0.1.0", diff --git a/package.json b/package.json index efa8105c..fccca5cc 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "oauth-client": "0.3.0", "queue-async": "~1.0.7", "redis-mpool": "0.4.0", - "rollbar": "~0.3.2", "step": "~0.0.5", "step-profiler": "~0.3.0", "topojson": "0.0.8", From e315e77525d34b21b1259d88efa3aef1544af116 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 14 Sep 2016 20:03:05 +0200 Subject: [PATCH 07/76] Allow to use absolute paths for log files Fixes #355 --- NEWS.md | 3 +++ app.js | 28 +++++++++++++--------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/NEWS.md b/NEWS.md index ea43ca50..f5965a11 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ 1.35.0 - 2016-mm-dd ------------------- +Bug fixes: + * Allow to use absolute paths for log files. + Announcements: * Removes support for optional rollbar logging. diff --git a/app.js b/app.js index 36b76c95..b1d91cb9 100755 --- a/app.js +++ b/app.js @@ -37,30 +37,28 @@ env.api_hostname = require('os').hostname().split('.')[0]; _.extend(global.settings, env); global.log4js = require('log4js'); -var log4js_config = { - appenders: [], - replaceConsole:true +var log4jsConfig = { + appenders: [], + replaceConsole: true }; if ( env.log_filename ) { - var logdir = path.dirname(env.log_filename); - // See cwd inlog4js.configure call below - logdir = path.resolve(__dirname, logdir); - if ( ! fs.existsSync(logdir) ) { - console.error("Log filename directory does not exist: " + logdir); + var logFilename = path.resolve(env.log_filename); + var logDirectory = path.dirname(logFilename); + if (!fs.existsSync(logDirectory)) { + console.error("Log filename directory does not exist: " + logDirectory); process.exit(1); } - console.log("Logs will be written to " + env.log_filename); - log4js_config.appenders.push( - { type: "file", filename: env.log_filename } + console.log("Logs will be written to " + logFilename); + log4jsConfig.appenders.push( + { type: "file", absolute: true, filename: logFilename } ); } else { - log4js_config.appenders.push( + log4jsConfig.appenders.push( { type: "console", layout: { type:'basic' } } ); } - -global.log4js.configure(log4js_config, { cwd: __dirname }); +global.log4js.configure(log4jsConfig); global.logger = global.log4js.getLogger(); @@ -85,7 +83,7 @@ process.on('uncaughtException', function(err) { process.on('SIGHUP', function() { global.log4js.clearAndShutdownAppenders(function() { - global.log4js.configure(log4js_config); + global.log4js.configure(log4jsConfig); global.logger = global.log4js.getLogger(); console.log('Log files reloaded'); }); From f92d50cccf27fd5acc524cad819aac4013705abf Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 14 Sep 2016 20:54:24 +0200 Subject: [PATCH 08/76] Rename from app to server Removes app_root dependency in requires --- app.js | 8 +- app/{app.js => server.js} | 0 test/acceptance/app.auth.test.js | 4 +- test/acceptance/app.test.js | 142 +++++++++--------- test/acceptance/backend_crash.js | 6 +- test/acceptance/export/arraybuffer.js | 8 +- test/acceptance/export/csv.js | 24 +-- test/acceptance/export/geojson.js | 26 ++-- test/acceptance/export/geopackage.js | 6 +- test/acceptance/export/kml.js | 36 ++--- test/acceptance/export/shapefile.js | 30 ++-- test/acceptance/export/spatialite.js | 8 +- test/acceptance/export/svg.js | 22 +-- test/acceptance/export/topojson.js | 14 +- test/acceptance/frontend_abort.js | 4 +- test/acceptance/health_check.js | 6 +- test/acceptance/job.callback-template.test.js | 8 +- test/acceptance/job.fallback.test.js | 98 ++++++------ test/acceptance/job.query.limit.test.js | 10 +- test/acceptance/job.test.js | 24 +-- test/acceptance/job.timing.test.js | 6 +- test/acceptance/job.use-case-1.test.js | 8 +- test/acceptance/job.use-case-10.test.js | 8 +- test/acceptance/job.use-case-2.test.js | 12 +- test/acceptance/job.use-case-3.test.js | 12 +- test/acceptance/job.use-case-4.test.js | 10 +- test/acceptance/job.use-case-5.test.js | 8 +- test/acceptance/job.use-case-6.test.js | 6 +- test/acceptance/job.use-case-7.test.js | 8 +- test/acceptance/job.use-case-8.test.js | 12 +- test/acceptance/job.use-case-9.test.js | 10 +- test/acceptance/last-modified-header.js | 8 +- test/acceptance/logging.js | 4 +- test/acceptance/query-tables-api-cache.js | 10 +- test/acceptance/regressions.js | 8 +- test/acceptance/stream-responses.js | 6 +- test/acceptance/surrogate-key.js | 18 +-- test/acceptance/timeout.js | 4 +- test/acceptance/transaction.js | 2 +- test/acceptance/x-cache-channel.js | 18 +-- 40 files changed, 331 insertions(+), 331 deletions(-) rename app/{app.js => server.js} (100%) diff --git a/app.js b/app.js index b1d91cb9..9f981e12 100755 --- a/app.js +++ b/app.js @@ -69,8 +69,8 @@ if ( ! global.settings.base_url ) { var version = require("./package").version; -var app = require(global.settings.app_root + '/app/app')(); -app.listen(global.settings.node_port, global.settings.node_host, function() { +var server = require('app/server')(); +server.listen(global.settings.node_port, global.settings.node_host, function() { console.log( "CartoDB SQL API %s listening on %s:%s with base_url %s (%s)", version, global.settings.node_host, global.settings.node_port, global.settings.base_url, ENV @@ -90,8 +90,8 @@ process.on('SIGHUP', function() { }); process.on('SIGTERM', function () { - app.batch.stop(); - app.batch.drain(function (err) { + server.batch.stop(); + server.batch.drain(function (err) { if (err) { console.log('Exit with error'); return process.exit(1); diff --git a/app/app.js b/app/server.js similarity index 100% rename from app/app.js rename to app/server.js diff --git a/test/acceptance/app.auth.test.js b/test/acceptance/app.auth.test.js index 8418ffa9..dd648cfd 100644 --- a/test/acceptance/app.auth.test.js +++ b/test/acceptance/app.auth.test.js @@ -1,6 +1,6 @@ require('../helper'); -var app = require(global.settings.app_root + '/app/app')(); +var server = require('../../app/server')(); var assert = require('../support/assert'); describe('app.auth', function() { @@ -40,7 +40,7 @@ describe('app.auth', function() { scenarios.forEach(function(scenario) { it(scenario.desc, function(done) { - assert.response(app, { + assert.response(server, { // view prepare_db.sh to find public table name and structure url: scenario.url, headers: { diff --git a/test/acceptance/app.test.js b/test/acceptance/app.test.js index fbd74d94..b7d3aa7c 100644 --- a/test/acceptance/app.test.js +++ b/test/acceptance/app.test.js @@ -14,7 +14,7 @@ */ require('../helper'); -var app = require(global.settings.app_root + '/app/app')(); +var server = require('../../app/server')(); var assert = require('../support/assert'); var querystring = require('querystring'); var _ = require('underscore'); @@ -28,7 +28,7 @@ var expected_rw_cache_control = 'no-cache,max-age=0,must-revalidate,public'; var expected_cache_control_persist = 'public,max-age=31536000'; it('GET /api/v1/version', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/version', method: 'GET' },{}, function(res) { @@ -42,7 +42,7 @@ it('GET /api/v1/version', function(done){ }); it('GET /api/v1/sql', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql', method: 'GET' },{ @@ -57,7 +57,7 @@ it('GET /api/v1/sql', function(done){ // Test base_url setting it('GET /api/whatever/sql', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/whatever/sql?q=SELECT%201', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -70,7 +70,7 @@ it('GET /api/whatever/sql', function(done){ // Test CORS headers with GET it('GET /api/whatever/sql', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/whatever/sql?q=SELECT%201', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -87,7 +87,7 @@ it('GET /api/whatever/sql', function(done){ // Test that OPTIONS does not run queries it('OPTIONS /api/x/sql', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/x/sql?q=syntax%20error', headers: {host: 'vizzuality.cartodb.com'}, method: 'OPTIONS' @@ -105,7 +105,7 @@ it('OPTIONS /api/x/sql', function(done){ it('GET /api/v1/sql with SQL parameter on SELECT only. No oAuth included ', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&database=cartodb_test_user_1_db', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -119,7 +119,7 @@ it('GET /api/v1/sql with SQL parameter on SELECT only. No oAuth included ', func }); it('cache_policy=persist', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&database=cartodb_test_user_1_db&cache_policy=persist', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -135,7 +135,7 @@ it('cache_policy=persist', function(done){ }); it('GET /api/v1/sql with SQL parameter on SELECT only. no database param, just id using headers', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -146,7 +146,7 @@ it('GET /api/v1/sql with SQL parameter on SELECT only. no database param, just i }); it('GET /user/vizzuality/api/v1/sql with SQL parameter on SELECT only', function(done){ - assert.response(app, { + assert.response(server, { url: '/user/vizzuality/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', method: 'GET' },{ }, function(res) { @@ -160,7 +160,7 @@ it('GET /user/vizzuality/api/v1/sql with SQL parameter on SELECT only', function it('SELECT from user-specific database', function(done){ var backupDBHost = global.settings.db_host; global.settings.db_host = '6.6.6.6'; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT+2+as+n', headers: {host: 'cartodb250user.cartodb.com'}, method: 'GET' @@ -183,7 +183,7 @@ it('SELECT from user-specific database', function(done){ it('SELECT with user-specific password', function(done){ var backupDBUserPass = global.settings.db_user_pass; global.settings.db_user_pass = '<%= user_password %>'; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT+2+as+n&api_key=1234', headers: {host: 'cartodb250user.cartodb.com'}, method: 'GET' @@ -204,7 +204,7 @@ it('SELECT with user-specific password', function(done){ it('GET /api/v1/sql with SQL parameter on SELECT only. no database param, just id using headers. Authenticated.', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20cartodb_id*2%20FROM%20untitle_table_4&api_key=1234', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -220,7 +220,7 @@ function(done){ // Test for https://github.com/Vizzuality/CartoDB-SQL-API/issues/85 it("paging doesn't break x-cache-channel", function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ // note: select casing intentionally mixed q: 'selECT cartodb_id*3 FROM untitle_table_4', @@ -290,7 +290,7 @@ it("paging", function(done){ req.headers['Content-Type'] = 'application/x-www-form-urlencoded'; req.data = data; } - assert.response(app, req, {}, function(res) { + assert.response(server, req, {}, function(res) { assert.equal(res.statusCode, 200, res.body); var parsed = JSON.parse(res.body); assert.equal(parsed.rows.length, nrows); @@ -311,7 +311,7 @@ it("paging starting with comment", function(done){ "SELECT * FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(v)"; var nrows = 3; var page = 2; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: sql, rows_per_page: nrows, @@ -333,7 +333,7 @@ it("paging starting with comment", function(done){ }); it('POST /api/v1/sql with SQL parameter on SELECT only. no database param, just id using headers', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql', data: querystring.stringify({q: "SELECT * FROM untitle_table_4"}), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, @@ -345,7 +345,7 @@ it('POST /api/v1/sql with SQL parameter on SELECT only. no database param, just }); it('GET /api/v1/sql with INSERT. oAuth not used, so public user - should fail', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?q=INSERT%20INTO%20untitle_table_4%20(cartodb_id)%20VALUES%20(1e4)" + "&database=cartodb_test_user_1_db", headers: {host: 'vizzuality.cartodb.com'}, @@ -363,7 +363,7 @@ it('GET /api/v1/sql with INSERT. oAuth not used, so public user - should fail', }); it('GET /api/v1/sql with DROP TABLE. oAuth not used, so public user - should fail', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?q=DROP%20TABLE%20untitle_table_4&database=cartodb_test_user_1_db", headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -380,7 +380,7 @@ it('GET /api/v1/sql with DROP TABLE. oAuth not used, so public user - should fai }); it('GET /api/v1/sql with INSERT. header based db - should fail', function (done) { - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?q=INSERT%20INTO%20untitle_table_4%20(id)%20VALUES%20(1)", headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -395,7 +395,7 @@ it('GET /api/v1/sql with INSERT. header based db - should fail', function (done) // // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/13 it('INSERT returns affected rows', function(done){ - assert.response(app, { + assert.response(server, { // view prepare_db.sh to see where to set api_key url: "/api/v1/sql?api_key=1234&" + querystring.stringify({q: "INSERT INTO private_table(name) VALUES('noret1') UNION VALUES('noret2')" @@ -420,7 +420,7 @@ it('INSERT returns affected rows', function(done){ // // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/13 it('UPDATE returns affected rows', function(done){ - assert.response(app, { + assert.response(server, { // view prepare_db.sh to see where to set api_key url: "/api/v1/sql?api_key=1234&" + querystring.stringify({q: "UPDATE private_table SET name = upper(name) WHERE name in ('noret1', 'noret2')" @@ -445,7 +445,7 @@ it('UPDATE returns affected rows', function(done){ // // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/13 it('DELETE returns affected rows', function(done){ - assert.response(app, { + assert.response(server, { // view prepare_db.sh to see where to set api_key url: "/api/v1/sql?api_key=1234&" + querystring.stringify({q: "DELETE FROM private_table WHERE name in ('NORET1', 'NORET2')" @@ -470,7 +470,7 @@ it('DELETE returns affected rows', function(done){ // // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/50 it('INSERT with RETURNING returns all results', function(done){ - assert.response(app, { + assert.response(server, { // view prepare_db.sh to see where to set api_key url: "/api/v1/sql?api_key=1234&" + querystring.stringify({q: "INSERT INTO private_table(name) VALUES('test') RETURNING upper(name), reverse(name)" @@ -494,7 +494,7 @@ it('INSERT with RETURNING returns all results', function(done){ // // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/50 it('UPDATE with RETURNING returns all results', function(done){ - assert.response(app, { + assert.response(server, { // view prepare_db.sh to see where to set api_key url: "/api/v1/sql?api_key=1234&" + querystring.stringify({q: "UPDATE private_table SET name = 'tost' WHERE name = 'test' RETURNING upper(name), reverse(name)" @@ -518,7 +518,7 @@ it('UPDATE with RETURNING returns all results', function(done){ // // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/50 it('DELETE with RETURNING returns all results', function(done){ - assert.response(app, { + assert.response(server, { // view prepare_db.sh to see where to set api_key url: "/api/v1/sql?api_key=1234&" + querystring.stringify({q: "DELETE FROM private_table WHERE name = 'tost' RETURNING name" @@ -538,7 +538,7 @@ it('DELETE with RETURNING returns all results', function(done){ }); it('GET /api/v1/sql with SQL parameter on DROP TABLE. should fail', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?q=DROP%20TABLE%20untitle_table_4", headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -557,7 +557,7 @@ it('GET /api/v1/sql with SQL parameter on DROP TABLE. should fail', function(don // // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/99 it('Field name is not confused with UPDATE operation', function(done){ - assert.response(app, { + assert.response(server, { // view prepare_db.sh to see where to set api_key url: "/api/v1/sql?api_key=1234&" + querystring.stringify({q: "SELECT min(updated_at) FROM private_table" @@ -572,7 +572,7 @@ it('Field name is not confused with UPDATE operation', function(done){ }); it('CREATE TABLE with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'CREATE TABLE test_table(a int)', api_key: 1234 @@ -595,7 +595,7 @@ it('SELECT INTO with paging ', function(done){ step( function select_into() { var next = this; - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'SELECT generate_series(1,10) InTO "' + esc_tabname + '"', rows_per_page: 1, page: 1, @@ -609,7 +609,7 @@ it('SELECT INTO with paging ', function(done){ assert.ifError(err); assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var next = this; - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'SELECT \' INTO "c"\' FROM "' + esc_tabname + '"', rows_per_page: 1, page: 1, @@ -625,7 +625,7 @@ it('SELECT INTO with paging ', function(done){ var out = JSON.parse(res.body); assert.equal(out.total_rows, 1); // windowing works var next = this; - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'DROP TABLE "' + esc_tabname + '"', api_key: 1234 @@ -648,7 +648,7 @@ it('SELECT INTO with paging ', function(done){ // Test effects of COPY // See https://github.com/Vizzuality/cartodb-management/issues/1502 it('COPY TABLE with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'COPY test_table FROM stdin;', api_key: 1234 @@ -666,7 +666,7 @@ it('COPY TABLE with GET and auth', function(done){ }); it('COPY TABLE with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: "COPY test_table to '/tmp/x';", api_key: 1234 @@ -687,7 +687,7 @@ it('COPY TABLE with GET and auth', function(done){ }); it('ALTER TABLE with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'ALTER TABLE test_table ADD b int', api_key: 1234 @@ -705,7 +705,7 @@ it('ALTER TABLE with GET and auth', function(done){ }); it('multistatement insert, alter, select, begin, commit', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'BEGIN; DELETE FROM test_table; COMMIT; BEGIN; INSERT INTO test_table(b) values (5); COMMIT; ' + 'ALTER TABLE test_table ALTER b TYPE float USING b::float/2; SELECT b FROM test_table;', @@ -723,7 +723,7 @@ it('multistatement insert, alter, select, begin, commit', function(done){ }); it('TRUNCATE TABLE with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'TRUNCATE TABLE test_table', api_key: 1234 @@ -736,7 +736,7 @@ it('TRUNCATE TABLE with GET and auth', function(done){ assert.equal(res.headers['cache-control'], expected_rw_cache_control); var pbody = JSON.parse(res.body); assert.equal(pbody.rows.length, 0); - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'SELECT count(*) FROM test_table', api_key: 1234 @@ -757,7 +757,7 @@ it('TRUNCATE TABLE with GET and auth', function(done){ }); it('REINDEX TABLE with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: ' ReINdEX TABLE test_table', api_key: 1234 @@ -775,7 +775,7 @@ it('REINDEX TABLE with GET and auth', function(done){ }); it('DROP TABLE with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'DROP TABLE test_table', api_key: 1234 @@ -793,7 +793,7 @@ it('DROP TABLE with GET and auth', function(done){ }); it('CREATE FUNCTION with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'CREATE FUNCTION create_func_test(a int) RETURNS INT AS \'SELECT 1\' LANGUAGE \'sql\'', api_key: 1234 @@ -811,7 +811,7 @@ it('CREATE FUNCTION with GET and auth', function(done){ }); it('DROP FUNCTION with GET and auth', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({ q: 'DROP FUNCTION create_func_test(a int)', api_key: 1234 @@ -829,7 +829,7 @@ it('DROP FUNCTION with GET and auth', function(done){ }); it('sends a 400 when an unsupported format is requested', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=unknown', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -843,7 +843,7 @@ it('sends a 400 when an unsupported format is requested', function(done){ }); it('GET /api/v1/sql with SQL parameter and no format, ensuring content-disposition set to json', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -859,7 +859,7 @@ it('GET /api/v1/sql with SQL parameter and no format, ensuring content-dispositi }); it('POST /api/v1/sql with SQL parameter and no format, ensuring content-disposition set to json', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql', data: querystring.stringify({q: "SELECT * FROM untitle_table_4" }), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, @@ -876,7 +876,7 @@ it('POST /api/v1/sql with SQL parameter and no format, ensuring content-disposit }); it('GET /api/v1/sql with SQL parameter and no format, but a filename', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&filename=x', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -892,7 +892,7 @@ it('GET /api/v1/sql with SQL parameter and no format, but a filename', function( }); it('field named "the_geom_webmercator" is not skipped by default', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -912,7 +912,7 @@ it('field named "the_geom_webmercator" is not skipped by default', function(done }); it('skipfields controls included fields', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&skipfields=the_geom_webmercator,cartodb_id,unexistant', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -932,7 +932,7 @@ it('skipfields controls included fields', function(done){ }); it('multiple skipfields parameter do not kill the backend', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&skipfields=unexistent,the_geom_webmercator' + '&skipfields=cartodb_id,unexistant', headers: {host: 'vizzuality.cartodb.com'}, @@ -953,7 +953,7 @@ it('multiple skipfields parameter do not kill the backend', function(done){ }); it('GET /api/v1/sql ensure cross domain set on errors', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*gadfgadfg%20FROM%20untitle_table_4', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -1022,7 +1022,7 @@ function testSystemQueries(description, queries, statusErrorCode, apiKey) { method: 'GET', url: '/api/v1/sql?' + querystring.stringify(queryStringParams) }; - assert.response(app, request, function(response) { + assert.response(server, request, function(response) { assert.equal(response.statusCode, statusErrorCode); done(); }); @@ -1031,7 +1031,7 @@ function testSystemQueries(description, queries, statusErrorCode, apiKey) { } it('GET decent error if domain is incorrect', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson', headers: {host: 'vizzualinot.cartodb.com'}, method: 'GET' @@ -1050,7 +1050,7 @@ it('GET decent error if domain is incorrect', function(done){ // this test does not make sense with the current CDB_QueryTables implementation it('GET decent error if SQL is broken', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({q: 'SELECT star FROM this and that' }), @@ -1069,7 +1069,7 @@ it('GET decent error if SQL is broken', function(done){ // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/88 it('numeric arrays are rendered as such', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?" + querystring.stringify({q: "SELECT ARRAY[8.7,4.3]::numeric[] as x" }), @@ -1092,7 +1092,7 @@ it('numeric arrays are rendered as such', function(done){ // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/97 it('field names and types are exposed', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SELECT 1::int as a, 2::float8 as b, 3::varchar as c, " + "4::char as d, now() as e, 'a'::text as f" + @@ -1125,7 +1125,7 @@ it('field names and types are exposed', function(done){ // See https://github.com/CartoDB/CartoDB-SQL-API/issues/109 it('schema response takes skipfields into account', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SELECT 1 as a, 2 as b, 3 as c ", skipfields: 'b' @@ -1145,7 +1145,7 @@ it('schema response takes skipfields into account', function(done){ // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/100 it('numeric fields are rendered as numbers in JSON', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "WITH inp AS ( SELECT 1::int2 as a, 2::int4 as b, " + "3::int8 as c, 4::float4 as d, " + @@ -1196,7 +1196,7 @@ it('timezone info in JSON output', function(done){ step( function testEuropeRomeExplicit() { var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SET timezone TO 'Europe/Rome'; SELECT '2000-01-01T00:00:00+01'::timestamptz as d" }), @@ -1216,7 +1216,7 @@ it('timezone info in JSON output', function(done){ function testEuropeRomeImplicit(err) { assert.ifError(err); var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SET timezone TO 'Europe/Rome'; SELECT '2000-01-01T00:00:00'::timestamp as d" }), @@ -1236,7 +1236,7 @@ it('timezone info in JSON output', function(done){ function testUTCExplicit(err) { assert.ifError(err); var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SET timezone TO 'UTC'; SELECT '2000-01-01T00:00:00+00'::timestamptz as d" }), @@ -1256,7 +1256,7 @@ it('timezone info in JSON output', function(done){ function testUTCImplicit(err) { assert.ifError(err); var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SET timezone TO 'UTC'; SELECT '2000-01-01T00:00:00'::timestamp as d" }), @@ -1285,7 +1285,7 @@ it('notice and warning info in JSON output', function(done){ step( function addRaiseFunction() { var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "create or replace function raise(lvl text, msg text) returns void as $$ begin if lvl = 'notice' " + "then raise notice '%', msg; elsif lvl = 'warning' then raise warning '%', msg; " + @@ -1305,7 +1305,7 @@ it('notice and warning info in JSON output', function(done){ function raiseNotice(err) { assert.ifError(err); var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SET client_min_messages TO 'notice'; select raise('notice', 'hello notice')" }), @@ -1326,7 +1326,7 @@ it('notice and warning info in JSON output', function(done){ function raiseWarning(err) { assert.ifError(err); var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SET client_min_messages TO 'notice'; select raise('warning', 'hello warning')" }), @@ -1347,7 +1347,7 @@ it('notice and warning info in JSON output', function(done){ function raiseBothWarningAndNotice(err) { assert.ifError(err); var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "SET client_min_messages TO 'notice'; select raise('warning', 'hello again warning'), " + "raise('notice', 'hello again notice');" @@ -1371,7 +1371,7 @@ it('notice and warning info in JSON output', function(done){ }, function delRaiseFunction(err) { var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "DROP function raise(text, text)", api_key: '1234' @@ -1396,7 +1396,7 @@ it('notice and warning info in JSON output', function(done){ * CORS */ it('GET /api/v1/sql with SQL parameter on SELECT only should return CORS headers ', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&database=cartodb_test_user_1_db', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -1415,7 +1415,7 @@ it('GET /api/v1/sql with SQL parameter on SELECT only should return CORS headers }); it('GET with callback param returns wrapped result set with callback as jsonp', function(done) { - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&callback=foo_jsonp', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -1427,7 +1427,7 @@ it('GET with callback param returns wrapped result set with callback as jsonp', }); it('GET with callback must return 200 status error even if it is an error', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?q=DROP%20TABLE%20untitle_table_4&callback=foo_jsonp", headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -1447,7 +1447,7 @@ it('GET with callback must return 200 status error even if it is an error', func }); it('GET with slow query exceeding statement timeout returns proper error message', function(done){ - assert.response(app, { + assert.response(server, { url: "/api/v1/sql?q=select%20pg_sleep(2.1)%20as%20sleep", headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -1474,7 +1474,7 @@ it('GET with callback must return 200 status error even if it is an error', func consoleError = what; }; assert.response( - app, + server, { url: "/api/v1/sql?" + querystring.stringify({ q: "SELECT * FROM untitle_table_4" diff --git a/test/acceptance/backend_crash.js b/test/acceptance/backend_crash.js index 59262109..6773ec3b 100644 --- a/test/acceptance/backend_crash.js +++ b/test/acceptance/backend_crash.js @@ -27,11 +27,11 @@ it('does not hang server', function(done){ var db_port_backup = global.settings.db_port; global.settings.db_host = 'localhost'; global.settings.db_port = sql_server_port; - var app = require(global.settings.app_root + '/app/app')(); + var server = require('../../app/server')(); step( function sendQuery() { var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT+1', method: 'GET', headers: {host: 'vizzuality.localhost' } @@ -50,7 +50,7 @@ it('does not hang server', function(done){ }, function sendAnotherQuery() { var next = this; - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT+2', method: 'GET', headers: {host: 'vizzuality.localhost' } diff --git a/test/acceptance/export/arraybuffer.js b/test/acceptance/export/arraybuffer.js index e3f7b66c..439a0395 100644 --- a/test/acceptance/export/arraybuffer.js +++ b/test/acceptance/export/arraybuffer.js @@ -2,17 +2,17 @@ require('../../helper'); require('../../support/assert'); -var app = require(global.settings.app_root + '/app/app')(); +var server = require('../../../app/server')(); var assert = require('assert'); var querystring = require('querystring'); // allow lots of emitters to be set to silence warning -app.setMaxListeners(0); +server.setMaxListeners(0); describe('export.arraybuffer', function() { it('GET /api/v1/sql as arraybuffer ', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: 'SELECT cartodb_id,name,1::integer,187.9 FROM untitle_table_4', format: 'arraybuffer' @@ -27,7 +27,7 @@ it('GET /api/v1/sql as arraybuffer ', function(done){ }); it('GET /api/v1/sql as arraybuffer does not support geometry types ', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: 'SELECT cartodb_id, the_geom FROM untitle_table_4', format: 'arraybuffer' diff --git a/test/acceptance/export/csv.js b/test/acceptance/export/csv.js index 180b5db1..427d80d6 100644 --- a/test/acceptance/export/csv.js +++ b/test/acceptance/export/csv.js @@ -2,17 +2,17 @@ require('../../helper'); require('../../support/assert'); -var app = require(global.settings.app_root + '/app/app')(); +var server = require('../../../app/server')(); var assert = require('assert'); var querystring = require('querystring'); // allow lots of emitters to be set to silence warning -app.setMaxListeners(0); +server.setMaxListeners(0); describe('export.csv', function() { it('CSV format', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: 'SELECT * FROM untitle_table_4 WHERE cartodb_id = 1', format: 'csv' @@ -39,7 +39,7 @@ it('CSV format', function(done){ }); it('CSV format, bigger than 81920 bytes', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql', data: querystring.stringify({ q: 'SELECT 0 as fname FROM generate_series(0,81920)', @@ -55,7 +55,7 @@ it('CSV format, bigger than 81920 bytes', function(done){ it('CSV format from POST', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql', data: querystring.stringify({q: "SELECT * FROM untitle_table_4 LIMIT 1", format: 'csv'}), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, @@ -72,7 +72,7 @@ it('CSV format from POST', function(done){ }); it('CSV format, custom filename', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=csv&filename=mycsv.csv', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -98,7 +98,7 @@ it('CSV format, custom filename', function(done){ }); it('skipfields controls fields included in CSV output', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=csv' + '&skipfields=unexistant,cartodb_id', headers: {host: 'vizzuality.cartodb.com'}, @@ -120,7 +120,7 @@ it('skipfields controls fields included in CSV output', function(done){ }); it('GET /api/v1/sql as csv', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20cartodb_id,ST_AsEWKT(the_geom)%20as%20geom%20FROM%20untitle_table_4%20LIMIT%201' + '&format=csv', headers: {host: 'vizzuality.cartodb.com'}, @@ -135,7 +135,7 @@ it('GET /api/v1/sql as csv', function(done){ // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/60 it('GET /api/v1/sql as csv with no rows', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20true%20WHERE%20false&format=csv', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -150,7 +150,7 @@ it('GET /api/v1/sql as csv with no rows', function(done){ }); it('GET /api/v1/sql as csv, properly escaped', function(done){ - assert.response(app, { + assert.response(server, { url: '/api/v1/sql?q=SELECT%20cartodb_id,%20address%20FROM%20untitle_table_4%20LIMIT%201&format=csv', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' @@ -174,7 +174,7 @@ it('GET /api/v1/sql as csv, concurrently', function(done){ } } for (var i=0; i Date: Wed, 14 Sep 2016 21:02:56 +0200 Subject: [PATCH 09/76] Remove settings' app_root --- app.js | 17 +++++++---------- config/settings.js | 4 ---- test/helper.js | 6 +----- 3 files changed, 8 insertions(+), 19 deletions(-) delete mode 100644 config/settings.js diff --git a/app.js b/app.js index 9f981e12..fa8895a1 100755 --- a/app.js +++ b/app.js @@ -9,7 +9,6 @@ * environments: [development, test, production] * */ -var _ = require('underscore'); var fs = require('fs'); var path = require('path'); @@ -31,10 +30,8 @@ if (availableEnvironments.indexOf(ENV) === -1) { } // set Node.js app settings and boot -global.settings = require(__dirname + '/config/settings'); -var env = require(__dirname + '/config/environments/' + ENV); -env.api_hostname = require('os').hostname().split('.')[0]; -_.extend(global.settings, env); +global.settings = require('./config/environments/' + ENV); +global.settings.api_hostname = require('os').hostname().split('.')[0]; global.log4js = require('log4js'); var log4jsConfig = { @@ -42,8 +39,8 @@ var log4jsConfig = { replaceConsole: true }; -if ( env.log_filename ) { - var logFilename = path.resolve(env.log_filename); +if ( global.settings.log_filename ) { + var logFilename = path.resolve(global.settings.log_filename); var logDirectory = path.dirname(logFilename); if (!fs.existsSync(logDirectory)) { console.error("Log filename directory does not exist: " + logDirectory); @@ -69,11 +66,11 @@ if ( ! global.settings.base_url ) { var version = require("./package").version; -var server = require('app/server')(); +var server = require('./app/server')(); server.listen(global.settings.node_port, global.settings.node_host, function() { console.log( - "CartoDB SQL API %s listening on %s:%s with base_url %s (%s)", - version, global.settings.node_host, global.settings.node_port, global.settings.base_url, ENV + "CartoDB SQL API %s listening on %s:%s with base_url %s PID=%d (%s)", + version, global.settings.node_host, global.settings.node_port, global.settings.base_url, process.pid, ENV ); }); diff --git a/config/settings.js b/config/settings.js deleted file mode 100644 index 4738663d..00000000 --- a/config/settings.js +++ /dev/null @@ -1,4 +0,0 @@ -var path = require('path'); - -module.exports.app_root = path.join(__dirname, '..'); - diff --git a/test/helper.js b/test/helper.js index 7c3b132f..e22cafec 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,5 +1 @@ -var _ = require('underscore'); - -global.settings = require(__dirname + '/../config/settings'); -var env = require(__dirname + '/../config/environments/test'); -_.extend(global.settings, env); +global.settings = require('../config/environments/test'); From 4ffadb725d163f65a0aa81f6760d2799ace77aba Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 14 Sep 2016 21:18:54 +0200 Subject: [PATCH 10/76] Use before_install hook for travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fac7e836..0582a506 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -before_script: +before_install: - lsb_release -a - sudo mv /etc/apt/sources.list.d/pgdg.list* /tmp - sudo apt-get -qq purge postgis* postgresql* From 0d54604428a53677626a6a264bd56a1a224386ac Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 14 Sep 2016 21:24:22 +0200 Subject: [PATCH 11/76] Remove setMaxListeners from tests --- test/acceptance/export/arraybuffer.js | 3 --- test/acceptance/export/csv.js | 3 --- test/acceptance/export/geojson.js | 4 ---- test/acceptance/export/kml.js | 3 --- test/acceptance/export/shapefile.js | 3 --- test/acceptance/export/svg.js | 3 --- test/acceptance/export/topojson.js | 4 ---- test/acceptance/surrogate-key.js | 3 --- test/acceptance/x-cache-channel.js | 3 --- 9 files changed, 29 deletions(-) diff --git a/test/acceptance/export/arraybuffer.js b/test/acceptance/export/arraybuffer.js index 439a0395..93629604 100644 --- a/test/acceptance/export/arraybuffer.js +++ b/test/acceptance/export/arraybuffer.js @@ -6,9 +6,6 @@ var server = require('../../../app/server')(); var assert = require('assert'); var querystring = require('querystring'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - describe('export.arraybuffer', function() { it('GET /api/v1/sql as arraybuffer ', function(done){ diff --git a/test/acceptance/export/csv.js b/test/acceptance/export/csv.js index 427d80d6..e3c246f7 100644 --- a/test/acceptance/export/csv.js +++ b/test/acceptance/export/csv.js @@ -6,9 +6,6 @@ var server = require('../../../app/server')(); var assert = require('assert'); var querystring = require('querystring'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - describe('export.csv', function() { it('CSV format', function(done){ diff --git a/test/acceptance/export/geojson.js b/test/acceptance/export/geojson.js index 72f00364..656c29f6 100644 --- a/test/acceptance/export/geojson.js +++ b/test/acceptance/export/geojson.js @@ -4,10 +4,6 @@ var server = require('../../../app/server')(); var assert = require('../../support/assert'); var querystring = require('querystring'); -// allow lots of emitters to be set to silence warning -// TODO: check if still needed ... -server.setMaxListeners(0); - // use dec_sep for internationalization var checkDecimals = function(x, dec_sep){ var tmp='' + x; diff --git a/test/acceptance/export/kml.js b/test/acceptance/export/kml.js index d2b3035c..0f8a69c1 100644 --- a/test/acceptance/export/kml.js +++ b/test/acceptance/export/kml.js @@ -7,9 +7,6 @@ var libxmljs = require('libxmljs'); var http = require('http'); var server_utils = require('../../support/server_utils'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - describe('export.kml', function() { // Check if an attribute is in the KML output diff --git a/test/acceptance/export/shapefile.js b/test/acceptance/export/shapefile.js index a6364495..76b4a864 100644 --- a/test/acceptance/export/shapefile.js +++ b/test/acceptance/export/shapefile.js @@ -8,9 +8,6 @@ var _ = require('underscore'); var zipfile = require('zipfile'); var fs = require('fs'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - describe('export.shapefile', function() { // SHP tests diff --git a/test/acceptance/export/svg.js b/test/acceptance/export/svg.js index 86c02974..10b9ceb7 100644 --- a/test/acceptance/export/svg.js +++ b/test/acceptance/export/svg.js @@ -4,9 +4,6 @@ var server = require('../../../app/server')(); var assert = require('../../support/assert'); var querystring = require('querystring'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - describe('export.svg', function() { it('GET /api/v1/sql with SVG format', function(done){ diff --git a/test/acceptance/export/topojson.js b/test/acceptance/export/topojson.js index 0cddbdcc..48516835 100644 --- a/test/acceptance/export/topojson.js +++ b/test/acceptance/export/topojson.js @@ -5,10 +5,6 @@ var assert = require('../../support/assert'); var querystring = require('querystring'); var _ = require('underscore'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - - describe('export.topojson', function() { // TOPOJSON tests diff --git a/test/acceptance/surrogate-key.js b/test/acceptance/surrogate-key.js index ff0b7653..8254bbed 100644 --- a/test/acceptance/surrogate-key.js +++ b/test/acceptance/surrogate-key.js @@ -6,9 +6,6 @@ var querystring = require('querystring'); var QueryTables = require('cartodb-query-tables'); var _ = require('underscore'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - describe('Surrogate-Key header', function() { function createGetRequest(sqlQuery) { diff --git a/test/acceptance/x-cache-channel.js b/test/acceptance/x-cache-channel.js index 3321066b..7b5708a3 100644 --- a/test/acceptance/x-cache-channel.js +++ b/test/acceptance/x-cache-channel.js @@ -5,9 +5,6 @@ var assert = require('../support/assert'); var querystring = require('querystring'); var _ = require('underscore'); -// allow lots of emitters to be set to silence warning -server.setMaxListeners(0); - describe('X-Cache-Channel header', function() { function createGetRequest(sqlQuery) { From 510f1cd7d7624ec64610bf68cb59ca0ae7e407b5 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 14 Sep 2016 23:10:14 +0200 Subject: [PATCH 12/76] Rename var --- app.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index fa8895a1..df097b7f 100755 --- a/app.js +++ b/app.js @@ -15,22 +15,22 @@ var path = require('path'); var ENV = process.env.NODE_ENV || 'development'; if (process.argv[2]) { - ENV = process.argv[2]; + ENVIRONMENT = process.argv[2]; } -process.env.NODE_ENV = ENV; +process.env.NODE_ENV = ENVIRONMENT; var availableEnvironments = ['development', 'production', 'test', 'staging']; // sanity check arguments -if (availableEnvironments.indexOf(ENV) === -1) { +if (availableEnvironments.indexOf(ENVIRONMENT) === -1) { console.error("\nnode app.js [environment]"); console.error("environments: " + availableEnvironments.join(', ')); process.exit(1); } // set Node.js app settings and boot -global.settings = require('./config/environments/' + ENV); +global.settings = require('./config/environments/' + ENVIRONMENT); global.settings.api_hostname = require('os').hostname().split('.')[0]; global.log4js = require('log4js'); @@ -70,7 +70,7 @@ var server = require('./app/server')(); server.listen(global.settings.node_port, global.settings.node_host, function() { console.log( "CartoDB SQL API %s listening on %s:%s with base_url %s PID=%d (%s)", - version, global.settings.node_host, global.settings.node_port, global.settings.base_url, process.pid, ENV + version, global.settings.node_host, global.settings.node_port, global.settings.base_url, process.pid, ENVIRONMENT ); }); From 27b73cb1630fc210081ccd10d83abd231928c02e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 15 Sep 2016 00:36:24 +0200 Subject: [PATCH 13/76] Allow to use `--config /path/to/config.js` to specify configuration file --- NEWS.md | 4 + app.js | 37 +++-- npm-shrinkwrap.json | 330 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- 4 files changed, 362 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index f5965a11..3690d2da 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,10 @@ 1.35.0 - 2016-mm-dd ------------------- +New features: + * Allow to use `--config /path/to/config.js` to specify configuration file. + - Environment will be loaded from config file if `environment` key is present, otherwise it keeps current behaviour. + Bug fixes: * Allow to use absolute paths for log files. diff --git a/app.js b/app.js index df097b7f..33b47e4d 100755 --- a/app.js +++ b/app.js @@ -12,25 +12,39 @@ var fs = require('fs'); var path = require('path'); -var ENV = process.env.NODE_ENV || 'development'; +var argv = require('yargs') + .usage('Usage: $0 [options]') + .help('h') + .example( + '$0 production -c /etc/windshaft/config.js', + 'start server in production environment with /etc/windshaft/config.js as configuration file' + ) + .alias('h', 'help') + .alias('c', 'config') + .nargs('c', 1) + .describe('c', 'Load configuration from path') + .argv; -if (process.argv[2]) { - ENVIRONMENT = process.argv[2]; +var environmentArg = argv._[0] || process.env.NODE_ENV || 'development'; +var configurationFile = path.resolve(argv.config || './config/environments/' + environmentArg + '.js'); +if (!fs.existsSync(configurationFile)) { + console.error('Configuration file "%s" does not exist', configurationFile); + process.exit(1); } +global.settings = require(configurationFile); +var ENVIRONMENT = argv._[0] || process.env.NODE_ENV || global.settings.environment; process.env.NODE_ENV = ENVIRONMENT; var availableEnvironments = ['development', 'production', 'test', 'staging']; // sanity check arguments if (availableEnvironments.indexOf(ENVIRONMENT) === -1) { - console.error("\nnode app.js [environment]"); - console.error("environments: " + availableEnvironments.join(', ')); + console.error("node app.js [environment]"); + console.error("Available environments: " + availableEnvironments.join(', ')); process.exit(1); } -// set Node.js app settings and boot -global.settings = require('./config/environments/' + ENVIRONMENT); global.settings.api_hostname = require('os').hostname().split('.')[0]; global.log4js = require('log4js'); @@ -68,10 +82,11 @@ var version = require("./package").version; var server = require('./app/server')(); server.listen(global.settings.node_port, global.settings.node_host, function() { - console.log( - "CartoDB SQL API %s listening on %s:%s with base_url %s PID=%d (%s)", - version, global.settings.node_host, global.settings.node_port, global.settings.base_url, process.pid, ENVIRONMENT - ); + console.info('Using configuration file "%s"', configurationFile); + console.log( + "CartoDB SQL API %s listening on %s:%s PID=%d (%s)", + version, global.settings.node_host, global.settings.node_port, process.pid, ENVIRONMENT + ); }); process.on('uncaughtException', function(err) { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2e2cd17b..64881186 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -237,6 +237,336 @@ "version": "1.6.0", "from": "underscore@>=1.6.0 <1.7.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" + }, + "yargs": { + "version": "5.0.0", + "from": "yargs@>=5.0.0 <6.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-5.0.0.tgz", + "dependencies": { + "cliui": { + "version": "3.2.0", + "from": "cliui@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "dependencies": { + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + }, + "wrap-ansi": { + "version": "2.0.0", + "from": "wrap-ansi@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.0.0.tgz" + } + } + }, + "decamelize": { + "version": "1.2.0", + "from": "decamelize@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + }, + "get-caller-file": { + "version": "1.0.2", + "from": "get-caller-file@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz" + }, + "lodash.assign": { + "version": "4.2.0", + "from": "lodash.assign@>=4.2.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" + }, + "os-locale": { + "version": "1.4.0", + "from": "os-locale@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "dependencies": { + "lcid": { + "version": "1.0.0", + "from": "lcid@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "dependencies": { + "invert-kv": { + "version": "1.0.0", + "from": "invert-kv@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz" + } + } + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "from": "read-pkg-up@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "dependencies": { + "find-up": { + "version": "1.1.2", + "from": "find-up@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "dependencies": { + "path-exists": { + "version": "2.1.0", + "from": "path-exists@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz" + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "dependencies": { + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + } + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "from": "read-pkg@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "dependencies": { + "load-json-file": { + "version": "1.1.0", + "from": "load-json-file@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "dependencies": { + "graceful-fs": { + "version": "4.1.6", + "from": "graceful-fs@>=4.1.2 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz" + }, + "parse-json": { + "version": "2.2.0", + "from": "parse-json@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "dependencies": { + "error-ex": { + "version": "1.3.0", + "from": "error-ex@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz", + "dependencies": { + "is-arrayish": { + "version": "0.2.1", + "from": "is-arrayish@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + } + } + } + } + }, + "pify": { + "version": "2.3.0", + "from": "pify@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "dependencies": { + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + } + } + }, + "strip-bom": { + "version": "2.0.0", + "from": "strip-bom@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "dependencies": { + "is-utf8": { + "version": "0.2.1", + "from": "is-utf8@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + } + } + } + } + }, + "normalize-package-data": { + "version": "2.3.5", + "from": "normalize-package-data@>=2.3.2 <3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", + "dependencies": { + "hosted-git-info": { + "version": "2.1.5", + "from": "hosted-git-info@>=2.1.4 <3.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz" + }, + "is-builtin-module": { + "version": "1.0.0", + "from": "is-builtin-module@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "dependencies": { + "builtin-modules": { + "version": "1.1.1", + "from": "builtin-modules@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" + } + } + }, + "semver": { + "version": "5.3.0", + "from": "semver@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0||>=4.0.0 <5.0.0||>=5.0.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "from": "validate-npm-package-license@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "dependencies": { + "spdx-correct": { + "version": "1.0.2", + "from": "spdx-correct@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "dependencies": { + "spdx-license-ids": { + "version": "1.2.2", + "from": "spdx-license-ids@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz" + } + } + }, + "spdx-expression-parse": { + "version": "1.0.3", + "from": "spdx-expression-parse@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.3.tgz" + } + } + } + } + }, + "path-type": { + "version": "1.1.0", + "from": "path-type@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "dependencies": { + "graceful-fs": { + "version": "4.1.6", + "from": "graceful-fs@>=4.1.2 <5.0.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz" + }, + "pify": { + "version": "2.3.0", + "from": "pify@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + }, + "pinkie-promise": { + "version": "2.0.1", + "from": "pinkie-promise@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "dependencies": { + "pinkie": { + "version": "2.0.4", + "from": "pinkie@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + } + } + } + } + } + } + } + } + }, + "require-directory": { + "version": "2.1.1", + "from": "require-directory@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + }, + "require-main-filename": { + "version": "1.0.1", + "from": "require-main-filename@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" + }, + "set-blocking": { + "version": "2.0.0", + "from": "set-blocking@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + }, + "string-width": { + "version": "1.0.2", + "from": "string-width@>=1.0.2 <2.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "dependencies": { + "code-point-at": { + "version": "1.0.0", + "from": "code-point-at@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz", + "dependencies": { + "number-is-nan": { + "version": "1.0.0", + "from": "number-is-nan@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz" + } + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "dependencies": { + "number-is-nan": { + "version": "1.0.0", + "from": "number-is-nan@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "from": "strip-ansi@>=3.0.1 <4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "from": "ansi-regex@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + } + } + } + } + }, + "which-module": { + "version": "1.0.0", + "from": "which-module@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz" + }, + "window-size": { + "version": "0.2.0", + "from": "window-size@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz" + }, + "y18n": { + "version": "3.2.1", + "from": "y18n@>=3.2.1 <4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz" + }, + "yargs-parser": { + "version": "3.2.0", + "from": "yargs-parser@>=3.2.0 <4.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-3.2.0.tgz", + "dependencies": { + "camelcase": { + "version": "3.0.0", + "from": "camelcase@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz" + } + } + } + } } } } diff --git a/package.json b/package.json index fccca5cc..6f750c81 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "step": "~0.0.5", "step-profiler": "~0.3.0", "topojson": "0.0.8", - "underscore": "~1.6.0" + "underscore": "~1.6.0", + "yargs": "~5.0.0" }, "devDependencies": { "istanbul": "~0.4.2", From 4dfdb2eaea2a16b7775ef8723fe3ac08696d3b7f Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 15 Sep 2016 00:40:25 +0200 Subject: [PATCH 14/76] Fix example --- app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index 33b47e4d..10261bfb 100755 --- a/app.js +++ b/app.js @@ -16,8 +16,8 @@ var argv = require('yargs') .usage('Usage: $0 [options]') .help('h') .example( - '$0 production -c /etc/windshaft/config.js', - 'start server in production environment with /etc/windshaft/config.js as configuration file' + '$0 production -c /etc/sql-api/config.js', + 'start server in production environment with /etc/sql-api/config.js as config file' ) .alias('h', 'help') .alias('c', 'config') From 149d8e6e12ff0f92ac830c243e6a43f06ea73e1b Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 15 Sep 2016 11:55:33 +0200 Subject: [PATCH 15/76] Release 1.35.0 --- NEWS.md | 2 +- npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3690d2da..62213696 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -1.35.0 - 2016-mm-dd +1.35.0 - 2016-09-15 ------------------- New features: diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 64881186..7bf1367d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.34.3", + "version": "1.35.0", "dependencies": { "cartodb-psql": { "version": "0.6.1", diff --git a/package.json b/package.json index 6f750c81..d63e604b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.34.3", + "version": "1.35.0", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From bdc160cde3b8d976a75b8c3f2b1552bab02a8aae Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 15 Sep 2016 11:57:07 +0200 Subject: [PATCH 16/76] Stubs next version --- NEWS.md | 4 ++++ npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 62213696..f98eb497 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +1.35.1 - 2016-mm-dd +------------------- + + 1.35.0 - 2016-09-15 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 7bf1367d..6b0dbadc 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.35.0", + "version": "1.35.1", "dependencies": { "cartodb-psql": { "version": "0.6.1", diff --git a/package.json b/package.json index d63e604b..7650cbe0 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.35.0", + "version": "1.35.1", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From 8d74b9dcda981238a36cb86f5b89b521fcefa520 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 16 Sep 2016 15:43:06 +0200 Subject: [PATCH 17/76] Remove best practice about updating a job as it's no longer possible --- doc/batch_queries.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/batch_queries.md b/doc/batch_queries.md index 46c6bdf5..c34de75d 100644 --- a/doc/batch_queries.md +++ b/doc/batch_queries.md @@ -482,12 +482,11 @@ In some scenarios, you may need to fetch the output of a job. If that is the cas For best practices, follow these recommended usage notes when using Batch Queries: -- Batch Queries are recommended for INSERT, UPDATE, and CREATE queries that manipulate and create new data, such as creating expensive indexes, applying updates over large tables, and creating tables from complex queries. Batch queries have no effect for SELECT queries that retrieve data but do not store the results in a table. For example, running a batch query using `SELECT * from my_dataset` will not produce any results +- Batch Queries are recommended for INSERT, UPDATE, and CREATE queries that manipulate and create new data, such as creating expensive indexes, applying updates over large tables, and creating tables from complex queries. Batch queries have no effect for SELECT queries that retrieve data but do not store the results in a table. For example, running a batch query using `SELECT * from my_dataset` will not produce any results. -- Batch Queries are not intended for large query payloads (e.g: inserting thousands of rows), use the [Import API](https://carto.com/docs/carto-engine/import-api/) for this type of data management +- Batch Queries are not intended for large query payloads (e.g: inserting thousands of rows), use the [Import API](https://carto.com/docs/carto-engine/import-api/) for this type of data management. - There is a limit of 8kb per job. The following error message appears if your job exceeds this size: `Your payload is too large. Max size allowed is 8192 (8kb)` -- Only the `query` element of the job scheme can be modified. All other elements of the job schema are defined by the Batch Query and are read-only From c9846a2437ec091c46ac874d3bba5ada9ca2a63e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 14:37:40 +0200 Subject: [PATCH 18/76] Change callback signature in assert.response --- test/acceptance/app.auth.test.js | 2 +- test/acceptance/app.test.js | 138 +++++++++--------- test/acceptance/backend_crash.js | 10 +- test/acceptance/export/arraybuffer.js | 4 +- test/acceptance/export/csv.js | 20 +-- test/acceptance/export/geojson.js | 22 +-- test/acceptance/export/geopackage.js | 4 +- test/acceptance/export/kml.js | 26 ++-- test/acceptance/export/shapefile.js | 26 ++-- test/acceptance/export/spatialite.js | 6 +- test/acceptance/export/svg.js | 18 +-- test/acceptance/export/topojson.js | 10 +- test/acceptance/frontend_abort.js | 5 +- test/acceptance/health_check.js | 4 +- test/acceptance/job.callback-template.test.js | 6 +- test/acceptance/job.fallback.test.js | 96 ++++++------ test/acceptance/job.query.limit.test.js | 8 +- test/acceptance/job.test.js | 22 +-- test/acceptance/job.timing.test.js | 4 +- test/acceptance/job.use-case-1.test.js | 6 +- test/acceptance/job.use-case-10.test.js | 6 +- test/acceptance/job.use-case-2.test.js | 10 +- test/acceptance/job.use-case-3.test.js | 10 +- test/acceptance/job.use-case-4.test.js | 8 +- test/acceptance/job.use-case-5.test.js | 6 +- test/acceptance/job.use-case-6.test.js | 4 +- test/acceptance/job.use-case-7.test.js | 6 +- test/acceptance/job.use-case-8.test.js | 10 +- test/acceptance/job.use-case-9.test.js | 8 +- test/acceptance/last-modified-header.js | 6 +- test/acceptance/logging.js | 4 +- test/acceptance/query-tables-api-cache.js | 8 +- test/acceptance/regressions.js | 6 +- test/acceptance/stream-responses.js | 4 +- test/acceptance/surrogate-key.js | 8 +- test/acceptance/timeout.js | 5 +- test/acceptance/x-cache-channel.js | 8 +- test/support/assert.js | 6 +- 38 files changed, 274 insertions(+), 286 deletions(-) diff --git a/test/acceptance/app.auth.test.js b/test/acceptance/app.auth.test.js index dd648cfd..1f990275 100644 --- a/test/acceptance/app.auth.test.js +++ b/test/acceptance/app.auth.test.js @@ -49,7 +49,7 @@ describe('app.auth', function() { method: 'GET' }, {}, - function(res) { + function(err, res) { assert.equal(res.statusCode, scenario.statusCode, res.statusCode + ': ' + res.body); done(); } diff --git a/test/acceptance/app.test.js b/test/acceptance/app.test.js index b7d3aa7c..28bd52d4 100644 --- a/test/acceptance/app.test.js +++ b/test/acceptance/app.test.js @@ -31,7 +31,7 @@ it('GET /api/v1/version', function(done){ assert.response(server, { url: '/api/v1/version', method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200); var parsed = JSON.parse(res.body); var sqlapi_version = require(__dirname + '/../../package.json').version; @@ -47,7 +47,7 @@ it('GET /api/v1/sql', function(done){ method: 'GET' },{ status: 400 - }, function(res) { + }, function(err, res) { assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); assert.deepEqual(JSON.parse(res.body), {"error":["You must indicate a sql query"]}); @@ -62,7 +62,7 @@ it('GET /api/whatever/sql', function(done){ headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' },{ - }, function(res) { + }, function(err, res) { assert.equal(res.statusCode, 200, res.body); done(); }); @@ -75,7 +75,7 @@ it('GET /api/whatever/sql', function(done){ headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' },{ - }, function(res) { + }, function(err, res) { assert.equal(res.statusCode, 200, res.body); assert.equal( res.headers['access-control-allow-headers'], 'X-Requested-With, X-Prototype-Version, X-CSRF-Token' @@ -91,7 +91,7 @@ it('OPTIONS /api/x/sql', function(done){ url: '/api/x/sql?q=syntax%20error', headers: {host: 'vizzuality.cartodb.com'}, method: 'OPTIONS' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.body, ''); assert.equal( @@ -109,7 +109,7 @@ it('GET /api/v1/sql with SQL parameter on SELECT only. No oAuth included ', func url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&database=cartodb_test_user_1_db', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); // Check cache headers assert.equal(res.headers['x-cache-channel'], 'cartodb_test_user_1_db:public.untitle_table_4'); @@ -123,7 +123,7 @@ it('cache_policy=persist', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&database=cartodb_test_user_1_db&cache_policy=persist', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); // Check cache headers assert.ok(res.headers.hasOwnProperty('x-cache-channel')); @@ -139,7 +139,7 @@ it('GET /api/v1/sql with SQL parameter on SELECT only. no database param, just i url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); done(); }); @@ -149,7 +149,7 @@ it('GET /user/vizzuality/api/v1/sql with SQL parameter on SELECT only', function assert.response(server, { url: '/user/vizzuality/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); done(); }); @@ -164,7 +164,7 @@ it('SELECT from user-specific database', function(done){ url: '/api/v1/sql?q=SELECT+2+as+n', headers: {host: 'cartodb250user.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { global.settings.db_host = backupDBHost; var err = null; try { @@ -187,7 +187,7 @@ it('SELECT with user-specific password', function(done){ url: '/api/v1/sql?q=SELECT+2+as+n&api_key=1234', headers: {host: 'cartodb250user.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { global.settings.db_user_pass = backupDBUserPass; var err = null; try { @@ -208,7 +208,7 @@ function(done){ url: '/api/v1/sql?q=SELECT%20cartodb_id*2%20FROM%20untitle_table_4&api_key=1234', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); // Check cache headers assert.equal(res.headers['x-cache-channel'], 'cartodb_test_user_1_db:public.untitle_table_4'); @@ -230,7 +230,7 @@ function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers['x-cache-channel'], 'cartodb_test_user_1_db:public.untitle_table_4'); var parsed = JSON.parse(res.body); @@ -290,7 +290,7 @@ it("paging", function(done){ req.headers['Content-Type'] = 'application/x-www-form-urlencoded'; req.data = data; } - assert.response(server, req, {}, function(res) { + assert.response(server, req, {}, function(err, res) { assert.equal(res.statusCode, 200, res.body); var parsed = JSON.parse(res.body); assert.equal(parsed.rows.length, nrows); @@ -319,7 +319,7 @@ it("paging starting with comment", function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - }, {}, function(res) { + }, {}, function(err, res) { assert.equal(res.statusCode, 200, res.body); var parsed = JSON.parse(res.body); assert.equal(parsed.rows.length, 3); @@ -338,7 +338,7 @@ it('POST /api/v1/sql with SQL parameter on SELECT only. no database param, just data: querystring.stringify({q: "SELECT * FROM untitle_table_4"}), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); done(); }); @@ -351,7 +351,7 @@ it('GET /api/v1/sql with INSERT. oAuth not used, so public user - should fail', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' },{ - }, function(res) { + }, function(err, res) { assert.equal(res.statusCode, 401, res.statusCode + ': ' + res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -368,7 +368,7 @@ it('GET /api/v1/sql with DROP TABLE. oAuth not used, so public user - should fai headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' },{ - }, function(res) { + }, function(err, res) { assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -386,7 +386,7 @@ it('GET /api/v1/sql with INSERT. header based db - should fail', function (done) method: 'GET' }, { status: 400 - }, function (res, err) { + }, function (err, res) { done(err); }); }); @@ -402,7 +402,7 @@ it('INSERT returns affected rows', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var out = JSON.parse(res.body); assert.ok(out.hasOwnProperty('time')); @@ -427,7 +427,7 @@ it('UPDATE returns affected rows', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var out = JSON.parse(res.body); assert.ok(out.hasOwnProperty('time')); @@ -452,7 +452,7 @@ it('DELETE returns affected rows', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var out = JSON.parse(res.body); assert.ok(out.hasOwnProperty('time')); @@ -477,7 +477,7 @@ it('INSERT with RETURNING returns all results', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var out = JSON.parse(res.body); assert.ok(out.hasOwnProperty('time')); @@ -501,7 +501,7 @@ it('UPDATE with RETURNING returns all results', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var out = JSON.parse(res.body); assert.ok(out.hasOwnProperty('time')); @@ -525,7 +525,7 @@ it('DELETE with RETURNING returns all results', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var out = JSON.parse(res.body); assert.ok(out.hasOwnProperty('time')); @@ -542,7 +542,7 @@ it('GET /api/v1/sql with SQL parameter on DROP TABLE. should fail', function(don url: "/api/v1/sql?q=DROP%20TABLE%20untitle_table_4", headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -564,7 +564,7 @@ it('Field name is not confused with UPDATE operation', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); assert.equal(res.headers['x-cache-channel'], 'cartodb_test_user_1_db:public.private_table'); done(); @@ -579,7 +579,7 @@ it('CREATE TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 @@ -603,7 +603,7 @@ it('SELECT INTO with paging ', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { next(null, res); }); + },{}, function(err, res) { next(null, res); }); }, function check_res_test_fake_into_1(err, res) { assert.ifError(err); @@ -617,7 +617,7 @@ it('SELECT INTO with paging ', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { next(null, res); }); + },{}, function(err, res) { next(null, res); }); }, function check_res_drop_table(err, res) { assert.ifError(err); @@ -632,7 +632,7 @@ it('SELECT INTO with paging ', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { next(null, res); }); + },{}, function(err, res) { next(null, res); }); }, function check_drop(err, res) { assert.ifError(err); @@ -655,7 +655,7 @@ it('COPY TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { // We expect a problem, actually assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); @@ -673,7 +673,7 @@ it('COPY TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { // We expect a problem, actually assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); @@ -694,7 +694,7 @@ it('ALTER TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 @@ -713,7 +713,7 @@ it('multistatement insert, alter, select, begin, commit', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var parsedBody = JSON.parse(res.body); assert.equal(parsedBody.total_rows, 1); @@ -730,7 +730,7 @@ it('TRUNCATE TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); assert.ok(!res.hasOwnProperty('x-cache-channel')); assert.equal(res.headers['cache-control'], expected_rw_cache_control); @@ -743,7 +743,7 @@ it('TRUNCATE TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // table should not get a cache channel as it won't get invalidated assert.ok(!res.headers.hasOwnProperty('x-cache-channel')); @@ -764,7 +764,7 @@ it('REINDEX TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); assert.ok(!res.hasOwnProperty('x-cache-channel')); assert.equal(res.headers['cache-control'], expected_rw_cache_control); @@ -782,7 +782,7 @@ it('DROP TABLE with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 @@ -800,7 +800,7 @@ it('CREATE FUNCTION with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 @@ -818,7 +818,7 @@ it('DROP FUNCTION with GET and auth', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); // Check cache headers // See https://github.com/Vizzuality/CartoDB-SQL-API/issues/43 @@ -833,7 +833,7 @@ it('sends a 400 when an unsupported format is requested', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=unknown', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 400, res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -847,7 +847,7 @@ it('GET /api/v1/sql with SQL parameter and no format, ensuring content-dispositi url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var ct = res.header('Content-Type'); assert.ok(/json/.test(ct), 'Default format is not JSON: ' + ct); @@ -864,7 +864,7 @@ it('POST /api/v1/sql with SQL parameter and no format, ensuring content-disposit data: querystring.stringify({q: "SELECT * FROM untitle_table_4" }), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var ct = res.header('Content-Type'); assert.ok(/json/.test(ct), 'Default format is not JSON: ' + ct); @@ -880,7 +880,7 @@ it('GET /api/v1/sql with SQL parameter and no format, but a filename', function( url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&filename=x', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var ct = res.header('Content-Type'); assert.ok(/json/.test(ct), 'Default format is not JSON: ' + ct); @@ -896,7 +896,7 @@ it('field named "the_geom_webmercator" is not skipped by default', function(done url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var row0 = JSON.parse(res.body).rows[0]; var checkfields = {'name':1, 'cartodb_id':1, 'the_geom':1, 'the_geom_webmercator':1}; @@ -916,7 +916,7 @@ it('skipfields controls included fields', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&skipfields=the_geom_webmercator,cartodb_id,unexistant', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var row0 = JSON.parse(res.body).rows[0]; var checkfields = {'name':1, 'cartodb_id':0, 'the_geom':1, 'the_geom_webmercator':0}; @@ -937,7 +937,7 @@ it('multiple skipfields parameter do not kill the backend', function(done){ '&skipfields=cartodb_id,unexistant', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var row0 = JSON.parse(res.body).rows[0]; var checkfields = {'name':1, 'cartodb_id':0, 'the_geom':1, 'the_geom_webmercator':0}; @@ -959,7 +959,7 @@ it('GET /api/v1/sql ensure cross domain set on errors', function(done){ method: 'GET' },{ status: 400 - }, function(res){ + }, function(err, res){ var cd = res.header('Access-Control-Allow-Origin'); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -1022,7 +1022,7 @@ function testSystemQueries(description, queries, statusErrorCode, apiKey) { method: 'GET', url: '/api/v1/sql?' + querystring.stringify(queryStringParams) }; - assert.response(server, request, function(response) { + assert.response(server, request, function(err, response) { assert.equal(response.statusCode, statusErrorCode); done(); }); @@ -1035,7 +1035,7 @@ it('GET decent error if domain is incorrect', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson', headers: {host: 'vizzualinot.cartodb.com'}, method: 'GET' - }, {}, function(res){ + }, {}, function(err, res){ assert.equal(res.statusCode, 404, res.statusCode + ( res.statusCode !== 200 ? ( ': ' + res.body ) : '')); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -1056,7 +1056,7 @@ it('GET decent error if SQL is broken', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res){ + },{}, function(err, res){ assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -1075,7 +1075,7 @@ it('numeric arrays are rendered as such', function(done){ }), headers: {host: 'vizzuality.localhost.lan:8080' }, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var out = JSON.parse(res.body); assert.ok(out.hasOwnProperty('time')); @@ -1105,7 +1105,7 @@ it('field names and types are exposed', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); assert.equal(_.keys(parsedBody.fields).length, 10); @@ -1132,7 +1132,7 @@ it('schema response takes skipfields into account', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); assert.equal(_.keys(parsedBody.fields).length, 2); @@ -1161,7 +1161,7 @@ it('numeric fields are rendered as numbers in JSON', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); var row = parsedBody.rows[0]; @@ -1202,7 +1202,7 @@ it('timezone info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { try { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); @@ -1222,7 +1222,7 @@ it('timezone info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { try { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); @@ -1242,7 +1242,7 @@ it('timezone info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { try { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); @@ -1262,7 +1262,7 @@ it('timezone info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { try { assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); @@ -1294,7 +1294,7 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { var err = null; try { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); @@ -1311,7 +1311,7 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { var err = null; try { assert.equal(res.statusCode, 200, res.body); @@ -1332,7 +1332,7 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { var err = null; try { assert.equal(res.statusCode, 200, res.body); @@ -1354,7 +1354,7 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { var err = null; try { assert.equal(res.statusCode, 200, res.body); @@ -1378,7 +1378,7 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { try { assert.equal(res.statusCode, 200, res.body); JSON.parse(res.body); @@ -1400,7 +1400,7 @@ it('GET /api/v1/sql with SQL parameter on SELECT only should return CORS headers url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&database=cartodb_test_user_1_db', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); // Check cache headers assert.equal(res.headers['x-cache-channel'], 'cartodb_test_user_1_db:public.untitle_table_4'); @@ -1419,7 +1419,7 @@ it('GET with callback param returns wrapped result set with callback as jsonp', url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&callback=foo_jsonp', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); assert.ok(res.body.match(/foo\_jsonp\(.*\)/)); done(); @@ -1431,7 +1431,7 @@ it('GET with callback must return 200 status error even if it is an error', func url: "/api/v1/sql?q=DROP%20TABLE%20untitle_table_4&callback=foo_jsonp", headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var didRunJsonCallback = false; // jshint ignore:start @@ -1455,7 +1455,7 @@ it('GET with callback must return 200 status error even if it is an error', func { status: 400 }, - function(res) { + function(err, res) { assert.ok(res.body.match(/was not able to finish.*try again/i)); done(); }); diff --git a/test/acceptance/backend_crash.js b/test/acceptance/backend_crash.js index 6773ec3b..d6d338a1 100644 --- a/test/acceptance/backend_crash.js +++ b/test/acceptance/backend_crash.js @@ -30,14 +30,11 @@ it('does not hang server', function(done){ var server = require('../../app/server')(); step( function sendQuery() { - var next = this; assert.response(server, { url: '/api/v1/sql?q=SELECT+1', method: 'GET', headers: {host: 'vizzuality.localhost' } - },{}, function(res, err) { - next(err, res); - }); + },{}, this); }, function checkResponse(err, res) { assert.ifError(err); @@ -49,14 +46,11 @@ it('does not hang server', function(done){ return null; }, function sendAnotherQuery() { - var next = this; assert.response(server, { url: '/api/v1/sql?q=SELECT+2', method: 'GET', headers: {host: 'vizzuality.localhost' } - },{}, function(res, err) { - next(err, res); - }); + },{}, this); }, function checkResponse(err, res) { assert.ifError(err); diff --git a/test/acceptance/export/arraybuffer.js b/test/acceptance/export/arraybuffer.js index 93629604..2a297b85 100644 --- a/test/acceptance/export/arraybuffer.js +++ b/test/acceptance/export/arraybuffer.js @@ -16,7 +16,7 @@ it('GET /api/v1/sql as arraybuffer ', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers['content-type'], "application/octet-stream"); done(); @@ -31,7 +31,7 @@ it('GET /api/v1/sql as arraybuffer does not support geometry types ', function(d }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 400, res.body); var result = JSON.parse(res.body); assert.equal(result.error[0], "geometry types are not supported"); diff --git a/test/acceptance/export/csv.js b/test/acceptance/export/csv.js index e3c246f7..d9a46fa0 100644 --- a/test/acceptance/export/csv.js +++ b/test/acceptance/export/csv.js @@ -16,7 +16,7 @@ it('CSV format', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'CSV is not disposed as attachment: ' + cd); @@ -44,7 +44,7 @@ it('CSV format, bigger than 81920 bytes', function(done){ }), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.ok(res.body.length > 81920, 'CSV smaller than expected: ' + res.body.length); done(); }); @@ -57,7 +57,7 @@ it('CSV format from POST', function(done){ data: querystring.stringify({q: "SELECT * FROM untitle_table_4 LIMIT 1", format: 'csv'}), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'CSV is not disposed as attachment: ' + cd); @@ -73,7 +73,7 @@ it('CSV format, custom filename', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=csv&filename=mycsv.csv', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'CSV is not disposed as attachment: ' + cd); @@ -100,7 +100,7 @@ it('skipfields controls fields included in CSV output', function(done){ '&skipfields=unexistant,cartodb_id', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var row0 = res.body.substring(0, res.body.search(/[\n\r]/)).split(','); var checkFields = { name: true, cartodb_id: false, the_geom: true, the_geom_webmercator: true }; @@ -122,7 +122,7 @@ it('GET /api/v1/sql as csv', function(done){ '&format=csv', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var expected = 'cartodb_id,geom\r\n1,"SRID=4326;POINT(-3.699732 40.423012)"\r\n'; assert.equal(res.body, expected); @@ -136,7 +136,7 @@ it('GET /api/v1/sql as csv with no rows', function(done){ url: '/api/v1/sql?q=SELECT%20true%20WHERE%20false&format=csv', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var obtained_lines = res.body.split('\r\n'); assert.ok(obtained_lines.length <= 2, // may or may not have an header @@ -151,7 +151,7 @@ it('GET /api/v1/sql as csv, properly escaped', function(done){ url: '/api/v1/sql?q=SELECT%20cartodb_id,%20address%20FROM%20untitle_table_4%20LIMIT%201&format=csv', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var expected = 'cartodb_id,address\r\n1,"Calle de Pérez Galdós 9, Madrid, Spain"\r\n'; assert.equal(res.body, expected); @@ -163,7 +163,7 @@ it('GET /api/v1/sql as csv, concurrently', function(done){ var concurrency = 4; var waiting = concurrency; - function validate(res){ + function validate(err, res){ var expected = 'cartodb_id,address\r\n1,"Calle de Pérez Galdós 9, Madrid, Spain"\r\n'; assert.equal(res.body, expected); if ( ! --waiting ) { @@ -199,7 +199,7 @@ it('GET /api/v1/sql as csv, concurrently', function(done){ { status: 200 }, - function(res) { + function(err, res) { var headersPlusExtraLine = 2; assert.equal(res.body.split('\n').length, limit + headersPlusExtraLine); done(); diff --git a/test/acceptance/export/geojson.js b/test/acceptance/export/geojson.js index 656c29f6..3d9ab47a 100644 --- a/test/acceptance/export/geojson.js +++ b/test/acceptance/export/geojson.js @@ -23,7 +23,7 @@ it('GET /api/v1/sql with SQL parameter, ensuring content-disposition set to geoj url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'GEOJSON is not disposed as attachment: ' + cd); @@ -38,7 +38,7 @@ it('POST /api/v1/sql with SQL parameter, ensuring content-disposition set to geo data: querystring.stringify({q: "SELECT * FROM untitle_table_4", format: 'geojson' }), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'GEOJSON is not disposed as attachment: ' + cd); @@ -52,7 +52,7 @@ it('uses the last format parameter when multiple are used', function(done){ url: '/api/v1/sql?format=csv&q=SELECT%20*%20FROM%20untitle_table_4&format=geojson', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /filename=cartodb-query.geojson/gi.test(cd)); @@ -65,7 +65,7 @@ it('uses custom filename', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson&filename=x', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /filename=x.geojson/gi.test(cd), cd); @@ -78,7 +78,7 @@ it('does not include the_geom and the_geom_webmercator properties by default', f url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var parsed_body = JSON.parse(res.body); var row0 = parsed_body.features[0].properties; @@ -99,7 +99,7 @@ it('skipfields controls fields included in GeoJSON output', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson&skipfields=unexistant,cartodb_id', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var parsed_body = JSON.parse(res.body); var row0 = parsed_body.features[0].properties; @@ -124,7 +124,7 @@ it('GET /api/v1/sql as geojson limiting decimal places', function(done){ dp: '1'}), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var result = JSON.parse(res.body); assert.equal(1, checkDecimals(result.features[0].geometry.coordinates[0], '.')); @@ -139,7 +139,7 @@ it('GET /api/v1/sql as geojson with default dp as 6', function(done){ format: 'geojson'}), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var result = JSON.parse(res.body); assert.equal(6, checkDecimals(result.features[0].geometry.coordinates[0], '.')); @@ -155,7 +155,7 @@ it('null geometries in geojson output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'GEOJSON is not disposed as attachment: ' + cd); @@ -180,7 +180,7 @@ it('stream response handle errors', function(done) { }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 400, res.body); var geoJson = JSON.parse(res.body); assert.ok(geoJson.error); @@ -198,7 +198,7 @@ it('stream response with empty result set has valid output', function(done) { }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var geoJson = JSON.parse(res.body); var expectedGeoJson = {"type": "FeatureCollection", "features": []}; diff --git a/test/acceptance/export/geopackage.js b/test/acceptance/export/geopackage.js index 68f7eabb..b7a9f5bf 100644 --- a/test/acceptance/export/geopackage.js +++ b/test/acceptance/export/geopackage.js @@ -15,7 +15,7 @@ describe('geopackage query', function(){ url: base_url, headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers["content-type"], "application/x-sqlite3; charset=utf-8"); assert.notEqual(res.headers["content-disposition"].indexOf(table_name + ".gpkg"), -1); @@ -35,7 +35,7 @@ describe('geopackage query', function(){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { var tmpfile = '/tmp/a_geopackage_file.gpkg'; try { fs.writeFileSync(tmpfile, res.body, 'binary'); diff --git a/test/acceptance/export/kml.js b/test/acceptance/export/kml.js index 0f8a69c1..b85d0e45 100644 --- a/test/acceptance/export/kml.js +++ b/test/acceptance/export/kml.js @@ -110,7 +110,7 @@ it('KML format, unauthenticated', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=kml', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); @@ -134,7 +134,7 @@ it('KML format, unauthenticated, POST', function(done){ data: 'q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=kml', headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); @@ -152,7 +152,7 @@ it('KML format, bigger than 81920 bytes', function(done){ }), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); @@ -167,7 +167,7 @@ it('KML format, skipfields', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=kml&skipfields=address,cartodb_id', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); @@ -190,7 +190,7 @@ it('KML format, unauthenticated, custom filename', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=kml&filename=kmltest', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); @@ -206,7 +206,7 @@ it('KML format, authenticated', function(done){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=kml&api_key=1234', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /filename=cartodb-query.kml/gi.test(cd), 'Unexpected KML filename: ' + cd); @@ -275,7 +275,7 @@ it('GET /api/v1/sql as kml with no rows', function(done){ url: '/api/v1/sql?q=SELECT%20true%20WHERE%20false&format=kml', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); // NOTE: GDAL-1.11+ added 'id="root_doc"' attribute to the output var pat = new RegExp('^<\\?xml version="1.0" encoding="utf-8" \\?>' + @@ -298,7 +298,7 @@ it('GET /api/v1/sql as kml with ending semicolon', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); // NOTE: GDAL-1.11+ added 'id="root_doc"' attribute to the output var pat = new RegExp('^<\\?xml version="1.0" encoding="utf-8" \\?>' + @@ -321,7 +321,7 @@ it('check point coordinates, unauthenticated', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var coords = extractCoordinates(res.body); assert(coords, 'No coordinates in ' + res.body); @@ -340,7 +340,7 @@ it('check point coordinates, authenticated', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var coords = extractCoordinates(res.body); assert(coords, 'No coordinates in ' + res.body); @@ -366,7 +366,7 @@ it('check point coordinates, authenticated', function(done){ { status: 200 }, - function(res) { + function(err, res) { assert.equal(res.body.match(//g).length, limit); done(); } @@ -387,7 +387,7 @@ it('check point coordinates, authenticated', function(done){ { status: 200 }, - function(res) { + function(err, res) { assert.equal(res.body.match(//g).length, limit); done(); } @@ -411,7 +411,7 @@ it('check point coordinates, authenticated', function(done){ { status: 200 }, - function(res) { + function(err, res) { assert.equal(res.body.match(//g), null); done(); } diff --git a/test/acceptance/export/shapefile.js b/test/acceptance/export/shapefile.js index 76b4a864..232b3894 100644 --- a/test/acceptance/export/shapefile.js +++ b/test/acceptance/export/shapefile.js @@ -18,7 +18,7 @@ it('SHP format, unauthenticated', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); @@ -45,7 +45,7 @@ it('SHP format, unauthenticated, POST', function(done){ data: 'q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=shp', headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); @@ -63,7 +63,7 @@ it('SHP format, big size, POST', function(done){ }), headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); @@ -79,7 +79,7 @@ it('SHP format, unauthenticated, with custom filename', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); @@ -105,7 +105,7 @@ it('SHP format, unauthenticated, with custom, dangerous filename', function(done headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var fname = "b_______a"; var cd = res.header('Content-Disposition'); @@ -132,7 +132,7 @@ it('SHP format, authenticated', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); @@ -165,7 +165,7 @@ it('SHP format, unauthenticated, with utf8 data', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var tmpfile = '/tmp/myshape.zip'; var err = fs.writeFileSync(tmpfile, res.body, 'binary'); @@ -192,7 +192,7 @@ it('mixed type geometry', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); assert.equal(res.statusCode, 400, res.statusCode + ': ' +res.body); @@ -217,7 +217,7 @@ it('errors are not confused with warnings', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); assert.equal(res.statusCode, 400, res.statusCode + ': ' +res.body); @@ -240,7 +240,7 @@ it('skipfields controls fields included in SHP output', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var tmpfile = '/tmp/myshape.zip'; var err = fs.writeFileSync(tmpfile, res.body, 'binary'); @@ -259,7 +259,7 @@ it('skipfields controls fields included in SHP output', function(done){ it('SHP format, concurrently', function(done){ var concurrency = 1; var waiting = concurrency; - function validate(res){ + function validate(err, res){ var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); @@ -307,7 +307,7 @@ it('point with null first', function(done){ headers: {host: 'vizzuality.cartodb.com'}, encoding: 'binary', method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); @@ -346,7 +346,7 @@ it('point with null first', function(done){ { status: 200 }, - function(res, err) { + function(err, res) { if (err) { return done(err); } diff --git a/test/acceptance/export/spatialite.js b/test/acceptance/export/spatialite.js index 6110af29..7b116cb3 100644 --- a/test/acceptance/export/spatialite.js +++ b/test/acceptance/export/spatialite.js @@ -11,7 +11,7 @@ describe('spatialite query', function(){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=spatialite', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.statusCode, 200, res.body); assert.equal(res.headers["content-type"], "application/x-sqlite3; charset=utf-8"); var db = new sqlite.Database(':memory:', res.body); @@ -29,7 +29,7 @@ describe('spatialite query', function(){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=spatialite&filename=manolo', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { assert.equal(res.headers["content-type"], "application/x-sqlite3; charset=utf-8"); assert.notEqual(res.headers["content-disposition"].indexOf("manolo.sqlite"), -1); done(); @@ -41,7 +41,7 @@ describe('spatialite query', function(){ url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4%20LIMIT%201&format=spatialite', headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res) { + },{ }, function(err, res) { var db = new sqlite.Database(':memory:', res.body); var schemaQuery = "SELECT name, sql FROM sqlite_master WHERE type='table' ORDER BY name"; var qr = db.get(schemaQuery, function(err){ diff --git a/test/acceptance/export/svg.js b/test/acceptance/export/svg.js index 10b9ceb7..743d7a70 100644 --- a/test/acceptance/export/svg.js +++ b/test/acceptance/export/svg.js @@ -15,7 +15,7 @@ it('GET /api/v1/sql with SVG format', function(done){ url: '/api/v1/sql?' + query, headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); @@ -36,7 +36,7 @@ it('POST /api/v1/sql with SVG format', function(done){ data: query, headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'SVG is not disposed as attachment: ' + cd); @@ -58,7 +58,7 @@ it('GET /api/v1/sql with SVG format and custom filename', function(done){ url: '/api/v1/sql?' + query, headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.ok(/filename=mysvg.svg/gi.test(cd), cd); @@ -78,7 +78,7 @@ it('GET /api/v1/sql with SVG format and centered point', function(done){ url: '/api/v1/sql?' + query, headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); @@ -100,7 +100,7 @@ it('GET /api/v1/sql with SVG format and trimmed decimals', function(done){ url: '/api/v1/sql?' + querystring.stringify(queryobj), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); @@ -113,7 +113,7 @@ it('GET /api/v1/sql with SVG format and trimmed decimals', function(done){ url: '/api/v1/sql?' + querystring.stringify(queryobj), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(res) { + },{}, function(err, res) { assert.equal(res.statusCode, 200, res.body); var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'SVG is not disposed as attachment: ' + cd); @@ -138,7 +138,7 @@ it('SVG format with "the_geom" in skipfields', function(done){ url: '/api/v1/sql?' + query, headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); @@ -158,7 +158,7 @@ it('SVG format with missing "the_geom" field', function(done){ url: '/api/v1/sql?' + query, headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(res){ + },{ }, function(err, res){ assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body); assert.deepEqual(JSON.parse(res.body), { error:['column "the_geom" does not exist'] @@ -183,7 +183,7 @@ it('SVG format with missing "the_geom" field', function(done){ { status: 400 }, - function(res) { + function(err, res) { var parsedBody = JSON.parse(res.body); assert.deepEqual(Object.keys(parsedBody), ['error']); assert.deepEqual(parsedBody.error, ["division by zero"]); diff --git a/test/acceptance/export/topojson.js b/test/acceptance/export/topojson.js index 48516835..de3487ef 100644 --- a/test/acceptance/export/topojson.js +++ b/test/acceptance/export/topojson.js @@ -34,7 +34,7 @@ it('GET two polygons sharing an edge as topojson', function(done){ { status: 200 }, - function(res) { + function(err, res) { var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'TOPOJSON is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.topojson/gi.test(cd)); @@ -139,7 +139,7 @@ it('null geometries', function(done){ { status: 200 }, - function(res) { + function(err, res) { var cd = res.header('Content-Disposition'); assert.equal(true, /^attachment/.test(cd), 'TOPOJSON is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.topojson/gi.test(cd)); @@ -199,7 +199,7 @@ it('null geometries', function(done){ { status: 200 }, - function(res) { + function(err, res) { var parsedBody = JSON.parse(res.body); assert.equal(parsedBody.objects[0].properties.gid, 1, 'gid was expected property'); assert.ok(!parsedBody.objects[0].properties.name); @@ -220,7 +220,7 @@ it('null geometries', function(done){ { status: 200 }, - function(res) { + function(err, res) { assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); var didRunJsonCallback = false; // jshint ignore:start @@ -252,7 +252,7 @@ it('null geometries', function(done){ { status: 400 }, - function(res) { + function(err, res) { var parsedBody = JSON.parse(res.body); assert.deepEqual(Object.keys(parsedBody), ['error']); assert.deepEqual(parsedBody.error, ["division by zero"]); diff --git a/test/acceptance/frontend_abort.js b/test/acceptance/frontend_abort.js index 0ed809be..16cb1080 100644 --- a/test/acceptance/frontend_abort.js +++ b/test/acceptance/frontend_abort.js @@ -34,15 +34,12 @@ it('aborts request', function(done){ var timeout; step( function sendQuery() { - var next = this; assert.response(server, { url: '/api/v1/sql?q=SELECT+1', method: 'GET', timeout: 1, headers: {host: 'vizzuality.localhost' } - },{}, function(res, err) { - next(err, res); - }); + },{}, this); }, function checkResponse(err/*, res*/) { assert(err); // expect timeout diff --git a/test/acceptance/health_check.js b/test/acceptance/health_check.js index 5d14b280..7a94e6cb 100644 --- a/test/acceptance/health_check.js +++ b/test/acceptance/health_check.js @@ -31,7 +31,7 @@ describe('health checks', function() { { status: 200 }, - function(res, err) { + function(err, res) { assert.ok(!err); var parsed = JSON.parse(res.body); @@ -50,7 +50,7 @@ describe('health checks', function() { { status: 200 }, - function(res, err) { + function(err, res) { assert.ok(!err); var parsed = JSON.parse(res.body); diff --git a/test/acceptance/job.callback-template.test.js b/test/acceptance/job.callback-template.test.js index 9e672e14..52f90ba3 100644 --- a/test/acceptance/job.callback-template.test.js +++ b/test/acceptance/job.callback-template.test.js @@ -28,7 +28,7 @@ describe('Batch API callback templates', function () { data: querystring.stringify(jobDefinition) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return callback(err); } @@ -45,7 +45,7 @@ describe('Batch API callback templates', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return callback(err); } @@ -62,7 +62,7 @@ describe('Batch API callback templates', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return callback(err); } diff --git a/test/acceptance/job.fallback.test.js b/test/acceptance/job.fallback.test.js index 499ad708..2e23d4a2 100644 --- a/test/acceptance/job.fallback.test.js +++ b/test/acceptance/job.fallback.test.js @@ -69,7 +69,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -98,7 +98,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -137,7 +137,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -165,7 +165,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -204,7 +204,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -233,7 +233,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -272,7 +272,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -302,7 +302,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -342,7 +342,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -370,7 +370,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -409,7 +409,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -438,7 +438,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -478,7 +478,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -507,7 +507,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -546,7 +546,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -574,7 +574,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -615,7 +615,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -645,7 +645,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -687,7 +687,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -721,7 +721,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -763,7 +763,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -798,7 +798,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -841,7 +841,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -876,7 +876,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -918,7 +918,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -952,7 +952,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -991,7 +991,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1021,7 +1021,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1061,7 +1061,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1090,7 +1090,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1132,7 +1132,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1167,7 +1167,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1209,7 +1209,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1244,7 +1244,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1287,7 +1287,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1322,7 +1322,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1366,7 +1366,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1402,7 +1402,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1443,7 +1443,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1473,7 +1473,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1512,7 +1512,7 @@ describe('Batch API fallback job', function () { method: 'DELETE' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1549,7 +1549,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1579,7 +1579,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1621,7 +1621,7 @@ describe('Batch API fallback job', function () { method: 'DELETE' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1661,7 +1661,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1697,7 +1697,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1740,7 +1740,7 @@ describe('Batch API fallback job', function () { }) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } @@ -1779,7 +1779,7 @@ describe('Batch API fallback job', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return done(err); } diff --git a/test/acceptance/job.query.limit.test.js b/test/acceptance/job.query.limit.test.js index 5a94589d..9ce4e627 100644 --- a/test/acceptance/job.query.limit.test.js +++ b/test/acceptance/job.query.limit.test.js @@ -51,7 +51,7 @@ describe('job query limit', function() { }) }, { status: 400 - }, function (res) { + }, function (err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [expectedErrorMessage(queryTooLong)] }); done(); @@ -69,7 +69,7 @@ describe('job query limit', function() { }) }, { status: 201 - }, function (res) { + }, function (err, res) { var job = JSON.parse(res.body); assert.ok(job.job_id); done(); @@ -87,7 +87,7 @@ describe('job query limit', function() { }) }, { status: 400 - }, function (res) { + }, function (err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [expectedErrorMessage(queries)] }); done(); @@ -113,7 +113,7 @@ describe('job query limit', function() { }) }, { status: 400 - }, function (res) { + }, function (err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [expectedErrorMessage(fallbackQueries)] }); done(); diff --git a/test/acceptance/job.test.js b/test/acceptance/job.test.js index f5e2890c..ec4f45ee 100644 --- a/test/acceptance/job.test.js +++ b/test/acceptance/job.test.js @@ -36,7 +36,7 @@ describe('job module', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { job = JSON.parse(res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.ok(job.job_id); @@ -55,7 +55,7 @@ describe('job module', function() { data: querystring.stringify({}) }, { status: 400 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [ 'You must indicate a valid SQL' ] }); done(); @@ -72,7 +72,7 @@ describe('job module', function() { }) }, { status: 400 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [ 'You must indicate a valid SQL' ] }); done(); @@ -89,7 +89,7 @@ describe('job module', function() { }) }, { status: 401 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [ 'permission denied' ] }); done(); @@ -106,7 +106,7 @@ describe('job module', function() { }) }, { status: 404 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [ @@ -125,7 +125,7 @@ describe('job module', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var jobGot = JSON.parse(res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.equal(jobGot.query, "SELECT * FROM untitle_table_4"); @@ -141,7 +141,7 @@ describe('job module', function() { method: 'GET' }, { status: 401 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [ 'permission denied' ] }); done(); @@ -155,7 +155,7 @@ describe('job module', function() { method: 'GET' }, { status: 400 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); console.log(error); assert.deepEqual(error , { @@ -172,7 +172,7 @@ describe('job module', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { var jobCancelled = JSON.parse(res.body); assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.equal(jobCancelled.job_id, job.job_id); @@ -190,7 +190,7 @@ describe('job module', function() { method: 'DELETE' }, { status: 401 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); assert.deepEqual(error, { error: [ 'permission denied' ] }); done(); @@ -204,7 +204,7 @@ describe('job module', function() { method: 'DELETE' }, { status: 404 - }, function(res) { + }, function(err, res) { var error = JSON.parse(res.body); assert.deepEqual(error , { error: [ diff --git a/test/acceptance/job.timing.test.js b/test/acceptance/job.timing.test.js index f5d479a9..ed88827b 100644 --- a/test/acceptance/job.timing.test.js +++ b/test/acceptance/job.timing.test.js @@ -28,7 +28,7 @@ describe('Batch API query timing', function () { data: querystring.stringify(jobDefinition) }, { status: 201 - }, function (res, err) { + }, function (err, res) { if (err) { return callback(err); } @@ -45,7 +45,7 @@ describe('Batch API query timing', function () { method: 'GET' }, { status: 200 - }, function (res, err) { + }, function (err, res) { if (err) { return callback(err); } diff --git a/test/acceptance/job.use-case-1.test.js b/test/acceptance/job.use-case-1.test.js index 68b47a07..c76004d9 100644 --- a/test/acceptance/job.use-case-1.test.js +++ b/test/acceptance/job.use-case-1.test.js @@ -53,7 +53,7 @@ describe('Use case 1: cancel and modify a done job', function () { }) }, { status: 201 - }, function (res) { + }, function (err, res) { doneJob = JSON.parse(res.body); done(); }); @@ -67,7 +67,7 @@ describe('Use case 1: cancel and modify a done job', function () { method: 'GET' }, { status: 200 - }, function (res) { + }, function (err, res) { var job = JSON.parse(res.body); if (job.status === "done") { clearInterval(interval); @@ -89,7 +89,7 @@ describe('Use case 1: cancel and modify a done job', function () { method: 'DELETE' }, { status: 400 - }, function(res) { + }, function(err, res) { var errors = JSON.parse(res.body); assert.equal(errors.error[0], "Cannot set status from done to cancelled"); done(); diff --git a/test/acceptance/job.use-case-10.test.js b/test/acceptance/job.use-case-10.test.js index 6dd5dc0e..52cfe3a6 100644 --- a/test/acceptance/job.use-case-10.test.js +++ b/test/acceptance/job.use-case-10.test.js @@ -57,7 +57,7 @@ describe('Use case 10: cancel and modify a done multiquery job', function () { }) }, { status: 201 - }, function (res) { + }, function (err, res) { doneJob = JSON.parse(res.body); done(); }); @@ -71,7 +71,7 @@ describe('Use case 10: cancel and modify a done multiquery job', function () { method: 'GET' }, { status: 200 - }, function (res) { + }, function (err, res) { var job = JSON.parse(res.body); if (job.status === "done") { clearInterval(interval); @@ -93,7 +93,7 @@ describe('Use case 10: cancel and modify a done multiquery job', function () { method: 'DELETE' }, { status: 400 - }, function(res) { + }, function(err, res) { var errors = JSON.parse(res.body); assert.equal(errors.error[0], "Cannot set status from done to cancelled"); done(); diff --git a/test/acceptance/job.use-case-2.test.js b/test/acceptance/job.use-case-2.test.js index 00fcabe6..244a6ac3 100644 --- a/test/acceptance/job.use-case-2.test.js +++ b/test/acceptance/job.use-case-2.test.js @@ -54,7 +54,7 @@ describe('Use case 2: cancel a running job', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { runningJob = JSON.parse(res.body); done(); }); @@ -68,7 +68,7 @@ describe('Use case 2: cancel a running job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "running") { clearInterval(interval); @@ -88,7 +88,7 @@ describe('Use case 2: cancel a running job', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { cancelledJob = JSON.parse(res.body); assert.equal(cancelledJob.status, "cancelled"); done(); @@ -102,7 +102,7 @@ describe('Use case 2: cancel a running job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "cancelled") { done(); @@ -119,7 +119,7 @@ describe('Use case 2: cancel a running job', function() { method: 'DELETE' }, { status: 400 - }, function(res) { + }, function(err, res) { var errors = JSON.parse(res.body); assert.equal(errors.error[0], "Cannot set status from cancelled to cancelled"); done(); diff --git a/test/acceptance/job.use-case-3.test.js b/test/acceptance/job.use-case-3.test.js index 546196ec..4f5eafb6 100644 --- a/test/acceptance/job.use-case-3.test.js +++ b/test/acceptance/job.use-case-3.test.js @@ -54,7 +54,7 @@ describe('Use case 3: cancel a pending job', function() { }) }, { status: 201 - }, function (res) { + }, function (err, res) { runningJob = JSON.parse(res.body); done(); }); @@ -70,7 +70,7 @@ describe('Use case 3: cancel a pending job', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { pendingJob = JSON.parse(res.body); done(); }); @@ -84,7 +84,7 @@ describe('Use case 3: cancel a pending job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "pending") { clearInterval(interval); @@ -104,7 +104,7 @@ describe('Use case 3: cancel a pending job', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { var jobGot = JSON.parse(res.body); assert.equal(jobGot.job_id, pendingJob.job_id); assert.equal(jobGot.status, "cancelled"); @@ -119,7 +119,7 @@ describe('Use case 3: cancel a pending job', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { var cancelledJob = JSON.parse(res.body); assert.equal(cancelledJob.status, "cancelled"); done(); diff --git a/test/acceptance/job.use-case-4.test.js b/test/acceptance/job.use-case-4.test.js index ceaf33e1..2c24af96 100644 --- a/test/acceptance/job.use-case-4.test.js +++ b/test/acceptance/job.use-case-4.test.js @@ -54,7 +54,7 @@ describe('Use case 4: modify a pending job', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { runningJob = JSON.parse(res.body); done(); }); @@ -70,7 +70,7 @@ describe('Use case 4: modify a pending job', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { pendingJob = JSON.parse(res.body); done(); }); @@ -84,7 +84,7 @@ describe('Use case 4: modify a pending job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "pending") { clearInterval(interval); @@ -104,7 +104,7 @@ describe('Use case 4: modify a pending job', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { var cancelledJob = JSON.parse(res.body); assert.equal(cancelledJob.status, "cancelled"); done(); diff --git a/test/acceptance/job.use-case-5.test.js b/test/acceptance/job.use-case-5.test.js index 6f41b964..a4581608 100644 --- a/test/acceptance/job.use-case-5.test.js +++ b/test/acceptance/job.use-case-5.test.js @@ -53,7 +53,7 @@ describe('Use case 5: modify a running job', function() { }) }, { status: 201 - }, function (res) { + }, function (err, res) { runningJob = JSON.parse(res.body); done(); }); @@ -67,7 +67,7 @@ describe('Use case 5: modify a running job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "running") { clearInterval(interval); @@ -87,7 +87,7 @@ describe('Use case 5: modify a running job', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { var cancelledJob = JSON.parse(res.body); assert.equal(cancelledJob.status, "cancelled"); done(); diff --git a/test/acceptance/job.use-case-6.test.js b/test/acceptance/job.use-case-6.test.js index abf69696..8f56c546 100644 --- a/test/acceptance/job.use-case-6.test.js +++ b/test/acceptance/job.use-case-6.test.js @@ -53,7 +53,7 @@ describe('Use case 6: modify a done job', function() { }) }, { status: 201 - }, function (res) { + }, function (err, res) { doneJob = JSON.parse(res.body); done(); }); @@ -67,7 +67,7 @@ describe('Use case 6: modify a done job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "done") { clearInterval(interval); diff --git a/test/acceptance/job.use-case-7.test.js b/test/acceptance/job.use-case-7.test.js index c867d5b9..1180078a 100644 --- a/test/acceptance/job.use-case-7.test.js +++ b/test/acceptance/job.use-case-7.test.js @@ -53,7 +53,7 @@ describe('Use case 7: cancel a job with quotes', function() { }) }, { status: 201 - }, function (res) { + }, function (err, res) { runningJob = JSON.parse(res.body); done(); }); @@ -67,7 +67,7 @@ describe('Use case 7: cancel a job with quotes', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "running") { clearInterval(interval); @@ -87,7 +87,7 @@ describe('Use case 7: cancel a job with quotes', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { var cancelledJob = JSON.parse(res.body); assert.equal(cancelledJob.status, "cancelled"); done(); diff --git a/test/acceptance/job.use-case-8.test.js b/test/acceptance/job.use-case-8.test.js index dd42921a..41863349 100644 --- a/test/acceptance/job.use-case-8.test.js +++ b/test/acceptance/job.use-case-8.test.js @@ -58,7 +58,7 @@ describe('Use case 8: cancel a running multiquery job', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { runningJob = JSON.parse(res.body); done(); }); @@ -72,7 +72,7 @@ describe('Use case 8: cancel a running multiquery job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "running") { clearInterval(interval); @@ -92,7 +92,7 @@ describe('Use case 8: cancel a running multiquery job', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { cancelledJob = JSON.parse(res.body); assert.equal(cancelledJob.status, "cancelled"); done(); @@ -106,7 +106,7 @@ describe('Use case 8: cancel a running multiquery job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "cancelled") { done(); @@ -123,7 +123,7 @@ describe('Use case 8: cancel a running multiquery job', function() { method: 'DELETE' }, { status: 400 - }, function(res) { + }, function(err, res) { var errors = JSON.parse(res.body); assert.equal(errors.error[0], "Cannot set status from cancelled to cancelled"); done(); diff --git a/test/acceptance/job.use-case-9.test.js b/test/acceptance/job.use-case-9.test.js index 8308bcc3..3ba2cd5f 100644 --- a/test/acceptance/job.use-case-9.test.js +++ b/test/acceptance/job.use-case-9.test.js @@ -57,7 +57,7 @@ describe('Use case 9: modify a pending multiquery job', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { runningJob = JSON.parse(res.body); done(); }); @@ -76,7 +76,7 @@ describe('Use case 9: modify a pending multiquery job', function() { }) }, { status: 201 - }, function(res) { + }, function(err, res) { pendingJob = JSON.parse(res.body); done(); }); @@ -90,7 +90,7 @@ describe('Use case 9: modify a pending multiquery job', function() { method: 'GET' }, { status: 200 - }, function(res) { + }, function(err, res) { var job = JSON.parse(res.body); if (job.status === "pending") { clearInterval(interval); @@ -110,7 +110,7 @@ describe('Use case 9: modify a pending multiquery job', function() { method: 'DELETE' }, { status: 200 - }, function(res) { + }, function(err, res) { var cancelledJob = JSON.parse(res.body); assert.equal(cancelledJob.status, "cancelled"); done(); diff --git a/test/acceptance/last-modified-header.js b/test/acceptance/last-modified-header.js index 5f0db6df..09e0c606 100644 --- a/test/acceptance/last-modified-header.js +++ b/test/acceptance/last-modified-header.js @@ -48,7 +48,7 @@ describe('last modified header', function() { { statusCode: 200 }, - function(res) { + function(err, res) { assert.equal(res.headers['last-modified'], scenario.expectedLastModified); done(); } @@ -77,7 +77,7 @@ describe('last modified header', function() { { statusCode: 200 }, - function(res) { + function(err, res) { Date.now = dateNowFn; assert.equal(res.headers['last-modified'], new Date(fixedDateNow).toUTCString()); done(); @@ -106,7 +106,7 @@ describe('last modified header', function() { { statusCode: 200 }, - function(res) { + function(err, res) { Date.now = dateNowFn; assert.equal(res.headers['last-modified'], new Date(fixedDateNow).toUTCString()); done(); diff --git a/test/acceptance/logging.js b/test/acceptance/logging.js index da348f5b..db332d65 100644 --- a/test/acceptance/logging.js +++ b/test/acceptance/logging.js @@ -105,7 +105,7 @@ describe('Logging SQL query on POST requests', function() { return result; }; - assert.response(server, scenario.request, RESPONSE_OK, function(res, err) { + assert.response(server, scenario.request, RESPONSE_OK, function(err, res) { assert.ok(!err); assert.equal(called, 1); @@ -137,7 +137,7 @@ describe('Logging SQL query on POST requests', function() { } }, RESPONSE_OK, - function(res, err) { + function(err) { assert.ok(!err); assert.equal(called, 1); diff --git a/test/acceptance/query-tables-api-cache.js b/test/acceptance/query-tables-api-cache.js index 5880e634..04489778 100644 --- a/test/acceptance/query-tables-api-cache.js +++ b/test/acceptance/query-tables-api-cache.js @@ -17,7 +17,7 @@ describe('query-tables-api', function() { { status: 200 }, - function(res) { + function(err, res) { callback(null, JSON.parse(res.body)); } ); @@ -38,7 +38,7 @@ describe('query-tables-api', function() { }; it('should create a key in affected tables cache', function(done) { - assert.response(server, request, RESPONSE_OK, function(res, err) { + assert.response(server, request, RESPONSE_OK, function(err, res) { assert.ok(!err, err); getCacheStatus(function(err, cacheStatus) { @@ -52,7 +52,7 @@ describe('query-tables-api', function() { }); it('should use cache to retrieve affected tables', function(done) { - assert.response(server, request, RESPONSE_OK, function(res, err) { + assert.response(server, request, RESPONSE_OK, function(err, res) { assert.ok(!err, err); getCacheStatus(function(err, cacheStatus) { @@ -76,7 +76,7 @@ describe('query-tables-api', function() { }, method: 'GET' }; - assert.response(server, authenticatedRequest, RESPONSE_OK, function(res, err) { + assert.response(server, authenticatedRequest, RESPONSE_OK, function(err) { assert.ok(!err, err); getCacheStatus(function(err, cacheStatus) { diff --git a/test/acceptance/regressions.js b/test/acceptance/regressions.js index 7d13615e..9efbb003 100644 --- a/test/acceptance/regressions.js +++ b/test/acceptance/regressions.js @@ -26,13 +26,13 @@ describe('regressions', function() { }; assert.response(server, createRequest('CREATE TABLE "foo.bar" (a int);'), responseOk, - function(res, err) { + function(err, res) { if (err) { return done(err); } assert.response(server, createRequest('INSERT INTO "foo.bar" (a) values (1), (2)'), responseOk, - function(res, err) { + function(err, res) { if (err) { return done(err); } @@ -40,7 +40,7 @@ describe('regressions', function() { assert.equal(parsedBody.total_rows, 2); assert.response(server, createRequest('SELECT * FROM "foo.bar"'), responseOk, - function(res, err) { + function(err, res) { if (err) { return done(err); } diff --git a/test/acceptance/stream-responses.js b/test/acceptance/stream-responses.js index cc6c7e6d..237cc9de 100644 --- a/test/acceptance/stream-responses.js +++ b/test/acceptance/stream-responses.js @@ -35,7 +35,7 @@ describe('stream-responses', function() { server, createFailingQueryRequest(), okResponse, - function(res) { + function(err, res) { var parsedBody = JSON.parse(res.body); assert.equal(parsedBody.rows.length, 2); assert.deepEqual(parsedBody.fields, { @@ -57,7 +57,7 @@ describe('stream-responses', function() { server, createFailingQueryRequest('geojson'), okResponse, - function(res) { + function(err, res) { var parsedBody = JSON.parse(res.body); assert.equal(parsedBody.features.length, 2); assert.deepEqual(parsedBody.error, ["division by zero"]); diff --git a/test/acceptance/surrogate-key.js b/test/acceptance/surrogate-key.js index 8254bbed..f460f556 100644 --- a/test/acceptance/surrogate-key.js +++ b/test/acceptance/surrogate-key.js @@ -40,7 +40,7 @@ describe('Surrogate-Key header', function() { function tableNamesInSurrogateKeyHeader(expectedTableNames, done) { - return function(res) { + return function(err, res) { surrogateKeyHasTables(res.headers['surrogate-key'], expectedTableNames); done(); }; @@ -84,7 +84,7 @@ describe('Surrogate-Key header', function() { it('should not add header for functions', function(done) { var sql = "SELECT format('%s', 'wadus')"; - assert.response(server, createGetRequest(sql), RESPONSE_OK, function(res) { + assert.response(server, createGetRequest(sql), RESPONSE_OK, function(err, res) { assert.ok(!res.headers.hasOwnProperty('surrogate-key'), res.headers['surrogate-key']); done(); }); @@ -92,7 +92,7 @@ describe('Surrogate-Key header', function() { it('should not add header for CDB_QueryTables', function(done) { var sql = "SELECT CDB_QueryTablesText('select * from untitle_table_4')"; - assert.response(server, createGetRequest(sql), RESPONSE_OK, function(res) { + assert.response(server, createGetRequest(sql), RESPONSE_OK, function(err, res) { assert.ok(!res.headers.hasOwnProperty('surrogate-key'), res.headers['surrogate-key']); done(); }); @@ -100,7 +100,7 @@ describe('Surrogate-Key header', function() { it('should not add header for non table results', function(done) { var sql = "SELECT 'wadus'::text"; - assert.response(server, createGetRequest(sql), RESPONSE_OK, function(res) { + assert.response(server, createGetRequest(sql), RESPONSE_OK, function(err, res) { assert.ok(!res.headers.hasOwnProperty('surrogate-key'), res.headers['surrogate-key']); done(); }); diff --git a/test/acceptance/timeout.js b/test/acceptance/timeout.js index 1f3d749e..24464cf1 100644 --- a/test/acceptance/timeout.js +++ b/test/acceptance/timeout.js @@ -29,14 +29,11 @@ it('after configured milliseconds', function(done){ var server = require('../../app/server')(); step( function sendLongQuery() { - var next = this; assert.response(server, { url: '/api/v1/sql?q=SELECT+count(*)+FROM+generate_series(1,100000)', method: 'GET', headers: {host: 'vizzuality.localhost' } - },{}, function(res, err) { - next(err, res); - }); + },{}, this); }, function checkResponse(err/*, res*/) { assert.ok(err); diff --git a/test/acceptance/x-cache-channel.js b/test/acceptance/x-cache-channel.js index 7b5708a3..d6effc9e 100644 --- a/test/acceptance/x-cache-channel.js +++ b/test/acceptance/x-cache-channel.js @@ -39,7 +39,7 @@ describe('X-Cache-Channel header', function() { } function tableNamesInCacheChannelHeader(expectedTableNames, done) { - return function(res) { + return function(err, res) { xCacheChannelHeaderHasTables(res.headers['x-cache-channel'], expectedTableNames); done(); }; @@ -83,7 +83,7 @@ describe('X-Cache-Channel header', function() { it('should not add header for functions', function(done) { var sql = "SELECT format('%s', 'wadus')"; - assert.response(server, createGetRequest(sql), RESPONSE_OK, function(res) { + assert.response(server, createGetRequest(sql), RESPONSE_OK, function(err, res) { assert.ok(!res.headers.hasOwnProperty('x-cache-channel'), res.headers['x-cache-channel']); done(); }); @@ -91,7 +91,7 @@ describe('X-Cache-Channel header', function() { it('should not add header for CDB_QueryTables', function(done) { var sql = "SELECT CDB_QueryTablesText('select * from untitle_table_4')"; - assert.response(server, createGetRequest(sql), RESPONSE_OK, function(res) { + assert.response(server, createGetRequest(sql), RESPONSE_OK, function(err, res) { assert.ok(!res.headers.hasOwnProperty('x-cache-channel'), res.headers['x-cache-channel']); done(); }); @@ -99,7 +99,7 @@ describe('X-Cache-Channel header', function() { it('should not add header for non table results', function(done) { var sql = "SELECT 'wadus'::text"; - assert.response(server, createGetRequest(sql), RESPONSE_OK, function(res) { + assert.response(server, createGetRequest(sql), RESPONSE_OK, function(err, res) { assert.ok(!res.headers.hasOwnProperty('x-cache-channel'), res.headers['x-cache-channel']); done(); }); diff --git a/test/support/assert.js b/test/support/assert.js index 64774ef6..bc855ccc 100644 --- a/test/support/assert.js +++ b/test/support/assert.js @@ -9,7 +9,7 @@ var assert = module.exports = exports = require('assert'); * @param {Server} server * @param {Object} req * @param {Object|Function} res - * @param {String|Function} msg + * @param {String|Function|Object} msg */ assert.response = function(server, req, res, msg){ var port = 5555; @@ -106,7 +106,7 @@ assert.response = function(server, req, res, msg){ request.on('error', function(err){ check(); - callback(null, err); + callback(err); }); request.on('response', function(response){ @@ -163,7 +163,7 @@ assert.response = function(server, req, res, msg){ } } - callback(response); + callback(null, response); }); }); From c47dde1a29843a3930b9e5a673826f403b4c8d95 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 14:42:02 +0200 Subject: [PATCH 19/76] Short hand method --- test/acceptance/app.test.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/acceptance/app.test.js b/test/acceptance/app.test.js index 28bd52d4..98c0eab4 100644 --- a/test/acceptance/app.test.js +++ b/test/acceptance/app.test.js @@ -386,9 +386,7 @@ it('GET /api/v1/sql with INSERT. header based db - should fail', function (done) method: 'GET' }, { status: 400 - }, function (err, res) { - done(err); - }); + }, done); }); // Check results from INSERT From 26400342f3a07b07e1bc2074ece961ee9969ffbe Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 14:42:14 +0200 Subject: [PATCH 20/76] Remove unused param --- test/acceptance/logging.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/acceptance/logging.js b/test/acceptance/logging.js index db332d65..65a308d6 100644 --- a/test/acceptance/logging.js +++ b/test/acceptance/logging.js @@ -105,7 +105,7 @@ describe('Logging SQL query on POST requests', function() { return result; }; - assert.response(server, scenario.request, RESPONSE_OK, function(err, res) { + assert.response(server, scenario.request, RESPONSE_OK, function(err) { assert.ok(!err); assert.equal(called, 1); From 9bd240ef6ca3ecc8a8943073e94bfef97c493e23 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 14:42:24 +0200 Subject: [PATCH 21/76] Remove unused params --- test/acceptance/query-tables-api-cache.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/acceptance/query-tables-api-cache.js b/test/acceptance/query-tables-api-cache.js index 04489778..ee7126ac 100644 --- a/test/acceptance/query-tables-api-cache.js +++ b/test/acceptance/query-tables-api-cache.js @@ -38,7 +38,7 @@ describe('query-tables-api', function() { }; it('should create a key in affected tables cache', function(done) { - assert.response(server, request, RESPONSE_OK, function(err, res) { + assert.response(server, request, RESPONSE_OK, function(err) { assert.ok(!err, err); getCacheStatus(function(err, cacheStatus) { @@ -52,7 +52,7 @@ describe('query-tables-api', function() { }); it('should use cache to retrieve affected tables', function(done) { - assert.response(server, request, RESPONSE_OK, function(err, res) { + assert.response(server, request, RESPONSE_OK, function(err) { assert.ok(!err, err); getCacheStatus(function(err, cacheStatus) { From 3dce6af20fa3505a3eab34fb9961410ab1a6c7b5 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 14:42:35 +0200 Subject: [PATCH 22/76] Remove unused param --- test/acceptance/regressions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/acceptance/regressions.js b/test/acceptance/regressions.js index 9efbb003..c18ea822 100644 --- a/test/acceptance/regressions.js +++ b/test/acceptance/regressions.js @@ -26,7 +26,7 @@ describe('regressions', function() { }; assert.response(server, createRequest('CREATE TABLE "foo.bar" (a int);'), responseOk, - function(err, res) { + function(err) { if (err) { return done(err); } From 90e4600a6cd8e26653f55aade27a54537e1b2221 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 14:42:50 +0200 Subject: [PATCH 23/76] Rename vars to avoid name clash --- test/acceptance/export/shapefile.js | 48 ++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/test/acceptance/export/shapefile.js b/test/acceptance/export/shapefile.js index 232b3894..9efaf104 100644 --- a/test/acceptance/export/shapefile.js +++ b/test/acceptance/export/shapefile.js @@ -24,9 +24,9 @@ it('SHP format, unauthenticated', function(done){ assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); assert.ok(_.contains(zf.names, 'cartodb-query.shp'), 'SHP zipfile does not contain .shp: ' + zf.names); @@ -85,9 +85,9 @@ it('SHP format, unauthenticated, with custom filename', function(done){ assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=myshape.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); assert.ok(_.contains(zf.names, 'myshape.shp'), 'SHP zipfile does not contain .shp: ' + zf.names); @@ -112,9 +112,9 @@ it('SHP format, unauthenticated, with custom, dangerous filename', function(done assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=b_______a.zip/gi.test(cd), 'Unexpected SHP filename: ' + cd); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); assert.ok(_.contains(zf.names, fname + '.shp'), 'SHP zipfile does not contain .shp: ' + zf.names); @@ -137,9 +137,9 @@ it('SHP format, authenticated', function(done){ var cd = res.header('Content-Disposition'); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); assert.ok(_.contains(zf.names, 'cartodb-query.shp'), 'SHP zipfile does not contain .shp: ' + zf.names); @@ -168,9 +168,9 @@ it('SHP format, unauthenticated, with utf8 data', function(done){ },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); var buffer = zf.readFileSync('myshape.dbf'); @@ -243,9 +243,9 @@ it('skipfields controls fields included in SHP output', function(done){ },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); var buffer = zf.readFileSync('myshape.dbf'); @@ -264,9 +264,9 @@ it('SHP format, concurrently', function(done){ assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); assert.ok(_.contains(zf.names, 'cartodb-query.shp'), 'SHP zipfile does not contain .shp: ' + zf.names); @@ -312,9 +312,9 @@ it('point with null first', function(done){ var cd = res.header('Content-Disposition'); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; - var err = fs.writeFileSync(tmpfile, res.body, 'binary'); - if (err) { - return done(err); + var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); + if (writeErr) { + return done(writeErr); } var zf = new zipfile.ZipFile(tmpfile); assert.ok(_.contains(zf.names, 'cartodb-query.shp'), 'SHP zipfile does not contain .shp: ' + zf.names); From a4aba62e9c0ca7ddcec7d3c8c0256d153b0a4206 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 14:51:41 +0200 Subject: [PATCH 24/76] Fix name clash for err vars --- test/acceptance/app.test.js | 72 +++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/test/acceptance/app.test.js b/test/acceptance/app.test.js index 98c0eab4..44fab364 100644 --- a/test/acceptance/app.test.js +++ b/test/acceptance/app.test.js @@ -23,6 +23,10 @@ var step = require('step'); describe('app.test', function() { + var RESPONSE_OK = { + statusCode: 200 + }; + var expected_cache_control = 'no-cache,max-age=31536000,must-revalidate,public'; var expected_rw_cache_control = 'no-cache,max-age=0,must-revalidate,public'; var expected_cache_control_persist = 'public,max-age=31536000'; @@ -164,18 +168,16 @@ it('SELECT from user-specific database', function(done){ url: '/api/v1/sql?q=SELECT+2+as+n', headers: {host: 'cartodb250user.cartodb.com'}, method: 'GET' - },{}, function(err, res) { + }, RESPONSE_OK, function(err, res) { global.settings.db_host = backupDBHost; - var err = null; try { - assert.equal(res.statusCode, 200, res.statusCode + ": " + res.body); - var parsed = JSON.parse(res.body); - assert.equal(parsed.rows.length, 1); - assert.equal(parsed.rows[0].n, 2); + var parsed = JSON.parse(res.body); + assert.equal(parsed.rows.length, 1); + assert.equal(parsed.rows[0].n, 2); } catch (e) { - err = e; + return done(e); } - done(err); + done(); }); }); @@ -187,18 +189,17 @@ it('SELECT with user-specific password', function(done){ url: '/api/v1/sql?q=SELECT+2+as+n&api_key=1234', headers: {host: 'cartodb250user.cartodb.com'}, method: 'GET' - },{}, function(err, res) { + }, RESPONSE_OK, function(err, res) { global.settings.db_user_pass = backupDBUserPass; - var err = null; try { assert.equal(res.statusCode, 200, res.statusCode + ": " + res.body); var parsed = JSON.parse(res.body); assert.equal(parsed.rows.length, 1); assert.equal(parsed.rows[0].n, 2); } catch (e) { - err = e; + return done(e); } - done(err); + return done(); }); }); @@ -1282,7 +1283,6 @@ it('timezone info in JSON output', function(done){ it('notice and warning info in JSON output', function(done){ step( function addRaiseFunction() { - var next = this; assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "create or replace function raise(lvl text, msg text) returns void as $$ begin if lvl = 'notice' " + @@ -1292,13 +1292,7 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(err, res) { - var err = null; - try { - assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body); - } catch (e) { err = e; } - next(err); - }); + }, RESPONSE_OK, this); }, function raiseNotice(err) { assert.ifError(err); @@ -1309,15 +1303,15 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(err, res) { - var err = null; + }, RESPONSE_OK, function(err, res) { try { - assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); assert.ok(parsedBody.hasOwnProperty('notices'), 'Missing notices from result'); assert.equal(parsedBody.notices.length, 1); assert.equal(parsedBody.notices[0], 'hello notice'); - } catch (e) { err = e; } + } catch (e) { + return next(e); + } next(err); }); }, @@ -1330,15 +1324,15 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(err, res) { - var err = null; + }, RESPONSE_OK, function(err, res) { try { - assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); assert.ok(parsedBody.hasOwnProperty('warnings'), 'Missing warnings from result'); assert.equal(parsedBody.warnings.length, 1); assert.equal(parsedBody.warnings[0], 'hello warning'); - } catch (e) { err = e; } + } catch (e) { + return next(e); + } next(err); }); }, @@ -1352,10 +1346,8 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{}, function(err, res) { - var err = null; + }, RESPONSE_OK, function(err, res) { try { - assert.equal(res.statusCode, 200, res.body); var parsedBody = JSON.parse(res.body); assert.ok(parsedBody.hasOwnProperty('warnings'), 'Missing warnings from result'); assert.equal(parsedBody.warnings.length, 1); @@ -1363,12 +1355,13 @@ it('notice and warning info in JSON output', function(done){ assert.ok(parsedBody.hasOwnProperty('notices'), 'Missing notices from result'); assert.equal(parsedBody.notices.length, 1); assert.equal(parsedBody.notices[0], 'hello again notice'); - } catch (e) { err = e; } + } catch (e) { + return next(e); + } next(err); }); }, - function delRaiseFunction(err) { - var next = this; + function delRaiseFunction() { assert.response(server, { url: '/api/v1/sql?' + querystring.stringify({ q: "DROP function raise(text, text)", @@ -1376,16 +1369,15 @@ it('notice and warning info in JSON output', function(done){ }), headers: {host: 'vizzuality.cartodb.com'}, method: 'GET' - },{ }, function(err, res) { + }, RESPONSE_OK, function(err, res) { try { assert.equal(res.statusCode, 200, res.body); JSON.parse(res.body); - } catch (e) { err = new Error(err + ',' + e); } - next(err); + } catch (e) { + err = new Error(err + ',' + e); + } + done(err); }); - }, - function finish(err) { - done(err); } ); }); From abc2f130c91759c06cc26dec75e9751c68f125b0 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:09:27 +0200 Subject: [PATCH 25/76] Migrate to express 4.x series - Remove express logger - Error handler responds with application/[json|javascript] - Fix all tests relying on res.headers - assert.response based on request module --- app.js | 3 +- app/server.js | 18 ++---- app/utils/error_handler.js | 18 ++++-- package.json | 3 +- test/acceptance/app.test.js | 14 ++--- test/acceptance/export/csv.js | 12 ++-- test/acceptance/export/geojson.js | 10 +-- test/acceptance/export/kml.js | 12 ++-- test/acceptance/export/shapefile.js | 16 ++--- test/acceptance/export/svg.js | 24 +++---- test/acceptance/export/topojson.js | 4 +- test/support/assert.js | 98 ++++++++++++++++++++++++++++- 12 files changed, 166 insertions(+), 66 deletions(-) diff --git a/app.js b/app.js index 10261bfb..f981cf5e 100755 --- a/app.js +++ b/app.js @@ -81,7 +81,8 @@ if ( ! global.settings.base_url ) { var version = require("./package").version; var server = require('./app/server')(); -server.listen(global.settings.node_port, global.settings.node_host, function() { +var listener = server.listen(global.settings.node_port, global.settings.node_host); +listener.on('listening', function() { console.info('Using configuration file "%s"', configurationFile); console.log( "CartoDB SQL API %s listening on %s:%s PID=%d (%s)", diff --git a/app/server.js b/app/server.js index 1513f7ed..6ef805d6 100644 --- a/app/server.js +++ b/app/server.js @@ -15,6 +15,7 @@ // var express = require('express'); +var bodyParser = require('body-parser'); var os = require('os'); var Profiler = require('step-profiler'); var StatsD = require('node-statsd').StatsD; @@ -50,7 +51,7 @@ require('./utils/date_to_json'); // jshint maxcomplexity:12 function App() { - var app = express.createServer(); + var app = express(); var redisConfig = { host: global.settings.redis_host, @@ -102,16 +103,6 @@ function App() { } }; app.use(global.log4js.connectLogger(global.log4js.getLogger(), _.defaults(loggerOpts, {level:'info'}))); - } else { - // Express logger uses tokens as described here: http://www.senchalabs.org/connect/logger.html - express.logger.token('sql', function(req) { - return app.getSqlQueryFromRequestBody(req); - }); - app.use(express.logger({ - buffer: true, - format: global.settings.log_format || - ':remote-addr :method :req[Host]:url :status :response-time ms -> :res[Content-Type]' - })); } // Initialize statsD client if requested @@ -172,9 +163,12 @@ function App() { }); } - app.use(express.bodyParser()); + app.use(bodyParser.json()); + app.use(bodyParser.urlencoded({ extended: true })); app.enable('jsonp callback'); app.set("trust proxy", true); + app.disable('x-powered-by'); + app.disable('etag'); // basic routing diff --git a/app/utils/error_handler.js b/app/utils/error_handler.js index e642de31..9d46def5 100644 --- a/app/utils/error_handler.js +++ b/app/utils/error_handler.js @@ -25,14 +25,22 @@ module.exports = function handleException(err, res) { // Force inline content disposition res.header("Content-Disposition", 'inline'); - if ( res.req && res.req.profiler ) { - res.req.profiler.done('finish'); - res.header('X-SQLAPI-Profiler', res.req.profiler.toJSONString()); + var req = res.req; + + if (req && req.profiler ) { + req.profiler.done('finish'); + res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); } - res.send(msg, getStatusError(pgErrorHandler, res.req)); + res.header('Content-Type', 'application/json; charset=utf-8'); + res.status(getStatusError(pgErrorHandler, req)); + if (req.query && req.query.callback) { + res.jsonp(msg); + } else { + res.json(msg); + } - if ( res.req && res.req.profiler ) { + if (req && req.profiler) { res.req.profiler.sendStats(); } }; diff --git a/package.json b/package.json index 7650cbe0..3cf1e083 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,12 @@ "Sandro Santilli " ], "dependencies": { + "body-parser": "~1.14.2", "cartodb-psql": "~0.6.0", "cartodb-query-tables": "0.2.0", "cartodb-redis": "0.13.1", "debug": "2.2.0", - "express": "~2.5.11", + "express": "~4.13.3", "log4js": "cartodb/log4js-node#cdb", "lru-cache": "~2.5.0", "node-statsd": "~0.0.7", diff --git a/test/acceptance/app.test.js b/test/acceptance/app.test.js index 44fab364..4d82e595 100644 --- a/test/acceptance/app.test.js +++ b/test/acceptance/app.test.js @@ -848,9 +848,9 @@ it('GET /api/v1/sql with SQL parameter and no format, ensuring content-dispositi method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var ct = res.header('Content-Type'); + var ct = res.headers['content-type']; assert.ok(/json/.test(ct), 'Default format is not JSON: ' + ct); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^inline/.test(cd), 'Default format is not disposed inline: ' + cd); assert.equal(true, /filename=cartodb-query.json/gi.test(cd), 'Unexpected JSON filename: ' + cd); done(); @@ -865,9 +865,9 @@ it('POST /api/v1/sql with SQL parameter and no format, ensuring content-disposit method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var ct = res.header('Content-Type'); + var ct = res.headers['content-type']; assert.ok(/json/.test(ct), 'Default format is not JSON: ' + ct); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^inline/.test(cd), 'Default format is not disposed inline: ' + cd); assert.equal(true, /filename=cartodb-query.json/gi.test(cd), 'Unexpected JSON filename: ' + cd); done(); @@ -881,9 +881,9 @@ it('GET /api/v1/sql with SQL parameter and no format, but a filename', function( method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var ct = res.header('Content-Type'); + var ct = res.headers['content-type']; assert.ok(/json/.test(ct), 'Default format is not JSON: ' + ct); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'Format with filename is not disposed as attachment: ' + cd); assert.equal(true, /filename=x.json/gi.test(cd), 'Unexpected JSON filename: ' + cd); done(); @@ -959,7 +959,7 @@ it('GET /api/v1/sql ensure cross domain set on errors', function(done){ },{ status: 400 }, function(err, res){ - var cd = res.header('Access-Control-Allow-Origin'); + var cd = res.headers['access-control-allow-origin']; assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8'); assert.deepEqual(res.headers['content-disposition'], 'inline'); assert.equal(cd, '*'); diff --git a/test/acceptance/export/csv.js b/test/acceptance/export/csv.js index d9a46fa0..98ea94a9 100644 --- a/test/acceptance/export/csv.js +++ b/test/acceptance/export/csv.js @@ -18,10 +18,10 @@ it('CSV format', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'CSV is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.csv/gi.test(cd)); - var ct = res.header('Content-Type'); + var ct = res.headers['content-type']; assert.equal(true, /header=present/.test(ct), "CSV doesn't advertise header presence: " + ct); var rows = res.body.split(/\r\n/); @@ -59,10 +59,10 @@ it('CSV format from POST', function(done){ method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'CSV is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.csv/gi.test(cd)); - var ct = res.header('Content-Type'); + var ct = res.headers['content-type']; assert.equal(true, /header=present/.test(ct), "CSV doesn't advertise header presence: " + ct); done(); }); @@ -75,10 +75,10 @@ it('CSV format, custom filename', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'CSV is not disposed as attachment: ' + cd); assert.equal(true, /filename=mycsv.csv/gi.test(cd), cd); - var ct = res.header('Content-Type'); + var ct = res.headers['content-type']; assert.equal(true, /header=present/.test(ct), "CSV doesn't advertise header presence: " + ct); var row0 = res.body.substring(0, res.body.search(/[\n\r]/)).split(','); var checkFields = { name: true, cartodb_id: true, the_geom: true, the_geom_webmercator: true }; diff --git a/test/acceptance/export/geojson.js b/test/acceptance/export/geojson.js index 3d9ab47a..e8a475e4 100644 --- a/test/acceptance/export/geojson.js +++ b/test/acceptance/export/geojson.js @@ -25,7 +25,7 @@ it('GET /api/v1/sql with SQL parameter, ensuring content-disposition set to geoj method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'GEOJSON is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.geojson/gi.test(cd)); done(); @@ -40,7 +40,7 @@ it('POST /api/v1/sql with SQL parameter, ensuring content-disposition set to geo method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'GEOJSON is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.geojson/gi.test(cd)); done(); @@ -54,7 +54,7 @@ it('uses the last format parameter when multiple are used', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /filename=cartodb-query.geojson/gi.test(cd)); done(); }); @@ -67,7 +67,7 @@ it('uses custom filename', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /filename=x.geojson/gi.test(cd), cd); done(); }); @@ -157,7 +157,7 @@ it('null geometries in geojson output', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'GEOJSON is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.geojson/gi.test(cd)); var gjson = JSON.parse(res.body); diff --git a/test/acceptance/export/kml.js b/test/acceptance/export/kml.js index b85d0e45..1e4b7b1e 100644 --- a/test/acceptance/export/kml.js +++ b/test/acceptance/export/kml.js @@ -112,7 +112,7 @@ it('KML format, unauthenticated', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.kml/gi.test(cd), 'Unexpected KML filename: ' + cd); var row0 = res.body; @@ -136,7 +136,7 @@ it('KML format, unauthenticated, POST', function(done){ method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.kml/gi.test(cd), 'Unexpected KML filename: ' + cd); done(); @@ -154,7 +154,7 @@ it('KML format, bigger than 81920 bytes', function(done){ method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.kml/gi.test(cd), 'Unexpected KML filename: ' + cd); assert.ok(res.body.length > 81920, 'KML smaller than expected: ' + res.body.length); @@ -169,7 +169,7 @@ it('KML format, skipfields', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.kml/gi.test(cd), 'Unexpected KML filename: ' + cd); var row0 = res.body; @@ -192,7 +192,7 @@ it('KML format, unauthenticated, custom filename', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'KML is not disposed as attachment: ' + cd); assert.equal(true, /filename=kmltest.kml/gi.test(cd), 'Unexpected KML filename: ' + cd); var name = extractFolderName(res.body); @@ -208,7 +208,7 @@ it('KML format, authenticated', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /filename=cartodb-query.kml/gi.test(cd), 'Unexpected KML filename: ' + cd); done(); }); diff --git a/test/acceptance/export/shapefile.js b/test/acceptance/export/shapefile.js index 9efaf104..ec04a389 100644 --- a/test/acceptance/export/shapefile.js +++ b/test/acceptance/export/shapefile.js @@ -20,7 +20,7 @@ it('SHP format, unauthenticated', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; @@ -47,7 +47,7 @@ it('SHP format, unauthenticated, POST', function(done){ method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd), 'Unexpected SHP filename: ' + cd); done(); @@ -65,7 +65,7 @@ it('SHP format, big size, POST', function(done){ method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd), 'Unexpected SHP filename: ' + cd); assert.ok(res.body.length > 81920, 'SHP smaller than expected: ' + res.body.length); @@ -81,7 +81,7 @@ it('SHP format, unauthenticated, with custom filename', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=myshape.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; @@ -108,7 +108,7 @@ it('SHP format, unauthenticated, with custom, dangerous filename', function(done },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); var fname = "b_______a"; - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=b_______a.zip/gi.test(cd), 'Unexpected SHP filename: ' + cd); var tmpfile = '/tmp/myshape.zip'; @@ -134,7 +134,7 @@ it('SHP format, authenticated', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); @@ -260,7 +260,7 @@ it('SHP format, concurrently', function(done){ var concurrency = 1; var waiting = concurrency; function validate(err, res){ - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SHP is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; @@ -309,7 +309,7 @@ it('point with null first', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /filename=cartodb-query.zip/gi.test(cd)); var tmpfile = '/tmp/myshape.zip'; var writeErr = fs.writeFileSync(tmpfile, res.body, 'binary'); diff --git a/test/acceptance/export/svg.js b/test/acceptance/export/svg.js index 743d7a70..6f9b2e9b 100644 --- a/test/acceptance/export/svg.js +++ b/test/acceptance/export/svg.js @@ -17,9 +17,9 @@ it('GET /api/v1/sql with SVG format', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); - assert.equal(res.header('Content-Type'), 'image/svg+xml; charset=utf-8'); + assert.equal(res.headers['content-type'], 'image/svg+xml; charset=utf-8'); assert.ok( res.body.indexOf('') > 0, res.body ); // TODO: test viewBox done(); @@ -38,10 +38,10 @@ it('POST /api/v1/sql with SVG format', function(done){ method: 'POST' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SVG is not disposed as attachment: ' + cd); assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); - assert.equal(res.header('Content-Type'), 'image/svg+xml; charset=utf-8'); + assert.equal(res.headers['content-type'], 'image/svg+xml; charset=utf-8'); assert.ok( res.body.indexOf('') > 0, res.body ); // TODO: test viewBox done(); @@ -60,9 +60,9 @@ it('GET /api/v1/sql with SVG format and custom filename', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.ok(/filename=mysvg.svg/gi.test(cd), cd); - assert.equal(res.header('Content-Type'), 'image/svg+xml; charset=utf-8'); + assert.equal(res.headers['content-type'], 'image/svg+xml; charset=utf-8'); assert.ok( res.body.indexOf('') > 0, res.body ); // TODO: test viewBox done(); @@ -80,9 +80,9 @@ it('GET /api/v1/sql with SVG format and centered point', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); - assert.equal(res.header('Content-Type'), 'image/svg+xml; charset=utf-8'); + assert.equal(res.headers['content-type'], 'image/svg+xml; charset=utf-8'); assert.ok( res.body.indexOf('cx="0" cy="0"') > 0, res.body ); // TODO: test viewBox // TODO: test radius @@ -102,9 +102,9 @@ it('GET /api/v1/sql with SVG format and trimmed decimals', function(done){ method: 'GET' },{ }, function(err, res){ assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); - assert.equal(res.header('Content-Type'), 'image/svg+xml; charset=utf-8'); + assert.equal(res.headers['content-type'], 'image/svg+xml; charset=utf-8'); assert.ok( res.body.indexOf('') > 0, res.body ); // TODO: test viewBox @@ -115,10 +115,10 @@ it('GET /api/v1/sql with SVG format and trimmed decimals', function(done){ method: 'GET' },{}, function(err, res) { assert.equal(res.statusCode, 200, res.body); - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'SVG is not disposed as attachment: ' + cd); assert.ok(/filename=cartodb-query.svg/gi.test(cd), cd); - assert.equal(res.header('Content-Type'), 'image/svg+xml; charset=utf-8'); + assert.equal(res.headers['content-type'], 'image/svg+xml; charset=utf-8'); assert.ok( res.body.indexOf('') > 0, res.body ); // TODO: test viewBox done(); diff --git a/test/acceptance/export/topojson.js b/test/acceptance/export/topojson.js index de3487ef..8316d86b 100644 --- a/test/acceptance/export/topojson.js +++ b/test/acceptance/export/topojson.js @@ -35,7 +35,7 @@ it('GET two polygons sharing an edge as topojson', function(done){ status: 200 }, function(err, res) { - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'TOPOJSON is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.topojson/gi.test(cd)); var topojson = JSON.parse(res.body); @@ -140,7 +140,7 @@ it('null geometries', function(done){ status: 200 }, function(err, res) { - var cd = res.header('Content-Disposition'); + var cd = res.headers['content-disposition']; assert.equal(true, /^attachment/.test(cd), 'TOPOJSON is not disposed as attachment: ' + cd); assert.equal(true, /filename=cartodb-query.topojson/gi.test(cd)); var topojson = JSON.parse(res.body); diff --git a/test/support/assert.js b/test/support/assert.js index bc855ccc..53323ea4 100644 --- a/test/support/assert.js +++ b/test/support/assert.js @@ -1,6 +1,7 @@ var http = require('http'); var assert = module.exports = exports = require('assert'); +var request = require('request'); /** * Assert response from `server` with @@ -11,7 +12,7 @@ var assert = module.exports = exports = require('assert'); * @param {Object|Function} res * @param {String|Function|Object} msg */ -assert.response = function(server, req, res, msg){ +assert.responseOld = function(server, req, res, msg){ var port = 5555; function check(){ try { @@ -171,6 +172,101 @@ assert.response = function(server, req, res, msg){ } }; +assert.response = function(server, req, res, callback) { + if (!callback) { + callback = res; + res = {}; + } + + var port = 5555, + host = '127.0.0.1'; + + var listeningAttempts = 0; + var listener; + function listen() { + if (listeningAttempts > 25) { + return callback(new Error('Tried too many ports')); + } + listener = server.listen(port, host); + listener.on('error', function() { + port++; + listeningAttempts++; + listen(); + }); + listener.on('listening', onServerListening); + } + + listen(); + + // jshint maxcomplexity:10 + function onServerListening() { + var status = res.status || res.statusCode; + var requestParams = { + url: 'http://' + host + ':' + port + req.url, + method: req.method || 'GET', + headers: req.headers || {}, + timeout: req.timeout || 0, + encoding: req.encoding || 'utf8' + }; + + if (req.body || req.data) { + requestParams.body = req.body || req.data; + } + + request(requestParams, function assert$response$requestHandler(error, response, body) { + listener.close(function() { + if (error) { + return callback(error); + } + + response = response || {}; + response.body = response.body || body; + + // Assert response body + if (res.body) { + var eql = res.body instanceof RegExp ? res.body.test(response.body) : res.body === response.body; + assert.ok( + eql, + colorize('[red]{Invalid response body.}\n' + + ' Expected: [green]{' + res.body + '}\n' + + ' Got: [red]{' + response.body + '}') + ); + } + + // Assert response status + if (typeof status === 'number') { + assert.equal(response.statusCode, status, + colorize('[red]{Invalid response status code.}\n' + + ' Expected: [green]{' + status + '}\n' + + ' Got: [red]{' + response.statusCode + '}\n' + + ' Body: ' + response.body) + ); + } + + // Assert response headers + if (res.headers) { + var keys = Object.keys(res.headers); + for (var i = 0, len = keys.length; i < len; ++i) { + var name = keys[i], + actual = response.headers[name.toLowerCase()], + expected = res.headers[name], + headerEql = expected instanceof RegExp ? expected.test(actual) : expected === actual; + assert.ok(headerEql, + colorize('Invalid response header [bold]{' + name + '}.\n' + + ' Expected: [green]{' + expected + '}\n' + + ' Got: [red]{' + actual + '}') + ); + } + } + + // Callback + callback(null, response); + }); + }); + + } +}; + /** * Colorize the given string using ansi-escape sequences. * Disabled when --boring is set. From 1a20ca0bc3868a2c520fc237ef248221504b75ff Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:09:50 +0200 Subject: [PATCH 26/76] Use listener for test --- test/acceptance/transaction.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/acceptance/transaction.js b/test/acceptance/transaction.js index 9655d846..8a831853 100644 --- a/test/acceptance/transaction.js +++ b/test/acceptance/transaction.js @@ -11,11 +11,12 @@ describe('transaction', function() { var server; before(function(done) { server = require('../../app/server')(); - server.listen(SERVER_PORT, '127.0.0.1', done); + this.listener = server.listen(SERVER_PORT, '127.0.0.1'); + this.listener.on('listening', done); }); after(function(done) { - server.close(done); + this.listener.close(done); }); var sqlRequest = request.defaults({ From 96fc32b24a805791bec3c21ad5898aeafb22b6fe Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:10:09 +0200 Subject: [PATCH 27/76] Concurrency test with assert.response --- test/acceptance/export/kml.js | 60 ++++++++++++----------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/test/acceptance/export/kml.js b/test/acceptance/export/kml.js index 1e4b7b1e..a7a3c6e4 100644 --- a/test/acceptance/export/kml.js +++ b/test/acceptance/export/kml.js @@ -4,8 +4,6 @@ var server = require('../../../app/server')(); var assert = require('../../support/assert'); var querystring = require('querystring'); var libxmljs = require('libxmljs'); -var http = require('http'); -var server_utils = require('../../support/server_utils'); describe('export.kml', function() { @@ -225,48 +223,30 @@ it('KML format, unauthenticated, concurrent requests', function(done){ var concurrency = 4; var waiting = concurrency; - function onResponse(res) { - //console.log("Response started"); - res.body = ''; - //res.setEncoding('binary'); - res.on('data', function(chunk){ res.body += chunk; }); - res.on('end', function(){ - //console.log("Response ended"); - assert.equal(res.statusCode, 200, res.body); - assert.ok(res.body); - var snippet = res.body.substr(0, 5); - assert.equal(snippet, " Date: Mon, 26 Sep 2016 18:10:20 +0200 Subject: [PATCH 28/76] Use .status() API --- app/controllers/health_check_controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/health_check_controller.js b/app/controllers/health_check_controller.js index 29458cf9..a5f84f12 100644 --- a/app/controllers/health_check_controller.js +++ b/app/controllers/health_check_controller.js @@ -24,11 +24,11 @@ HealthCheckController.prototype.handleHealthCheck = function (req, res) { if (err) { response.err = err.message; } - res.send(response, ok ? 200 : 503); + res.status(ok ? 200 : 503).send(response); }); } else { - res.send({enabled: false, ok: true}, 200); + res.status(200).send({enabled: false, ok: true}); } }; From b29358a0ed9645f24c8db67d0daa9d72bbb92eea Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:11:40 +0200 Subject: [PATCH 29/76] Remove old response from assert --- test/support/assert.js | 171 ----------------------------------------- 1 file changed, 171 deletions(-) diff --git a/test/support/assert.js b/test/support/assert.js index 53323ea4..c069b6dd 100644 --- a/test/support/assert.js +++ b/test/support/assert.js @@ -1,177 +1,6 @@ -var http = require('http'); - var assert = module.exports = exports = require('assert'); var request = require('request'); -/** - * Assert response from `server` with - * the given `req` object and `res` assertions object. - * - * @param {Server} server - * @param {Object} req - * @param {Object|Function} res - * @param {String|Function|Object} msg - */ -assert.responseOld = function(server, req, res, msg){ - var port = 5555; - function check(){ - try { - server.__port = server.address().port; - server.__listening = true; - } catch (err) { - process.nextTick(check); - return; - } - if (server.__deferred) { - server.__deferred.forEach(function(args){ - assert.response.apply(assert, args); - }); - server.__deferred = null; - } - } - - // Check that the server is ready or defer - if (!server.fd) { - server.__deferred = server.__deferred || []; - server.listen(server.__port = port++, '127.0.0.1', check); - } else if (!server.__port) { - server.__deferred = server.__deferred || []; - process.nextTick(check); - } - - // The socket was created but is not yet listening, so keep deferring - if (!server.__listening) { - server.__deferred.push(arguments); - return; - } - - // Callback as third or fourth arg - var callback = typeof res === 'function' - ? res - : typeof msg === 'function' - ? msg - : function(){}; - - // Default messate to test title - if (typeof msg === 'function') msg = null; - msg = msg || assert.testTitle; - msg += '. '; - - // Pending responses - server.__pending = server.__pending || 0; - server.__pending++; - - // Create client - if (!server.fd) { - server.listen(server.__port = port++, '127.0.0.1', issue); - } else { - issue(); - } - - function issue(){ - - // Issue request - var timer, - method = req.method || 'GET', - status = res.status || res.statusCode, - data = req.data || req.body, - requestTimeout = req.timeout || 0, - encoding = req.encoding || 'utf8'; - - var request = http.request({ - host: '127.0.0.1', - port: server.__port, - path: req.url, - method: method, - headers: req.headers, - agent: false - }); - - var check = function() { - if (--server.__pending === 0) { - server.close(); - server.__listening = false; - } - }; - - // Timeout - if (requestTimeout) { - timer = setTimeout(function(){ - check(); - delete req.timeout; - request.destroy(); // will trigger 'error' event - }, requestTimeout); - } - - if (data) request.write(data); - - request.on('error', function(err){ - check(); - callback(err); - }); - - request.on('response', function(response){ - response.body = ''; - response.setEncoding(encoding); - response.on('data', function(chunk){ response.body += chunk; }); - response.on('end', function(){ - if (timer) clearTimeout(timer); - - check(); - - // Assert response body - if (res.body !== undefined) { - var eql = res.body instanceof RegExp - ? res.body.test(response.body) - : res.body === response.body; - assert.ok( - eql, - msg + 'Invalid response body.\n' - + ' Expected: ' + res.body + '\n' - + ' Got: ' + response.body - ); - } - - // Assert response status - if (typeof status === 'number') { - assert.equal( - response.statusCode, - status, - msg + colorize('Invalid response status code.\n' - + ' Expected: [green]{' + status + '}\n' - + ' Got: [red]{' + response.statusCode + '}\n' - + ' Response body: ' + response.body) - ); - } - - // Assert response headers - if (res.headers) { - var keys = Object.keys(res.headers); - for (var i = 0, len = keys.length; i < len; ++i) { - var name = keys[i], - actual = response.headers[name.toLowerCase()], - expected = res.headers[name], - eql = expected instanceof RegExp - ? expected.test(actual) - : expected == actual; - assert.ok( - eql, - msg + colorize('Invalid response header [bold]{' + name + '}.\n' - + ' Expected: [green]{' + expected + '}\n' - + ' Got: [red]{' + actual + '}\n' - + ' Response body: ' + response.body) - ); - } - } - - callback(null, response); - }); - }); - - request.end(); - } -}; - assert.response = function(server, req, res, callback) { if (!callback) { callback = res; From 2712d81d50cdffddfac1e46264a96332cb6c1cb4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:13:08 +0200 Subject: [PATCH 30/76] Remove unused server utils --- test/support/server_utils.js | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 test/support/server_utils.js diff --git a/test/support/server_utils.js b/test/support/server_utils.js deleted file mode 100644 index 42f229e8..00000000 --- a/test/support/server_utils.js +++ /dev/null @@ -1,17 +0,0 @@ -var utils = {}; - -utils.startOnNextPort = function(server, issue, start_port) { - - var port = start_port || 5555; - - server.on('error', function(e) { - console.log("Port " + port + " already in use, retrying"); - utils.startOnNextPort(server, issue, port+1); - }); - - server.listen(port, '127.0.0.1', issue); -} - -module.exports = utils; - - From 3cc942b0a2583aa090fa61a9099bb19b7e803a92 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:18:12 +0200 Subject: [PATCH 31/76] Regenerate npm-shrinkwrap.json --- npm-shrinkwrap.json | 384 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 359 insertions(+), 25 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 6b0dbadc..f42481eb 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -2,6 +2,108 @@ "name": "cartodb_sql_api", "version": "1.35.1", "dependencies": { + "body-parser": { + "version": "1.14.2", + "from": "body-parser@>=1.14.2 <1.15.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "dependencies": { + "bytes": { + "version": "2.2.0", + "from": "bytes@2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "http-errors": { + "version": "1.3.1", + "from": "http-errors@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "dependencies": { + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "statuses": { + "version": "1.3.0", + "from": "statuses@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.0.tgz" + } + } + }, + "iconv-lite": { + "version": "0.4.13", + "from": "iconv-lite@0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "dependencies": { + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + } + } + }, + "qs": { + "version": "5.2.0", + "from": "qs@5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz" + }, + "raw-body": { + "version": "2.1.7", + "from": "raw-body@>=2.1.5 <2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "dependencies": { + "bytes": { + "version": "2.4.0", + "from": "bytes@2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" + }, + "unpipe": { + "version": "1.0.0", + "from": "unpipe@1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + } + } + }, + "type-is": { + "version": "1.6.13", + "from": "type-is@>=1.6.10 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", + "dependencies": { + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "mime-types": { + "version": "2.1.12", + "from": "mime-types@>=2.1.2 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", + "dependencies": { + "mime-db": { + "version": "1.24.0", + "from": "mime-db@>=1.24.0 <1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz" + } + } + } + } + } + } + }, "cartodb-psql": { "version": "0.6.1", "from": "cartodb-psql@>=0.6.0 <0.7.0", @@ -56,36 +158,268 @@ } }, "express": { - "version": "2.5.11", - "from": "express@>=2.5.11 <2.6.0", - "resolved": "https://registry.npmjs.org/express/-/express-2.5.11.tgz", + "version": "4.13.4", + "from": "express@>=4.13.3 <4.14.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.13.4.tgz", "dependencies": { - "connect": { - "version": "1.9.2", - "from": "connect@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-1.9.2.tgz", + "accepts": { + "version": "1.2.13", + "from": "accepts@>=1.2.12 <1.3.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", "dependencies": { - "formidable": { - "version": "1.0.17", - "from": "formidable@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz" + "mime-types": { + "version": "2.1.12", + "from": "mime-types@>=2.1.6 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", + "dependencies": { + "mime-db": { + "version": "1.24.0", + "from": "mime-db@>=1.24.0 <1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz" + } + } + }, + "negotiator": { + "version": "0.5.3", + "from": "negotiator@0.5.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz" } } }, - "mime": { - "version": "1.2.4", - "from": "mime@1.2.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.4.tgz" + "array-flatten": { + "version": "1.1.1", + "from": "array-flatten@1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "content-disposition": { + "version": "0.5.1", + "from": "content-disposition@0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + }, + "cookie": { + "version": "0.1.5", + "from": "cookie@0.1.5", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.5.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "escape-html": { + "version": "1.0.3", + "from": "escape-html@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "etag": { + "version": "1.7.0", + "from": "etag@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "finalhandler": { + "version": "0.4.1", + "from": "finalhandler@0.4.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz", + "dependencies": { + "unpipe": { + "version": "1.0.0", + "from": "unpipe@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + } + } + }, + "fresh": { + "version": "0.3.0", + "from": "fresh@0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "merge-descriptors": { + "version": "1.0.1", + "from": "merge-descriptors@1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "dependencies": { + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + } + } + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "path-to-regexp": { + "version": "0.1.7", + "from": "path-to-regexp@0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + }, + "proxy-addr": { + "version": "1.0.10", + "from": "proxy-addr@>=1.0.10 <1.1.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", + "dependencies": { + "forwarded": { + "version": "0.1.0", + "from": "forwarded@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "ipaddr.js": { + "version": "1.0.5", + "from": "ipaddr.js@1.0.5", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz" + } + } }, "qs": { - "version": "0.4.2", - "from": "qs@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-0.4.2.tgz" + "version": "4.0.0", + "from": "qs@4.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz" }, - "mkdirp": { - "version": "0.3.0", - "from": "mkdirp@0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz" + "range-parser": { + "version": "1.0.3", + "from": "range-parser@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz" + }, + "send": { + "version": "0.13.1", + "from": "send@0.13.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.1.tgz", + "dependencies": { + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "http-errors": { + "version": "1.3.1", + "from": "http-errors@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "dependencies": { + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + } + }, + "mime": { + "version": "1.3.4", + "from": "mime@1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "statuses": { + "version": "1.2.1", + "from": "statuses@>=1.2.1 <1.3.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" + } + } + }, + "serve-static": { + "version": "1.10.3", + "from": "serve-static@>=1.10.2 <1.11.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.3.tgz", + "dependencies": { + "send": { + "version": "0.13.2", + "from": "send@0.13.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", + "dependencies": { + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "http-errors": { + "version": "1.3.1", + "from": "http-errors@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "dependencies": { + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + } + }, + "mime": { + "version": "1.3.4", + "from": "mime@1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "statuses": { + "version": "1.2.1", + "from": "statuses@>=1.2.1 <1.3.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" + } + } + } + } + }, + "type-is": { + "version": "1.6.13", + "from": "type-is@>=1.6.6 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", + "dependencies": { + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "mime-types": { + "version": "2.1.12", + "from": "mime-types@>=2.1.6 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", + "dependencies": { + "mime-db": { + "version": "1.24.0", + "from": "mime-db@>=1.24.0 <1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz" + } + } + } + } + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + }, + "vary": { + "version": "1.0.1", + "from": "vary@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz" } } }, @@ -240,7 +574,7 @@ }, "yargs": { "version": "5.0.0", - "from": "yargs@>=5.0.0 <6.0.0", + "from": "yargs@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-5.0.0.tgz", "dependencies": { "cliui": { @@ -250,7 +584,7 @@ "dependencies": { "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.1 <4.0.0", + "from": "strip-ansi@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "dependencies": { "ansi-regex": { @@ -527,7 +861,7 @@ }, "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.1 <4.0.0", + "from": "strip-ansi@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "dependencies": { "ansi-regex": { From 89f9a99e4426b89dcc8037ded836018c142a6cf8 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:26:00 +0200 Subject: [PATCH 32/76] Delete table so suite ends clear --- test/acceptance/regressions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/acceptance/regressions.js b/test/acceptance/regressions.js index c18ea822..f81f08e0 100644 --- a/test/acceptance/regressions.js +++ b/test/acceptance/regressions.js @@ -50,7 +50,9 @@ describe('regressions', function() { var parsedBody = JSON.parse(res.body); assert.equal(parsedBody.total_rows, 2); assert.deepEqual(parsedBody.rows, [{ a: 1 }, { a: 2 }]); - done(); + + // delete table + assert.response(server, createRequest('DROP TABLE "foo.bar"'), responseOk, done); } ); } From 0e03bcd1d39de3ca91da880444ce14303a612024 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 26 Sep 2016 18:26:00 +0200 Subject: [PATCH 33/76] Delete table so suite ends clear --- test/acceptance/regressions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/acceptance/regressions.js b/test/acceptance/regressions.js index c18ea822..f81f08e0 100644 --- a/test/acceptance/regressions.js +++ b/test/acceptance/regressions.js @@ -50,7 +50,9 @@ describe('regressions', function() { var parsedBody = JSON.parse(res.body); assert.equal(parsedBody.total_rows, 2); assert.deepEqual(parsedBody.rows, [{ a: 1 }, { a: 2 }]); - done(); + + // delete table + assert.response(server, createRequest('DROP TABLE "foo.bar"'), responseOk, done); } ); } From aa0ce62a856297f404a18ed29157bec284062727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Thu, 29 Sep 2016 15:09:36 +0200 Subject: [PATCH 34/76] Implement batch logger to log query times when queries are defined with id --- app.js | 2 + batch/batch-logger.js | 86 +++++++++++++++++++++++++++++++++++++++++++ batch/batch.js | 5 ++- batch/index.js | 7 ++-- package.json | 1 + 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 batch/batch-logger.js diff --git a/app.js b/app.js index 10261bfb..bf0719ab 100755 --- a/app.js +++ b/app.js @@ -99,6 +99,8 @@ process.on('SIGHUP', function() { global.logger = global.log4js.getLogger(); console.log('Log files reloaded'); }); + + server.batch.logger.reopenFileStreams(); }); process.on('SIGTERM', function () { diff --git a/batch/batch-logger.js b/batch/batch-logger.js new file mode 100644 index 00000000..0948f94b --- /dev/null +++ b/batch/batch-logger.js @@ -0,0 +1,86 @@ +'use strict'; + +var bunyan = require('bunyan'); +var fs = require('fs'); + +var debug = require('./util/debug')('batch-logger'); + +var JobUtils = require('./models/job_state_machine'); +var jobUtils = new JobUtils(); +var JobFallback = require('./models/job_fallback'); + +function BatchLogger (path) { + this.path = path; + this.stream = this.path ? fs.createWriteStream(this.path, { flags: 'a', encoding: 'utf8' }) : process.stdout; + this.logger = bunyan.createLogger({ + name: 'batch-queries', + streams: [{ + level: 'info', + stream: this.stream + }] + }); +} + +module.exports = BatchLogger; + +BatchLogger.prototype.log = function (job) { + if (!isFinished(job)) { + return; + } + + var queries = job.data.query.query; + + for (var i = 0; i < queries.length; i++) { + var query = queries[i]; + + if (!query.id) { + continue; + } + + var node = parseQueryId(query.id); + var output = { + username: job.data.user, + job: job.data.job_id, + analysis: node.analysis, + node: node.id, + type: node.type, + elapsedTime: calculateElpasedTime(query.started_at, query.ended_at) + }; + + debug('analysis %j', output); + + this.logger.info(output); + } +}; + +function isFinished (job) { + return job instanceof JobFallback && + jobUtils.isFinalStatus(job.data.status) && + (!job.data.fallback_status || jobUtils.isFinalStatus(job.data.fallback_status)); +} + +BatchLogger.prototype.reopenFileStreams = function () { + this.logger.reopenFileStreams(); +}; + +function parseQueryId (queryId) { + var data = queryId.split(':'); + + return { + analysis: data[0], + id: data[1], + type: data[2] + }; +} + +function calculateElpasedTime (started_at, ended_at) { + if (!started_at || !ended_at) { + return; + } + + var start = new Date(started_at); + var end = new Date(ended_at); + var elapsedTimeMilliseconds = end.getTime() - start.getTime(); + + return elapsedTimeMilliseconds; +} diff --git a/batch/batch.js b/batch/batch.js index 3edcec0f..76ea6b39 100644 --- a/batch/batch.js +++ b/batch/batch.js @@ -7,12 +7,13 @@ var forever = require('./util/forever'); var queue = require('queue-async'); var jobStatus = require('./job_status'); -function Batch(jobSubscriber, jobQueuePool, jobRunner, jobService) { +function Batch(jobSubscriber, jobQueuePool, jobRunner, jobService, logger) { EventEmitter.call(this); this.jobSubscriber = jobSubscriber; this.jobQueuePool = jobQueuePool; this.jobRunner = jobRunner; this.jobService = jobService; + this.logger = logger; } util.inherits(Batch, EventEmitter); @@ -90,6 +91,8 @@ Batch.prototype._consumeJobs = function (host, queue, callback) { debug('Job %s %s in %s', job_id, job.data.status, host); } + self.logger.log(job); + self.emit('job:' + job.data.status, job_id); callback(); diff --git a/batch/index.js b/batch/index.js index afe9ea00..53a0e479 100644 --- a/batch/index.js +++ b/batch/index.js @@ -1,6 +1,5 @@ 'use strict'; - var RedisPool = require('redis-mpool'); var _ = require('underscore'); var JobRunner = require('./job_runner'); @@ -14,9 +13,10 @@ var JobPublisher = require('./job_publisher'); var JobQueue = require('./job_queue'); var JobBackend = require('./job_backend'); var JobService = require('./job_service'); +var BatchLogger = require('./batch-logger'); var Batch = require('./batch'); -module.exports = function batchFactory (metadataBackend, redisConfig, statsdClient) { +module.exports = function batchFactory (metadataBackend, redisConfig, statsdClient, loggerPath) { var redisPoolSubscriber = new RedisPool(_.extend(redisConfig, { name: 'batch-subscriber'})); var redisPoolPublisher = new RedisPool(_.extend(redisConfig, { name: 'batch-publisher'})); var queueSeeker = new QueueSeeker(metadataBackend); @@ -30,6 +30,7 @@ module.exports = function batchFactory (metadataBackend, redisConfig, statsdClie var jobCanceller = new JobCanceller(userDatabaseMetadataService); var jobService = new JobService(jobBackend, jobCanceller); var jobRunner = new JobRunner(jobService, jobQueue, queryRunner, statsdClient); + var logger = new BatchLogger(loggerPath); - return new Batch(jobSubscriber, jobQueuePool, jobRunner, jobService); + return new Batch(jobSubscriber, jobQueuePool, jobRunner, jobService, logger); }; diff --git a/package.json b/package.json index 7650cbe0..6c974713 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "Sandro Santilli " ], "dependencies": { + "bunyan": "1.8.1", "cartodb-psql": "~0.6.0", "cartodb-query-tables": "0.2.0", "cartodb-redis": "0.13.1", From ed27b67cec04ed78ab0c1a2ea164328d341d6ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Thu, 29 Sep 2016 15:17:25 +0200 Subject: [PATCH 35/76] Simplified batch logger construction --- batch/batch-logger.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/batch/batch-logger.js b/batch/batch-logger.js index 0948f94b..284091ab 100644 --- a/batch/batch-logger.js +++ b/batch/batch-logger.js @@ -11,12 +11,11 @@ var JobFallback = require('./models/job_fallback'); function BatchLogger (path) { this.path = path; - this.stream = this.path ? fs.createWriteStream(this.path, { flags: 'a', encoding: 'utf8' }) : process.stdout; this.logger = bunyan.createLogger({ name: 'batch-queries', streams: [{ level: 'info', - stream: this.stream + stream: path ? fs.createWriteStream(path, { flags: 'a', encoding: 'utf8' }) : process.stdout }] }); } From 2cce19c3ff7db714352e1ddcece0fcbb69275076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Thu, 29 Sep 2016 15:23:39 +0200 Subject: [PATCH 36/76] Regenerated npm shrinkwrap --- npm-shrinkwrap.json | 135 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 5 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 6b0dbadc..a501d234 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -2,6 +2,131 @@ "name": "cartodb_sql_api", "version": "1.35.1", "dependencies": { + "bunyan": { + "version": "1.8.1", + "from": "bunyan@1.8.1", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.1.tgz", + "dependencies": { + "dtrace-provider": { + "version": "0.6.0", + "from": "dtrace-provider@>=0.6.0 <0.7.0", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.6.0.tgz", + "dependencies": { + "nan": { + "version": "2.4.0", + "from": "nan@>=2.0.8 <3.0.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.4.0.tgz" + } + } + }, + "mv": { + "version": "2.1.1", + "from": "mv@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "ncp": { + "version": "2.0.0", + "from": "ncp@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz" + }, + "rimraf": { + "version": "2.4.5", + "from": "rimraf@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "dependencies": { + "glob": { + "version": "6.0.4", + "from": "glob@>=6.0.1 <7.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "dependencies": { + "inflight": { + "version": "1.0.5", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "minimatch": { + "version": "3.0.3", + "from": "minimatch@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "dependencies": { + "brace-expansion": { + "version": "1.1.6", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + } + } + } + } + }, + "once": { + "version": "1.4.0", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "dependencies": { + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + } + } + }, + "path-is-absolute": { + "version": "1.0.0", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz" + } + } + } + } + } + } + }, + "safe-json-stringify": { + "version": "1.0.3", + "from": "safe-json-stringify@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.3.tgz" + }, + "moment": { + "version": "2.15.1", + "from": "moment@>=2.10.6 <3.0.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.15.1.tgz" + } + } + }, "cartodb-psql": { "version": "0.6.1", "from": "cartodb-psql@>=0.6.0 <0.7.0", @@ -240,7 +365,7 @@ }, "yargs": { "version": "5.0.0", - "from": "yargs@>=5.0.0 <6.0.0", + "from": "yargs@>=5.0.0 <5.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-5.0.0.tgz", "dependencies": { "cliui": { @@ -341,9 +466,9 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "dependencies": { "graceful-fs": { - "version": "4.1.6", + "version": "4.1.9", "from": "graceful-fs@>=4.1.2 <5.0.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz" }, "parse-json": { "version": "2.2.0", @@ -454,9 +579,9 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "dependencies": { "graceful-fs": { - "version": "4.1.6", + "version": "4.1.9", "from": "graceful-fs@>=4.1.2 <5.0.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz" }, "pify": { "version": "2.3.0", From 59e5c10f854ea6445b899f8b63b02c07ceb1b0c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Aubert?= Date: Thu, 29 Sep 2016 15:37:14 +0200 Subject: [PATCH 37/76] Set batch queries log path --- app/server.js | 2 +- config/environments/development.js.example | 1 + config/environments/production.js.example | 1 + config/environments/staging.js.example | 1 + config/environments/test.js.example | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/server.js b/app/server.js index 1513f7ed..1deeba76 100644 --- a/app/server.js +++ b/app/server.js @@ -209,7 +209,7 @@ function App() { var isBatchProcess = process.argv.indexOf('--no-batch') === -1; if (global.settings.environment !== 'test' && isBatchProcess) { - app.batch = batchFactory(metadataBackend, redisConfig, statsd_client); + app.batch = batchFactory(metadataBackend, redisConfig, statsd_client, global.settings.batch_log_filename); app.batch.start(); } diff --git a/config/environments/development.js.example b/config/environments/development.js.example index 6eae0145..3303c71e 100644 --- a/config/environments/development.js.example +++ b/config/environments/development.js.example @@ -30,6 +30,7 @@ module.exports.db_host = 'localhost'; module.exports.db_port = '5432'; module.exports.db_batch_port = '5432'; module.exports.finished_jobs_ttl_in_seconds = 2 * 3600; // 2 hours +module.exports.batch_log_filename = 'logs/batch-queries.log'; // Max database connections in the pool // Subsequent connections will wait for a free slot. // NOTE: not used by OGR-mediated accesses diff --git a/config/environments/production.js.example b/config/environments/production.js.example index 96683a51..6e5ba080 100644 --- a/config/environments/production.js.example +++ b/config/environments/production.js.example @@ -31,6 +31,7 @@ module.exports.db_host = 'localhost'; module.exports.db_port = '6432'; module.exports.db_batch_port = '5432'; module.exports.finished_jobs_ttl_in_seconds = 2 * 3600; // 2 hours +module.exports.batch_log_filename = 'logs/batch-queries.log'; // Max database connections in the pool // Subsequent connections will wait for a free slot.i // NOTE: not used by OGR-mediated accesses diff --git a/config/environments/staging.js.example b/config/environments/staging.js.example index 123e56fd..ce31b032 100644 --- a/config/environments/staging.js.example +++ b/config/environments/staging.js.example @@ -31,6 +31,7 @@ module.exports.db_host = 'localhost'; module.exports.db_port = '6432'; module.exports.db_batch_port = '5432'; module.exports.finished_jobs_ttl_in_seconds = 2 * 3600; // 2 hours +module.exports.batch_log_filename = 'logs/batch-queries.log'; // Max database connections in the pool // Subsequent connections will wait for a free slot. // NOTE: not used by OGR-mediated accesses diff --git a/config/environments/test.js.example b/config/environments/test.js.example index d0ef2236..01df1ebc 100644 --- a/config/environments/test.js.example +++ b/config/environments/test.js.example @@ -28,6 +28,7 @@ module.exports.db_host = 'localhost'; module.exports.db_port = '5432'; module.exports.db_batch_port = '5432'; module.exports.finished_jobs_ttl_in_seconds = 2 * 3600; // 2 hours +module.exports.batch_log_filename = 'logs/batch-queries.log'; // Max database connections in the pool // Subsequent connections will wait for a free slot. // NOTE: not used by OGR-mediated accesses From 60546de14761d6f57de562b5ab72c8b6ba1fc7f3 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 16:44:39 +0200 Subject: [PATCH 38/76] Move log logic to each job --- batch/batch-logger.js | 62 +--------------------------------------- batch/models/job_base.js | 4 +++ 2 files changed, 5 insertions(+), 61 deletions(-) diff --git a/batch/batch-logger.js b/batch/batch-logger.js index 284091ab..02f4f951 100644 --- a/batch/batch-logger.js +++ b/batch/batch-logger.js @@ -3,12 +3,6 @@ var bunyan = require('bunyan'); var fs = require('fs'); -var debug = require('./util/debug')('batch-logger'); - -var JobUtils = require('./models/job_state_machine'); -var jobUtils = new JobUtils(); -var JobFallback = require('./models/job_fallback'); - function BatchLogger (path) { this.path = path; this.logger = bunyan.createLogger({ @@ -23,63 +17,9 @@ function BatchLogger (path) { module.exports = BatchLogger; BatchLogger.prototype.log = function (job) { - if (!isFinished(job)) { - return; - } - - var queries = job.data.query.query; - - for (var i = 0; i < queries.length; i++) { - var query = queries[i]; - - if (!query.id) { - continue; - } - - var node = parseQueryId(query.id); - var output = { - username: job.data.user, - job: job.data.job_id, - analysis: node.analysis, - node: node.id, - type: node.type, - elapsedTime: calculateElpasedTime(query.started_at, query.ended_at) - }; - - debug('analysis %j', output); - - this.logger.info(output); - } + return job.log(this.logger); }; -function isFinished (job) { - return job instanceof JobFallback && - jobUtils.isFinalStatus(job.data.status) && - (!job.data.fallback_status || jobUtils.isFinalStatus(job.data.fallback_status)); -} - BatchLogger.prototype.reopenFileStreams = function () { this.logger.reopenFileStreams(); }; - -function parseQueryId (queryId) { - var data = queryId.split(':'); - - return { - analysis: data[0], - id: data[1], - type: data[2] - }; -} - -function calculateElpasedTime (started_at, ended_at) { - if (!started_at || !ended_at) { - return; - } - - var start = new Date(started_at); - var end = new Date(ended_at); - var elapsedTimeMilliseconds = end.getTime() - start.getTime(); - - return elapsedTimeMilliseconds; -} diff --git a/batch/models/job_base.js b/batch/models/job_base.js index ab6da063..b2143ac0 100644 --- a/batch/models/job_base.js +++ b/batch/models/job_base.js @@ -111,3 +111,7 @@ JobBase.prototype.serialize = function () { return data; }; + +JobBase.prototype.log = function(/*logger*/) { + return false; +}; From 9555a2cbde2c279631118b83718230306d0750f3 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 16:47:37 +0200 Subject: [PATCH 39/76] Bring back log logic for FallbackJob --- batch/models/job_fallback.js | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/batch/models/job_fallback.js b/batch/models/job_fallback.js index 6117cb72..6c710fb3 100644 --- a/batch/models/job_fallback.js +++ b/batch/models/job_fallback.js @@ -7,6 +7,9 @@ var QueryFallback = require('./query/query_fallback'); var MainFallback = require('./query/main_fallback'); var QueryFactory = require('./query/query_factory'); +var JobUtils = require('./job_state_machine'); +var jobUtils = new JobUtils(); + function JobFallback(jobDefinition) { JobBase.call(this, jobDefinition); @@ -206,3 +209,59 @@ JobFallback.prototype.getLastFinishedStatus = function () { return this.isFinalStatus(status) ? status : lastFinished; }.bind(this), jobStatus.DONE); }; + +JobFallback.prototype.log = function(logger) { + if (!isFinished(this)) { + return; + } + + var queries = this.data.query.query; + + for (var i = 0; i < queries.length; i++) { + var query = queries[i]; + + if (!query.id) { + continue; + } + + var node = parseQueryId(query.id); + var output = { + username: this.data.user, + job: this.data.job_id, + analysis: node.analysis, + node: node.id, + type: node.type, + elapsedTime: calculateElpasedTime(query.started_at, query.ended_at) + }; + + logger.info(output); + } + +}; + +function isFinished (job) { + return jobUtils.isFinalStatus(job.data.status) && + (!job.data.fallback_status || jobUtils.isFinalStatus(job.data.fallback_status)); +} + +function parseQueryId (queryId) { + var data = queryId.split(':'); + + return { + analysis: data[0], + id: data[1], + type: data[2] + }; +} + +function calculateElpasedTime (started_at, ended_at) { + if (!started_at || !ended_at) { + return; + } + + var start = new Date(started_at); + var end = new Date(ended_at); + var elapsedTimeMilliseconds = end.getTime() - start.getTime(); + + return elapsedTimeMilliseconds; +} From ba34412ce318de8d8d24742ab668cedf5d703119 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 16:51:34 +0200 Subject: [PATCH 40/76] Return on boolean on log --- batch/models/job_fallback.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/batch/models/job_fallback.js b/batch/models/job_fallback.js index 6c710fb3..59e7ebfe 100644 --- a/batch/models/job_fallback.js +++ b/batch/models/job_fallback.js @@ -212,7 +212,7 @@ JobFallback.prototype.getLastFinishedStatus = function () { JobFallback.prototype.log = function(logger) { if (!isFinished(this)) { - return; + return false; } var queries = this.data.query.query; @@ -237,6 +237,7 @@ JobFallback.prototype.log = function(logger) { logger.info(output); } + return true; }; function isFinished (job) { From 20573a7f67fd3f2713ccabc508f005437b958cf9 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 16:53:00 +0200 Subject: [PATCH 41/76] Always log queries from fallback jobs - Add query id if exists - Only log analyses for expected format - Log with query start and end times --- batch/models/job_fallback.js | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/batch/models/job_fallback.js b/batch/models/job_fallback.js index 59e7ebfe..fabd0c48 100644 --- a/batch/models/job_fallback.js +++ b/batch/models/job_fallback.js @@ -220,20 +220,27 @@ JobFallback.prototype.log = function(logger) { for (var i = 0; i < queries.length; i++) { var query = queries[i]; - if (!query.id) { - continue; - } - - var node = parseQueryId(query.id); var output = { + time: query.started_at, + endtime: query.ended_at, username: this.data.user, job: this.data.job_id, - analysis: node.analysis, - node: node.id, - type: node.type, elapsedTime: calculateElpasedTime(query.started_at, query.ended_at) }; + var queryId = query.id; + + if (queryId) { + output.query_id = queryId; + + var node = parseQueryId(queryId); + if (node) { + output.analysis = node.analysisId; + output.node = node.nodeId; + output.type = node.nodeType; + } + } + logger.info(output); } @@ -248,11 +255,14 @@ function isFinished (job) { function parseQueryId (queryId) { var data = queryId.split(':'); - return { - analysis: data[0], - id: data[1], - type: data[2] - }; + if (data.length === 3) { + return { + analysisId: data[0], + nodeId: data[1], + nodeType: data[2] + }; + } + return null; } function calculateElpasedTime (started_at, ended_at) { From 72fb851db70b5e4017ca6fccf7acc5d7b2bb37b9 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 16:55:33 +0200 Subject: [PATCH 42/76] Fix typo --- batch/models/job_fallback.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/batch/models/job_fallback.js b/batch/models/job_fallback.js index fabd0c48..83d57905 100644 --- a/batch/models/job_fallback.js +++ b/batch/models/job_fallback.js @@ -225,7 +225,7 @@ JobFallback.prototype.log = function(logger) { endtime: query.ended_at, username: this.data.user, job: this.data.job_id, - elapsedTime: calculateElpasedTime(query.started_at, query.ended_at) + elapsed: elapsedTime(query.started_at, query.ended_at) }; var queryId = query.id; @@ -265,14 +265,12 @@ function parseQueryId (queryId) { return null; } -function calculateElpasedTime (started_at, ended_at) { +function elapsedTime (started_at, ended_at) { if (!started_at || !ended_at) { return; } var start = new Date(started_at); var end = new Date(ended_at); - var elapsedTimeMilliseconds = end.getTime() - start.getTime(); - - return elapsedTimeMilliseconds; + return end.getTime() - start.getTime(); } From b0dfe1d509ba7779cd568da8fdb7692b0c98b564 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 17:10:52 +0200 Subject: [PATCH 43/76] Only reload log files if logger exists --- app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index bf0719ab..3dae2f88 100755 --- a/app.js +++ b/app.js @@ -100,7 +100,9 @@ process.on('SIGHUP', function() { console.log('Log files reloaded'); }); - server.batch.logger.reopenFileStreams(); + if (server.batch && server.batch.logger) { + server.batch.logger.reopenFileStreams(); + } }); process.on('SIGTERM', function () { From 1321eeae65a623b3fe3860323d073a4a8f08c632 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 17:12:41 +0200 Subject: [PATCH 44/76] Bump version and update news --- NEWS.md | 8 +++++++- npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index f98eb497..0a41039f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,12 @@ -1.35.1 - 2016-mm-dd +1.36.0 - 2016-mm-dd ------------------- +New features: + * Log queries from batch fallback jobs. + +Enhancements: + * assert.response following callback(err, obj) pattern. + 1.35.0 - 2016-09-15 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a501d234..6380b6e0 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.35.1", + "version": "1.36.0", "dependencies": { "bunyan": { "version": "1.8.1", diff --git a/package.json b/package.json index 6c974713..09a9bb1a 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.35.1", + "version": "1.36.0", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From d685585d5c357ec9c657cddbc5d95c96f8e351e6 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 17:13:02 +0200 Subject: [PATCH 45/76] Release 1.36.0 --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 0a41039f..562e31b2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -1.36.0 - 2016-mm-dd +1.36.0 - 2016-09-30 ------------------- New features: From d7762c9f73979ed83d1672cd14cf3c559f389301 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 17:13:50 +0200 Subject: [PATCH 46/76] Stubs next version --- NEWS.md | 4 ++++ npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 562e31b2..868cc1fd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +1.36.1 - 2016-mm-dd +------------------- + + 1.36.0 - 2016-09-30 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 6380b6e0..06a49bb7 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.36.0", + "version": "1.36.1", "dependencies": { "bunyan": { "version": "1.8.1", diff --git a/package.json b/package.json index 09a9bb1a..bb6ac515 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.36.0", + "version": "1.36.1", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From b269418db4552ba13ae24888e09069297491cc36 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 18:45:15 +0200 Subject: [PATCH 47/76] Tag logs --- batch/models/job_fallback.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/batch/models/job_fallback.js b/batch/models/job_fallback.js index 83d57905..40e18d3d 100644 --- a/batch/models/job_fallback.js +++ b/batch/models/job_fallback.js @@ -230,6 +230,7 @@ JobFallback.prototype.log = function(logger) { var queryId = query.id; + var tag = 'query'; if (queryId) { output.query_id = queryId; @@ -238,10 +239,11 @@ JobFallback.prototype.log = function(logger) { output.analysis = node.analysisId; output.node = node.nodeId; output.type = node.nodeType; + tag = 'analysis'; } } - logger.info(output); + logger.info(output, tag); } return true; From 857ba747d083ec70ea4ce493c447c1828956cf3d Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 18:45:33 +0200 Subject: [PATCH 48/76] Rename --- batch/models/job_fallback.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/batch/models/job_fallback.js b/batch/models/job_fallback.js index 40e18d3d..29779fd8 100644 --- a/batch/models/job_fallback.js +++ b/batch/models/job_fallback.js @@ -220,7 +220,7 @@ JobFallback.prototype.log = function(logger) { for (var i = 0; i < queries.length; i++) { var query = queries[i]; - var output = { + var logEntry = { time: query.started_at, endtime: query.ended_at, username: this.data.user, @@ -232,18 +232,18 @@ JobFallback.prototype.log = function(logger) { var tag = 'query'; if (queryId) { - output.query_id = queryId; + logEntry.query_id = queryId; var node = parseQueryId(queryId); if (node) { - output.analysis = node.analysisId; - output.node = node.nodeId; - output.type = node.nodeType; + logEntry.analysis = node.analysisId; + logEntry.node = node.nodeId; + logEntry.type = node.nodeType; tag = 'analysis'; } } - logger.info(output, tag); + logger.info(logEntry, tag); } return true; From 9099b6ae13a69fa41db36fa58933a3c9b23cd010 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 18:46:34 +0200 Subject: [PATCH 49/76] Update news --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 868cc1fd..09b25626 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ 1.36.1 - 2016-mm-dd ------------------- +Enhancements: + * Tag fallback jobs logs. + 1.36.0 - 2016-09-30 ------------------- From eef302a0b523d0420280a757dac9c2fb42c81628 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 18:46:54 +0200 Subject: [PATCH 50/76] Release 1.36.1 --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 09b25626..b959509f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -1.36.1 - 2016-mm-dd +1.36.1 - 2016-09-30 ------------------- Enhancements: From ccbadf4ab4f68d6d199c5065bac906770465debc Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Fri, 30 Sep 2016 18:48:13 +0200 Subject: [PATCH 51/76] Stubs next version --- NEWS.md | 4 ++++ npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index b959509f..0392711e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +1.36.2 - 2016-mm-dd +------------------- + + 1.36.1 - 2016-09-30 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 06a49bb7..3291204a 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.36.1", + "version": "1.36.2", "dependencies": { "bunyan": { "version": "1.8.1", diff --git a/package.json b/package.json index bb6ac515..ebb295f9 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.36.1", + "version": "1.36.2", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From 6c2db4385cdae84541ca01791fb66012c42581c4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 3 Oct 2016 13:28:13 +0200 Subject: [PATCH 52/76] Batch Queries: use path instead of stream to be able to reopen FD --- NEWS.md | 3 +++ batch/batch-logger.js | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0392711e..399e30d2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ 1.36.2 - 2016-mm-dd ------------------- +Bug fixes: + - Batch Queries logs: use path instead of stream to be able to reopen FD. + 1.36.1 - 2016-09-30 ------------------- diff --git a/batch/batch-logger.js b/batch/batch-logger.js index 02f4f951..775976e7 100644 --- a/batch/batch-logger.js +++ b/batch/batch-logger.js @@ -1,16 +1,20 @@ 'use strict'; var bunyan = require('bunyan'); -var fs = require('fs'); function BatchLogger (path) { + var stream = { + level: 'info' + }; + if (path) { + stream.path = path; + } else { + stream.stream = process.stdout; + } this.path = path; this.logger = bunyan.createLogger({ name: 'batch-queries', - streams: [{ - level: 'info', - stream: path ? fs.createWriteStream(path, { flags: 'a', encoding: 'utf8' }) : process.stdout - }] + streams: [stream] }); } From 51fedbb8c48b545cf5b923af7b73d93634070454 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 3 Oct 2016 13:29:11 +0200 Subject: [PATCH 53/76] Release 1.36.2 --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 399e30d2..4422c58e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -1.36.2 - 2016-mm-dd +1.36.2 - 2016-10-03 ------------------- Bug fixes: From 4f83da3b5c3d176bec5a45f96c2f2227136dca0b Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Mon, 3 Oct 2016 13:36:04 +0200 Subject: [PATCH 54/76] Stubs next version --- NEWS.md | 4 ++++ npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4422c58e..2786b76c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +1.36.3 - 2016-mm-dd +------------------- + + 1.36.2 - 2016-10-03 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 3291204a..0c652fc6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.36.2", + "version": "1.36.3", "dependencies": { "bunyan": { "version": "1.8.1", diff --git a/package.json b/package.json index ebb295f9..d730de17 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.36.2", + "version": "1.36.3", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From fa96ba6892b7c09cbdc5f3e40f6ae090f4f2adbf Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 12:01:08 +0200 Subject: [PATCH 55/76] Bump version and update news --- NEWS.md | 5 ++++- npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2786b76c..347d6a97 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ -1.36.3 - 2016-mm-dd +1.37.0 - 2016-mm-dd ------------------- +Enhancements: + * Migrate to Express.js 4.x series. + 1.36.2 - 2016-10-03 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index aaff4c0a..1ea00329 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.36.3", + "version": "1.37.0", "dependencies": { "body-parser": { "version": "1.14.2", diff --git a/package.json b/package.json index 02e8fafa..d043d932 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.36.3", + "version": "1.37.0", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From 11a9d591ac8adc0df2895388d50cc23fad4ca4c6 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 12:01:33 +0200 Subject: [PATCH 56/76] Release 1.37.0 --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 347d6a97..36b052cf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -1.37.0 - 2016-mm-dd +1.37.0 - 2016-10-04 ------------------- Enhancements: From 0cc6066298c8e2c2ce168532f8a25e6bb68ee041 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 12:02:46 +0200 Subject: [PATCH 57/76] Stubs next version --- NEWS.md | 4 ++++ npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 36b052cf..3d3ab544 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +1.37.1 - 2016-mm-dd +------------------- + + 1.37.0 - 2016-10-04 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1ea00329..33bc34cb 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.37.0", + "version": "1.37.1", "dependencies": { "body-parser": { "version": "1.14.2", diff --git a/package.json b/package.json index d043d932..6fc0d54d 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.37.0", + "version": "1.37.1", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From 3b6bc14d1748e668b2e49a978f7c1beadb07cf6c Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 13:19:29 +0200 Subject: [PATCH 58/76] Increment errors on err --- app/controllers/job_controller.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index 7da6be70..c90b9414 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -96,6 +96,7 @@ JobController.prototype.cancelJob = function (req, res) { }, function handleResponse(err, result) { if ( err ) { + self.statsdClient.increment('sqlapi.job.error'); return handleException(err, res); } @@ -115,11 +116,7 @@ JobController.prototype.cancelJob = function (req, res) { res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); } - if ( err ) { - self.statsdClient.increment('sqlapi.job.error'); - } else { - self.statsdClient.increment('sqlapi.job.success'); - } + self.statsdClient.increment('sqlapi.job.success'); res.send(result.job); } @@ -171,6 +168,7 @@ JobController.prototype.getJob = function (req, res) { }, function handleResponse(err, result) { if ( err ) { + self.statsdClient.increment('sqlapi.job.error'); return handleException(err, res); } @@ -190,11 +188,7 @@ JobController.prototype.getJob = function (req, res) { res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); } - if ( err ) { - self.statsdClient.increment('sqlapi.job.error'); - } else { - self.statsdClient.increment('sqlapi.job.success'); - } + self.statsdClient.increment('sqlapi.job.success'); res.send(result.job); } @@ -252,6 +246,7 @@ JobController.prototype.createJob = function (req, res) { }, function handleResponse(err, result) { if ( err ) { + self.statsdClient.increment('sqlapi.job.error'); return handleException(err, res); } @@ -271,11 +266,7 @@ JobController.prototype.createJob = function (req, res) { res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); } - if ( err ) { - self.statsdClient.increment('sqlapi.job.error'); - } else { - self.statsdClient.increment('sqlapi.job.success'); - } + self.statsdClient.increment('sqlapi.job.success'); console.info(JSON.stringify({ type: 'sql_api_batch_job', From cb9db0c4cb972fad00f4fafe947eb48d37b58580 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 14:40:04 +0200 Subject: [PATCH 59/76] Make request.profiler always available --- app/server.js | 14 +++++----- app/stats/profiler-proxy.js | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 app/stats/profiler-proxy.js diff --git a/app/server.js b/app/server.js index c3bdf4f4..f070c7f9 100644 --- a/app/server.js +++ b/app/server.js @@ -17,7 +17,7 @@ var express = require('express'); var bodyParser = require('body-parser'); var os = require('os'); -var Profiler = require('step-profiler'); +var Profiler = require('./stats/profiler-proxy'); var StatsD = require('node-statsd').StatsD; var _ = require('underscore'); var LRU = require('lru-cache'); @@ -147,12 +147,14 @@ function App() { app.use(cors()); // Use step-profiler - if ( global.settings.useProfiler ) { - app.use(function(req, res, next) { - req.profiler = new Profiler({statsd_client:statsd_client}); + app.use(function(req, res, next) { + var profile = global.settings.useProfiler; + req.profiler = new Profiler({ + profile: profile, + statsd_client: statsd_client + }); next(); - }); - } + }); // Set connection timeout if ( global.settings.hasOwnProperty('node_socket_timeout') ) { diff --git a/app/stats/profiler-proxy.js b/app/stats/profiler-proxy.js new file mode 100644 index 00000000..1e1f91e7 --- /dev/null +++ b/app/stats/profiler-proxy.js @@ -0,0 +1,53 @@ +var Profiler = require('step-profiler'); + +/** + * Proxy to encapsulate node-step-profiler module so there is no need to check if there is an instance + */ +function ProfilerProxy(opts) { + this.profile = !!opts.profile; + + this.profiler = null; + if (!!opts.profile) { + this.profiler = new Profiler({statsd_client: opts.statsd_client}); + } +} + +ProfilerProxy.prototype.done = function(what) { + if (this.profile) { + this.profiler.done(what); + } +}; + +ProfilerProxy.prototype.end = function() { + if (this.profile) { + this.profiler.end(); + } +}; + +ProfilerProxy.prototype.start = function(what) { + if (this.profile) { + this.profiler.start(what); + } +}; + +ProfilerProxy.prototype.add = function(what) { + if (this.profile) { + this.profiler.add(what || {}); + } +}; + +ProfilerProxy.prototype.sendStats = function() { + if (this.profile) { + this.profiler.sendStats(); + } +}; + +ProfilerProxy.prototype.toString = function() { + return this.profile ? this.profiler.toString() : ""; +}; + +ProfilerProxy.prototype.toJSONString = function() { + return this.profile ? this.profiler.toJSONString() : "{}"; +}; + +module.exports = ProfilerProxy; From 2edc7505e7e53220742b7cb52317ffd97f6acd2e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 15:08:31 +0200 Subject: [PATCH 60/76] Do not condition req.profiler --- app/controllers/job_controller.js | 60 +++++++++++-------------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index c90b9414..769ceed3 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -58,10 +58,8 @@ JobController.prototype.cancelJob = function (req, res) { var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken var cdbUsername = cdbReq.userByReq(req); - if ( req.profiler ) { - req.profiler.start('sqlapi.job'); - req.profiler.done('init'); - } + req.profiler.start('sqlapi.job'); + req.profiler.done('init'); step( function getUserDBInfo() { @@ -79,9 +77,7 @@ JobController.prototype.cancelJob = function (req, res) { var next = this; - if ( req.profiler ) { - req.profiler.done('setDBAuth'); - } + req.profiler.done('setDBAuth'); self.jobService.cancel(job_id, function (err, job) { if (err) { @@ -108,13 +104,11 @@ JobController.prototype.cancelJob = function (req, res) { res.header('X-Served-By-DB-Host', result.host); } - if ( req.profiler ) { - req.profiler.done('cancelJob'); - req.profiler.end(); - req.profiler.sendStats(); + req.profiler.done('cancelJob'); + req.profiler.end(); + req.profiler.sendStats(); - res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); - } + res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); self.statsdClient.increment('sqlapi.job.success'); @@ -130,10 +124,8 @@ JobController.prototype.getJob = function (req, res) { var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken var cdbUsername = cdbReq.userByReq(req); - if ( req.profiler ) { - req.profiler.start('sqlapi.job'); - req.profiler.done('init'); - } + req.profiler.start('sqlapi.job'); + req.profiler.done('init'); step( function getUserDBInfo() { @@ -151,9 +143,7 @@ JobController.prototype.getJob = function (req, res) { var next = this; - if ( req.profiler ) { - req.profiler.done('setDBAuth'); - } + req.profiler.done('setDBAuth'); self.jobService.get(job_id, function (err, job) { if (err) { @@ -180,13 +170,11 @@ JobController.prototype.getJob = function (req, res) { res.header('X-Served-By-DB-Host', result.host); } - if ( req.profiler ) { - req.profiler.done('getJob'); - req.profiler.end(); - req.profiler.sendStats(); + req.profiler.done('getJob'); + req.profiler.end(); + req.profiler.sendStats(); - res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); - } + res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); self.statsdClient.increment('sqlapi.job.success'); @@ -202,10 +190,8 @@ JobController.prototype.createJob = function (req, res) { var sql = (params.query === "" || _.isUndefined(params.query)) ? null : params.query; var cdbUsername = cdbReq.userByReq(req); - if ( req.profiler ) { - req.profiler.start('sqlapi.job'); - req.profiler.done('init'); - } + req.profiler.start('sqlapi.job'); + req.profiler.done('init'); step( function getUserDBInfo() { @@ -223,9 +209,7 @@ JobController.prototype.createJob = function (req, res) { var next = this; - if ( req.profiler ) { - req.profiler.done('setDBAuth'); - } + req.profiler.done('setDBAuth'); var data = { user: cdbUsername, @@ -258,13 +242,11 @@ JobController.prototype.createJob = function (req, res) { res.header('X-Served-By-DB-Host', result.host); } - if ( req.profiler ) { - req.profiler.done('persistJob'); - req.profiler.end(); - req.profiler.sendStats(); + req.profiler.done('persistJob'); + req.profiler.end(); + req.profiler.sendStats(); - res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); - } + res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); self.statsdClient.increment('sqlapi.job.success'); From b139b9ab2101bea413d8b691cf46bf129e92a0a5 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 15:12:46 +0200 Subject: [PATCH 61/76] Add context object in all requests --- app/server.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/server.js b/app/server.js index f070c7f9..a5e78719 100644 --- a/app/server.js +++ b/app/server.js @@ -147,7 +147,9 @@ function App() { app.use(cors()); // Use step-profiler - app.use(function(req, res, next) { + app.use(function bootstrap$prepareRequestResponse(req, res, next) { + req.context = req.context || {}; + var profile = global.settings.useProfiler; req.profiler = new Profiler({ profile: profile, From 20f50d988e3e98d70b703b8a248b267b2f709387 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 15:19:31 +0200 Subject: [PATCH 62/76] Use user middleware in job controller --- app/controllers/job_controller.js | 22 +++++++++------------- app/middlewares/user.js | 7 +++++++ 2 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 app/middlewares/user.js diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index 769ceed3..6a5171a5 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -5,10 +5,9 @@ var step = require('step'); var assert = require('assert'); var util = require('util'); +var userMiddleware = require('../middlewares/user'); var AuthApi = require('../auth/auth_api'); -var CdbRequest = require('../models/cartodb_request'); var handleException = require('../utils/error_handler'); -var cdbReq = new CdbRequest(); var ONE_KILOBYTE_IN_BYTES = 1024; var MAX_LIMIT_QUERY_SIZE_IN_KB = 8; @@ -46,9 +45,9 @@ module.exports.MAX_LIMIT_QUERY_SIZE_IN_BYTES = MAX_LIMIT_QUERY_SIZE_IN_BYTES; module.exports.getMaxSizeErrorMessage = getMaxSizeErrorMessage; JobController.prototype.route = function (app) { - app.post(global.settings.base_url + '/sql/job', bodyPayloadSizeMiddleware, this.createJob.bind(this)); - app.get(global.settings.base_url + '/sql/job/:job_id', this.getJob.bind(this)); - app.delete(global.settings.base_url + '/sql/job/:job_id', this.cancelJob.bind(this)); + app.post(global.settings.base_url + '/sql/job', bodyPayloadSizeMiddleware, userMiddleware, this.createJob.bind(this)); + app.get(global.settings.base_url + '/sql/job/:job_id', userMiddleware, this.getJob.bind(this)); + app.delete(global.settings.base_url + '/sql/job/:job_id', userMiddleware, this.cancelJob.bind(this)); }; JobController.prototype.cancelJob = function (req, res) { @@ -56,7 +55,6 @@ JobController.prototype.cancelJob = function (req, res) { var job_id = req.params.job_id; var body = (req.body) ? req.body : {}; var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken - var cdbUsername = cdbReq.userByReq(req); req.profiler.start('sqlapi.job'); req.profiler.done('init'); @@ -66,7 +64,7 @@ JobController.prototype.cancelJob = function (req, res) { var next = this; var authApi = new AuthApi(req, params); - self.userDatabaseService.getConnectionParams(authApi, cdbUsername, next); + self.userDatabaseService.getConnectionParams(authApi, req.context.user, next); }, function cancelJob(err, userDatabase) { assert.ifError(err); @@ -122,7 +120,6 @@ JobController.prototype.getJob = function (req, res) { var job_id = req.params.job_id; var body = (req.body) ? req.body : {}; var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken - var cdbUsername = cdbReq.userByReq(req); req.profiler.start('sqlapi.job'); req.profiler.done('init'); @@ -132,7 +129,7 @@ JobController.prototype.getJob = function (req, res) { var next = this; var authApi = new AuthApi(req, params); - self.userDatabaseService.getConnectionParams(authApi, cdbUsername, next); + self.userDatabaseService.getConnectionParams(authApi, req.context.user, next); }, function getJob(err, userDatabase) { assert.ifError(err); @@ -188,7 +185,6 @@ JobController.prototype.createJob = function (req, res) { var body = (req.body) ? req.body : {}; var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken var sql = (params.query === "" || _.isUndefined(params.query)) ? null : params.query; - var cdbUsername = cdbReq.userByReq(req); req.profiler.start('sqlapi.job'); req.profiler.done('init'); @@ -198,7 +194,7 @@ JobController.prototype.createJob = function (req, res) { var next = this; var authApi = new AuthApi(req, params); - self.userDatabaseService.getConnectionParams(authApi, cdbUsername, next); + self.userDatabaseService.getConnectionParams(authApi, req.context.user, next); }, function persistJob(err, userDatabase) { assert.ifError(err); @@ -212,7 +208,7 @@ JobController.prototype.createJob = function (req, res) { req.profiler.done('setDBAuth'); var data = { - user: cdbUsername, + user: req.context.user, query: sql, host: userDatabase.host }; @@ -252,7 +248,7 @@ JobController.prototype.createJob = function (req, res) { console.info(JSON.stringify({ type: 'sql_api_batch_job', - username: cdbUsername, + username: req.context.user, action: 'create', job_id: result.job.job_id })); diff --git a/app/middlewares/user.js b/app/middlewares/user.js new file mode 100644 index 00000000..57e9d8b5 --- /dev/null +++ b/app/middlewares/user.js @@ -0,0 +1,7 @@ +var CdbRequest = require('../models/cartodb_request'); +var cdbRequest = new CdbRequest(); + +module.exports = function userMiddleware(req, res, next) { + req.context.user = cdbRequest.userByReq(req); + next(); +}; From 7b7d651d8fe4ce199547c418e7d0f19e493330a4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 15:40:56 +0200 Subject: [PATCH 63/76] DRY while authenticating requests --- app/controllers/job_controller.js | 92 ++++++------------------ app/middlewares/authenticated-request.js | 35 +++++++++ 2 files changed, 58 insertions(+), 69 deletions(-) create mode 100644 app/middlewares/authenticated-request.js diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index 6a5171a5..5003ec1d 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -2,11 +2,10 @@ var _ = require('underscore'); var step = require('step'); -var assert = require('assert'); var util = require('util'); var userMiddleware = require('../middlewares/user'); -var AuthApi = require('../auth/auth_api'); +var authenticatedMiddleware = require('../middlewares/authenticated-request'); var handleException = require('../utils/error_handler'); var ONE_KILOBYTE_IN_BYTES = 1024; @@ -45,38 +44,30 @@ module.exports.MAX_LIMIT_QUERY_SIZE_IN_BYTES = MAX_LIMIT_QUERY_SIZE_IN_BYTES; module.exports.getMaxSizeErrorMessage = getMaxSizeErrorMessage; JobController.prototype.route = function (app) { - app.post(global.settings.base_url + '/sql/job', bodyPayloadSizeMiddleware, userMiddleware, this.createJob.bind(this)); - app.get(global.settings.base_url + '/sql/job/:job_id', userMiddleware, this.getJob.bind(this)); - app.delete(global.settings.base_url + '/sql/job/:job_id', userMiddleware, this.cancelJob.bind(this)); + app.post( + global.settings.base_url + '/sql/job', + bodyPayloadSizeMiddleware, userMiddleware, authenticatedMiddleware(this.userDatabaseService), + this.createJob.bind(this) + ); + app.get( + global.settings.base_url + '/sql/job/:job_id', + userMiddleware, authenticatedMiddleware(this.userDatabaseService), + this.getJob.bind(this) + ); + app.delete( + global.settings.base_url + '/sql/job/:job_id', + userMiddleware, authenticatedMiddleware(this.userDatabaseService), + this.cancelJob.bind(this) + ); }; JobController.prototype.cancelJob = function (req, res) { var self = this; var job_id = req.params.job_id; - var body = (req.body) ? req.body : {}; - var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken - - req.profiler.start('sqlapi.job'); - req.profiler.done('init'); step( - function getUserDBInfo() { + function cancelJob() { var next = this; - var authApi = new AuthApi(req, params); - - self.userDatabaseService.getConnectionParams(authApi, req.context.user, next); - }, - function cancelJob(err, userDatabase) { - assert.ifError(err); - - if (!userDatabase.authenticated) { - throw new Error('permission denied'); - } - - var next = this; - - req.profiler.done('setDBAuth'); - self.jobService.cancel(job_id, function (err, job) { if (err) { return next(err); @@ -84,7 +75,7 @@ JobController.prototype.cancelJob = function (req, res) { next(null, { job: job.serialize(), - host: userDatabase.host + host: req.context.userDatabase.host }); }); }, @@ -118,30 +109,10 @@ JobController.prototype.cancelJob = function (req, res) { JobController.prototype.getJob = function (req, res) { var self = this; var job_id = req.params.job_id; - var body = (req.body) ? req.body : {}; - var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken - - req.profiler.start('sqlapi.job'); - req.profiler.done('init'); step( - function getUserDBInfo() { + function getJob() { var next = this; - var authApi = new AuthApi(req, params); - - self.userDatabaseService.getConnectionParams(authApi, req.context.user, next); - }, - function getJob(err, userDatabase) { - assert.ifError(err); - - if (!userDatabase.authenticated) { - throw new Error('permission denied'); - } - - var next = this; - - req.profiler.done('setDBAuth'); - self.jobService.get(job_id, function (err, job) { if (err) { return next(err); @@ -149,7 +120,7 @@ JobController.prototype.getJob = function (req, res) { next(null, { job: job.serialize(), - host: userDatabase.host + host: req.context.userDatabase.host }); }); }, @@ -186,31 +157,14 @@ JobController.prototype.createJob = function (req, res) { var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken var sql = (params.query === "" || _.isUndefined(params.query)) ? null : params.query; - req.profiler.start('sqlapi.job'); - req.profiler.done('init'); - step( - function getUserDBInfo() { + function persistJob() { var next = this; - var authApi = new AuthApi(req, params); - - self.userDatabaseService.getConnectionParams(authApi, req.context.user, next); - }, - function persistJob(err, userDatabase) { - assert.ifError(err); - - if (!userDatabase.authenticated) { - throw new Error('permission denied'); - } - - var next = this; - - req.profiler.done('setDBAuth'); var data = { user: req.context.user, query: sql, - host: userDatabase.host + host: req.context.userDatabase.host }; self.jobService.create(data, function (err, job) { @@ -220,7 +174,7 @@ JobController.prototype.createJob = function (req, res) { next(null, { job: job.serialize(), - host: userDatabase.host + host: req.context.userDatabase.host }); }); }, diff --git a/app/middlewares/authenticated-request.js b/app/middlewares/authenticated-request.js new file mode 100644 index 00000000..05f20f59 --- /dev/null +++ b/app/middlewares/authenticated-request.js @@ -0,0 +1,35 @@ +'use strict'; + +var _ = require('underscore'); +var AuthApi = require('../auth/auth_api'); +var handleException = require('../utils/error_handler'); + +function authenticatedMiddleware(userDatabaseService) { + return function middleware(req, res, next) { + req.profiler.start('sqlapi.job'); + req.profiler.done('init'); + + var body = (req.body) ? req.body : {}; + // clone so don't modify req.params or req.body so oauth is not broken + var params = _.extend({}, req.query, body); + + var authApi = new AuthApi(req, params); + userDatabaseService.getConnectionParams(authApi, req.context.user, function cancelJob(err, userDatabase) { + req.profiler.done('setDBAuth'); + + if (err) { + return handleException(err, res); + } + + if (!userDatabase.authenticated) { + return handleException(new Error('permission denied'), res); + } + + req.context.userDatabase = userDatabase; + + return next(null); + }); + }; +} + +module.exports = authenticatedMiddleware; From c32a2199faaa6bcfcf6c3fd76758f864132cfbaf Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 15:43:19 +0200 Subject: [PATCH 64/76] Use request bootstrapper to add host header --- app/controllers/job_controller.js | 12 ------------ app/controllers/query_controller.js | 3 --- app/server.js | 4 ++++ 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index 5003ec1d..1f7f7aa1 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -85,10 +85,6 @@ JobController.prototype.cancelJob = function (req, res) { return handleException(err, res); } - if (global.settings.api_hostname) { - res.header('X-Served-By-Host', global.settings.api_hostname); - } - if (result.host) { res.header('X-Served-By-DB-Host', result.host); } @@ -130,10 +126,6 @@ JobController.prototype.getJob = function (req, res) { return handleException(err, res); } - if (global.settings.api_hostname) { - res.header('X-Served-By-Host', global.settings.api_hostname); - } - if (result.host) { res.header('X-Served-By-DB-Host', result.host); } @@ -184,10 +176,6 @@ JobController.prototype.createJob = function (req, res) { return handleException(err, res); } - if (global.settings.api_hostname) { - res.header('X-Served-By-Host', global.settings.api_hostname); - } - if (result.host) { res.header('X-Served-By-DB-Host', result.host); } diff --git a/app/controllers/query_controller.js b/app/controllers/query_controller.js index 8e09b072..c287d2ed 100644 --- a/app/controllers/query_controller.js +++ b/app/controllers/query_controller.js @@ -228,9 +228,6 @@ QueryController.prototype.handleQuery = function (req, res) { }; } - if (global.settings.api_hostname) { - res.header('X-Served-By-Host', global.settings.api_hostname); - } if (dbopts.host) { res.header('X-Served-By-DB-Host', dbopts.host); } diff --git a/app/server.js b/app/server.js index a5e78719..4a9be504 100644 --- a/app/server.js +++ b/app/server.js @@ -150,6 +150,10 @@ function App() { app.use(function bootstrap$prepareRequestResponse(req, res, next) { req.context = req.context || {}; + if (global.settings.api_hostname) { + res.header('X-Served-By-Host', global.settings.api_hostname); + } + var profile = global.settings.useProfiler; req.profiler = new Profiler({ profile: profile, From 05cbd55b958585d728898bf91c6a10636bb58377 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 15:50:39 +0200 Subject: [PATCH 65/76] Use db host from request's context --- app/controllers/job_controller.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index 1f7f7aa1..065f4689 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -74,8 +74,7 @@ JobController.prototype.cancelJob = function (req, res) { } next(null, { - job: job.serialize(), - host: req.context.userDatabase.host + job: job.serialize() }); }); }, @@ -85,9 +84,7 @@ JobController.prototype.cancelJob = function (req, res) { return handleException(err, res); } - if (result.host) { - res.header('X-Served-By-DB-Host', result.host); - } + res.header('X-Served-By-DB-Host', req.context.userDatabase.host); req.profiler.done('cancelJob'); req.profiler.end(); @@ -115,8 +112,7 @@ JobController.prototype.getJob = function (req, res) { } next(null, { - job: job.serialize(), - host: req.context.userDatabase.host + job: job.serialize() }); }); }, @@ -126,9 +122,7 @@ JobController.prototype.getJob = function (req, res) { return handleException(err, res); } - if (result.host) { - res.header('X-Served-By-DB-Host', result.host); - } + res.header('X-Served-By-DB-Host', req.context.userDatabase.host); req.profiler.done('getJob'); req.profiler.end(); @@ -165,8 +159,7 @@ JobController.prototype.createJob = function (req, res) { } next(null, { - job: job.serialize(), - host: req.context.userDatabase.host + job: job.serialize() }); }); }, @@ -176,9 +169,7 @@ JobController.prototype.createJob = function (req, res) { return handleException(err, res); } - if (result.host) { - res.header('X-Served-By-DB-Host', result.host); - } + res.header('X-Served-By-DB-Host', req.context.userDatabase.host); req.profiler.done('persistJob'); req.profiler.end(); From 19c9bec633320f46a8f9749f34ae7024747f4031 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 15:57:13 +0200 Subject: [PATCH 66/76] Callback with job --- app/controllers/job_controller.js | 48 +++++++------------------------ 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index 065f4689..a40be61e 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -67,18 +67,9 @@ JobController.prototype.cancelJob = function (req, res) { step( function cancelJob() { - var next = this; - self.jobService.cancel(job_id, function (err, job) { - if (err) { - return next(err); - } - - next(null, { - job: job.serialize() - }); - }); + self.jobService.cancel(job_id, this); }, - function handleResponse(err, result) { + function handleResponse(err, job) { if ( err ) { self.statsdClient.increment('sqlapi.job.error'); return handleException(err, res); @@ -94,7 +85,7 @@ JobController.prototype.cancelJob = function (req, res) { self.statsdClient.increment('sqlapi.job.success'); - res.send(result.job); + res.send(job.serialize()); } ); }; @@ -105,18 +96,9 @@ JobController.prototype.getJob = function (req, res) { step( function getJob() { - var next = this; - self.jobService.get(job_id, function (err, job) { - if (err) { - return next(err); - } - - next(null, { - job: job.serialize() - }); - }); + self.jobService.get(job_id, this); }, - function handleResponse(err, result) { + function handleResponse(err, job) { if ( err ) { self.statsdClient.increment('sqlapi.job.error'); return handleException(err, res); @@ -132,7 +114,7 @@ JobController.prototype.getJob = function (req, res) { self.statsdClient.increment('sqlapi.job.success'); - res.send(result.job); + res.send(job.serialize()); } ); }; @@ -145,25 +127,15 @@ JobController.prototype.createJob = function (req, res) { step( function persistJob() { - var next = this; - var data = { user: req.context.user, query: sql, host: req.context.userDatabase.host }; - self.jobService.create(data, function (err, job) { - if (err) { - return next(err); - } - - next(null, { - job: job.serialize() - }); - }); + self.jobService.create(data, this); }, - function handleResponse(err, result) { + function handleResponse(err, job) { if ( err ) { self.statsdClient.increment('sqlapi.job.error'); return handleException(err, res); @@ -183,10 +155,10 @@ JobController.prototype.createJob = function (req, res) { type: 'sql_api_batch_job', username: req.context.user, action: 'create', - job_id: result.job.job_id + job_id: job.job_id })); - res.status(201).send(result.job); + res.status(201).send(job.serialize()); } ); }; From 2a2a54a073d4c9f1637993b405ed17d1c86fc0bc Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Tue, 4 Oct 2016 16:07:13 +0200 Subject: [PATCH 67/76] DRY in job response handler --- app/controllers/job_controller.js | 126 +++++++++--------------------- 1 file changed, 37 insertions(+), 89 deletions(-) diff --git a/app/controllers/job_controller.js b/app/controllers/job_controller.js index a40be61e..cee91a41 100644 --- a/app/controllers/job_controller.js +++ b/app/controllers/job_controller.js @@ -1,7 +1,6 @@ 'use strict'; var _ = require('underscore'); -var step = require('step'); var util = require('util'); var userMiddleware = require('../middlewares/user'); @@ -62,103 +61,52 @@ JobController.prototype.route = function (app) { }; JobController.prototype.cancelJob = function (req, res) { - var self = this; - var job_id = req.params.job_id; - - step( - function cancelJob() { - self.jobService.cancel(job_id, this); - }, - function handleResponse(err, job) { - if ( err ) { - self.statsdClient.increment('sqlapi.job.error'); - return handleException(err, res); - } - - res.header('X-Served-By-DB-Host', req.context.userDatabase.host); - - req.profiler.done('cancelJob'); - req.profiler.end(); - req.profiler.sendStats(); - - res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); - - self.statsdClient.increment('sqlapi.job.success'); - - res.send(job.serialize()); - } - ); + this.jobService.cancel(req.params.job_id, jobResponse(req, res, this.statsdClient, 'cancel')); }; JobController.prototype.getJob = function (req, res) { - var self = this; - var job_id = req.params.job_id; - - step( - function getJob() { - self.jobService.get(job_id, this); - }, - function handleResponse(err, job) { - if ( err ) { - self.statsdClient.increment('sqlapi.job.error'); - return handleException(err, res); - } - - res.header('X-Served-By-DB-Host', req.context.userDatabase.host); - - req.profiler.done('getJob'); - req.profiler.end(); - req.profiler.sendStats(); - - res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); - - self.statsdClient.increment('sqlapi.job.success'); - - res.send(job.serialize()); - } - ); + this.jobService.get(req.params.job_id, jobResponse(req, res, this.statsdClient, 'retrieve')); }; JobController.prototype.createJob = function (req, res) { - var self = this; var body = (req.body) ? req.body : {}; var params = _.extend({}, req.query, body); // clone so don't modify req.params or req.body so oauth is not broken var sql = (params.query === "" || _.isUndefined(params.query)) ? null : params.query; - step( - function persistJob() { - var data = { - user: req.context.user, - query: sql, - host: req.context.userDatabase.host - }; + var data = { + user: req.context.user, + query: sql, + host: req.context.userDatabase.host + }; - self.jobService.create(data, this); - }, - function handleResponse(err, job) { - if ( err ) { - self.statsdClient.increment('sqlapi.job.error'); - return handleException(err, res); - } - - res.header('X-Served-By-DB-Host', req.context.userDatabase.host); - - req.profiler.done('persistJob'); - req.profiler.end(); - req.profiler.sendStats(); - - res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); - - self.statsdClient.increment('sqlapi.job.success'); - - console.info(JSON.stringify({ - type: 'sql_api_batch_job', - username: req.context.user, - action: 'create', - job_id: job.job_id - })); - - res.status(201).send(job.serialize()); - } - ); + this.jobService.create(data, jobResponse(req, res, this.statsdClient, 'create', 201)); }; + +function jobResponse(req, res, statsdClient, action, status) { + return function handler(err, job) { + status = status || 200; + + if (err) { + statsdClient.increment('sqlapi.job.error'); + return handleException(err, res); + } + + res.header('X-Served-By-DB-Host', req.context.userDatabase.host); + + req.profiler.done(action); + req.profiler.end(); + req.profiler.sendStats(); + + res.header('X-SQLAPI-Profiler', req.profiler.toJSONString()); + statsdClient.increment('sqlapi.job.success'); + + console.info(JSON.stringify({ + type: 'sql_api_batch_job', + username: req.context.user, + action: action, + job_id: job.job_id + })); + + res.status(status).send(job.serialize()); + }; +} From 025b3f3cc71c39862aee26f1a131535e1a34b6de Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Oct 2016 11:14:06 +0200 Subject: [PATCH 68/76] Increase body limit to 20mb --- app/server.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/server.js b/app/server.js index 4a9be504..f205125c 100644 --- a/app/server.js +++ b/app/server.js @@ -171,8 +171,9 @@ function App() { }); } - app.use(bodyParser.json()); - app.use(bodyParser.urlencoded({ extended: true })); + app.use(bodyParser.json({ limit: '20mb' })); + app.use(bodyParser.urlencoded({ extended: true, limit: '20mb' })); + app.use(bodyParser.raw({ limit: '20mb' })); app.enable('jsonp callback'); app.set("trust proxy", true); app.disable('x-powered-by'); From 6309318534a8e42671456c89ac00f32f86714123 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Oct 2016 14:22:44 +0200 Subject: [PATCH 69/76] Use body-parser from old connect module --- app/middlewares/body-parser.js | 141 +++++++++++++++++++++++++++++++++ app/server.js | 6 +- npm-shrinkwrap.json | 111 ++------------------------ package.json | 3 +- 4 files changed, 151 insertions(+), 110 deletions(-) create mode 100644 app/middlewares/body-parser.js diff --git a/app/middlewares/body-parser.js b/app/middlewares/body-parser.js new file mode 100644 index 00000000..b1f26b04 --- /dev/null +++ b/app/middlewares/body-parser.js @@ -0,0 +1,141 @@ + +/*! + * Connect - bodyParser + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var qs = require('qs'); + +/** + * Extract the mime type from the given request's + * _Content-Type_ header. + * + * @param {IncomingMessage} req + * @return {String} + * @api private + */ + +function mime(req) { + var str = req.headers['content-type'] || ''; + return str.split(';')[0]; +} + +/** + * Parse request bodies. + * + * By default _application/json_, _application/x-www-form-urlencoded_, + * and _multipart/form-data_ are supported, however you may map `connect.bodyParser.parse[contentType]` + * to a function receiving `(req, options, callback)`. + * + * Examples: + * + * connect.createServer( + * connect.bodyParser() + * , function(req, res) { + * res.end('viewing user ' + req.body.user.name); + * } + * ); + * + * $ curl -d 'user[name]=tj' http://localhost/ + * $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://localhost/ + * + * Multipart req.files: + * + * As a security measure files are stored in a separate object, stored + * as `req.files`. This prevents attacks that may potentially alter + * filenames, and depending on the application gain access to restricted files. + * + * Multipart configuration: + * + * The `options` passed are provided to each parser function. + * The _multipart/form-data_ parser merges these with formidable's + * IncomingForm object, allowing you to tweak the upload directory, + * size limits, etc. For example you may wish to retain the file extension + * and change the upload directory: + * + * server.use(bodyParser({ uploadDir: '/www/mysite.com/uploads' })); + * + * View [node-formidable](https://github.com/felixge/node-formidable) for more information. + * + * If you wish to use formidable directly within your app, and do not + * desire this behaviour for multipart requests simply remove the + * parser: + * + * delete connect.bodyParser.parse['multipart/form-data']; + * + * Or + * + * delete express.bodyParser.parse['multipart/form-data']; + * + * @param {Object} options + * @return {Function} + * @api public + */ + +exports = module.exports = function bodyParser(options){ + options = options || {}; + return function bodyParser(req, res, next) { + if (req.body) { + return next(); + } + req.body = {}; + + if ('GET' === req.method || 'HEAD' === req.method) { + return next(); + } + var parser = exports.parse[mime(req)]; + if (parser) { + parser(req, options, next); + } else { + next(); + } + }; +}; + +/** + * Parsers. + */ + +exports.parse = {}; + +/** + * Parse application/x-www-form-urlencoded. + */ + +exports.parse['application/x-www-form-urlencoded'] = function(req, options, fn){ + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk; }); + req.on('end', function(){ + try { + req.body = buf.length ? qs.parse(buf) : {}; + fn(); + } catch (err){ + fn(err); + } + }); +}; + +/** + * Parse application/json. + */ + +exports.parse['application/json'] = function(req, options, fn){ + var buf = ''; + req.setEncoding('utf8'); + req.on('data', function(chunk){ buf += chunk; }); + req.on('end', function(){ + try { + req.body = buf.length ? JSON.parse(buf) : {}; + fn(); + } catch (err){ + fn(err); + } + }); +}; diff --git a/app/server.js b/app/server.js index f205125c..3b05b00e 100644 --- a/app/server.js +++ b/app/server.js @@ -15,7 +15,7 @@ // var express = require('express'); -var bodyParser = require('body-parser'); +var bodyParser = require('./middlewares/body-parser'); var os = require('os'); var Profiler = require('./stats/profiler-proxy'); var StatsD = require('node-statsd').StatsD; @@ -171,9 +171,7 @@ function App() { }); } - app.use(bodyParser.json({ limit: '20mb' })); - app.use(bodyParser.urlencoded({ extended: true, limit: '20mb' })); - app.use(bodyParser.raw({ limit: '20mb' })); + app.use(bodyParser()); app.enable('jsonp callback'); app.set("trust proxy", true); app.disable('x-powered-by'); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 33bc34cb..bbecec47 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -2,108 +2,6 @@ "name": "cartodb_sql_api", "version": "1.37.1", "dependencies": { - "body-parser": { - "version": "1.14.2", - "from": "body-parser@>=1.14.2 <1.15.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", - "dependencies": { - "bytes": { - "version": "2.2.0", - "from": "bytes@2.2.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz" - }, - "content-type": { - "version": "1.0.2", - "from": "content-type@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" - }, - "depd": { - "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" - }, - "http-errors": { - "version": "1.3.1", - "from": "http-errors@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", - "dependencies": { - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.1 <2.1.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "statuses": { - "version": "1.3.0", - "from": "statuses@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.0.tgz" - } - } - }, - "iconv-lite": { - "version": "0.4.13", - "from": "iconv-lite@0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" - }, - "on-finished": { - "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "dependencies": { - "ee-first": { - "version": "1.1.1", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - } - } - }, - "qs": { - "version": "5.2.0", - "from": "qs@5.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz" - }, - "raw-body": { - "version": "2.1.7", - "from": "raw-body@>=2.1.5 <2.2.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", - "dependencies": { - "bytes": { - "version": "2.4.0", - "from": "bytes@2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" - }, - "unpipe": { - "version": "1.0.0", - "from": "unpipe@1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - } - } - }, - "type-is": { - "version": "1.6.13", - "from": "type-is@>=1.6.10 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", - "dependencies": { - "media-typer": { - "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - }, - "mime-types": { - "version": "2.1.12", - "from": "mime-types@>=2.1.11 <2.2.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", - "dependencies": { - "mime-db": { - "version": "1.24.0", - "from": "mime-db@>=1.24.0 <1.25.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz" - } - } - } - } - } - } - }, "bunyan": { "version": "1.8.1", "from": "bunyan@1.8.1", @@ -624,6 +522,11 @@ } } }, + "qs": { + "version": "6.2.1", + "from": "qs@>=6.2.1 <6.3.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" + }, "queue-async": { "version": "1.0.7", "from": "queue-async@>=1.0.7 <1.1.0", @@ -709,7 +612,7 @@ "dependencies": { "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.1 <4.0.0", + "from": "strip-ansi@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "dependencies": { "ansi-regex": { @@ -986,7 +889,7 @@ }, "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.1 <4.0.0", + "from": "strip-ansi@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "dependencies": { "ansi-regex": { diff --git a/package.json b/package.json index 6fc0d54d..2d349570 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "Sandro Santilli " ], "dependencies": { - "body-parser": "~1.14.2", "bunyan": "1.8.1", "cartodb-psql": "~0.6.0", "cartodb-query-tables": "0.2.0", @@ -29,6 +28,7 @@ "node-statsd": "~0.0.7", "node-uuid": "^1.4.7", "oauth-client": "0.3.0", + "qs": "~6.2.1", "queue-async": "~1.0.7", "redis-mpool": "0.4.0", "step": "~0.0.5", @@ -45,7 +45,6 @@ "jshint": "~2.6.0", "zipfile": "~0.5.0", "libxmljs": "~0.8.1", - "qs": "6.2.0", "sqlite3": "~3.0.8" }, "scripts": { From 42a1f3ad4cebe880c6a7653dc338037a1fe1b9f7 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Oct 2016 17:29:16 +0200 Subject: [PATCH 70/76] Accept multipart requests --- app/middlewares/body-parser.js | 4 + npm-shrinkwrap.json | 173 ++++++++++++++++++++++++++++++++- package.json | 1 + 3 files changed, 174 insertions(+), 4 deletions(-) diff --git a/app/middlewares/body-parser.js b/app/middlewares/body-parser.js index b1f26b04..6c44e295 100644 --- a/app/middlewares/body-parser.js +++ b/app/middlewares/body-parser.js @@ -11,6 +11,7 @@ */ var qs = require('qs'); +var multer = require('multer'); /** * Extract the mime type from the given request's @@ -139,3 +140,6 @@ exports.parse['application/json'] = function(req, options, fn){ } }); }; + +var multipartMiddleware = multer({ limits: { fieldSize: Infinity } }); +exports.parse['multipart/form-data'] = multipartMiddleware.none(); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index bbecec47..c4ec56c5 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -192,7 +192,7 @@ "dependencies": { "mime-types": { "version": "2.1.12", - "from": "mime-types@>=2.1.6 <2.2.0", + "from": "mime-types@>=2.1.11 <2.2.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", "dependencies": { "mime-db": { @@ -422,7 +422,7 @@ }, "mime-types": { "version": "2.1.12", - "from": "mime-types@>=2.1.6 <2.2.0", + "from": "mime-types@>=2.1.11 <2.2.0", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", "dependencies": { "mime-db": { @@ -500,6 +500,171 @@ "from": "lru-cache@>=2.5.0 <2.6.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.2.tgz" }, + "multer": { + "version": "1.2.0", + "from": "multer@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.2.0.tgz", + "dependencies": { + "append-field": { + "version": "0.1.0", + "from": "append-field@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-0.1.0.tgz" + }, + "busboy": { + "version": "0.2.13", + "from": "busboy@>=0.2.11 <0.3.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.13.tgz", + "dependencies": { + "dicer": { + "version": "0.2.5", + "from": "dicer@0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "dependencies": { + "streamsearch": { + "version": "0.1.2", + "from": "streamsearch@0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz" + } + } + }, + "readable-stream": { + "version": "1.1.14", + "from": "readable-stream@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + } + } + } + } + }, + "concat-stream": { + "version": "1.5.2", + "from": "concat-stream@>=1.5.0 <2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "dependencies": { + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.1 <2.1.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "typedarray": { + "version": "0.0.6", + "from": "typedarray@>=0.0.5 <0.1.0", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" + }, + "readable-stream": { + "version": "2.0.6", + "from": "readable-stream@>=2.0.0 <2.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + } + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "from": "mkdirp@>=0.5.1 <0.6.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "dependencies": { + "minimist": { + "version": "0.0.8", + "from": "minimist@0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + } + } + }, + "object-assign": { + "version": "3.0.0", + "from": "object-assign@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <3.0.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "dependencies": { + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + } + } + }, + "type-is": { + "version": "1.6.13", + "from": "type-is@>=1.6.4 <2.0.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.13.tgz", + "dependencies": { + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "mime-types": { + "version": "2.1.12", + "from": "mime-types@>=2.1.2 <2.2.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", + "dependencies": { + "mime-db": { + "version": "1.24.0", + "from": "mime-db@>=1.24.0 <1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz" + } + } + } + } + }, + "xtend": { + "version": "4.0.1", + "from": "xtend@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + } + } + }, "node-statsd": { "version": "0.0.7", "from": "node-statsd@>=0.0.7 <0.1.0", @@ -612,7 +777,7 @@ "dependencies": { "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.0 <4.0.0", + "from": "strip-ansi@>=3.0.1 <4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "dependencies": { "ansi-regex": { @@ -889,7 +1054,7 @@ }, "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.0 <4.0.0", + "from": "strip-ansi@>=3.0.1 <4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "dependencies": { "ansi-regex": { diff --git a/package.json b/package.json index 2d349570..c163341a 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "express": "~4.13.3", "log4js": "cartodb/log4js-node#cdb", "lru-cache": "~2.5.0", + "multer": "~1.2.0", "node-statsd": "~0.0.7", "node-uuid": "^1.4.7", "oauth-client": "0.3.0", From 14a8a99191b9f6c3da41c19f990b74d768ae4acf Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Oct 2016 17:32:45 +0200 Subject: [PATCH 71/76] Update news --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 3d3ab544..ed81eeb4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,9 @@ 1.37.1 - 2016-mm-dd ------------------- +Bug fixes: + * Body parser accepting multipart requests. + 1.37.0 - 2016-10-04 ------------------- From 2014036ba702d34ae69edaa0e2ef5a9d87c14c89 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Oct 2016 17:33:05 +0200 Subject: [PATCH 72/76] Release 1.37.1 --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ed81eeb4..38828410 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -1.37.1 - 2016-mm-dd +1.37.1 - 2016-10-05 ------------------- Bug fixes: From 2bba1934edf038111811c3ff95e3aa6bb5021737 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Oct 2016 17:33:56 +0200 Subject: [PATCH 73/76] Stubs next version --- NEWS.md | 4 ++++ npm-shrinkwrap.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 38828410..08444207 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +1.37.2 - 2016-mm-dd +------------------- + + 1.37.1 - 2016-10-05 ------------------- diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index c4ec56c5..9bd56489 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "cartodb_sql_api", - "version": "1.37.1", + "version": "1.37.2", "dependencies": { "bunyan": { "version": "1.8.1", diff --git a/package.json b/package.json index c163341a..c9dfd8e8 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [ "cartodb" ], - "version": "1.37.1", + "version": "1.37.2", "repository": { "type": "git", "url": "git://github.com/CartoDB/CartoDB-SQL-API.git" From eb2768c197a9e9de755a67cd2b15d30a2010da77 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 5 Oct 2016 19:09:10 +0200 Subject: [PATCH 74/76] Add dbhost attribute to batch queries logs --- batch/models/job_fallback.js | 1 + 1 file changed, 1 insertion(+) diff --git a/batch/models/job_fallback.js b/batch/models/job_fallback.js index 29779fd8..0d3b3bea 100644 --- a/batch/models/job_fallback.js +++ b/batch/models/job_fallback.js @@ -224,6 +224,7 @@ JobFallback.prototype.log = function(logger) { time: query.started_at, endtime: query.ended_at, username: this.data.user, + dbhost: this.data.host, job: this.data.job_id, elapsed: elapsedTime(query.started_at, query.ended_at) }; From 2ac39b5748321ad65550aff947f8a7dcef19e9a8 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 6 Oct 2016 11:53:56 +0200 Subject: [PATCH 75/76] Move all batch tests to their own directory --- Makefile | 2 +- test/acceptance/{ => batch}/batch.test.js | 19 ++++++++++--------- .../{ => batch}/job.callback-template.test.js | 12 ++++++------ .../{ => batch}/job.fallback.test.js | 12 ++++++------ .../{ => batch}/job.query.limit.test.js | 10 +++++----- test/acceptance/{ => batch}/job.test.js | 8 ++++---- .../acceptance/{ => batch}/job.timing.test.js | 12 ++++++------ .../{ => batch}/job.use-case-1.test.js | 10 +++++----- .../{ => batch}/job.use-case-10.test.js | 10 +++++----- .../{ => batch}/job.use-case-2.test.js | 10 +++++----- .../{ => batch}/job.use-case-3.test.js | 10 +++++----- .../{ => batch}/job.use-case-4.test.js | 10 +++++----- .../{ => batch}/job.use-case-5.test.js | 10 +++++----- .../{ => batch}/job.use-case-6.test.js | 10 +++++----- .../{ => batch}/job.use-case-7.test.js | 10 +++++----- .../{ => batch}/job.use-case-8.test.js | 10 +++++----- .../{ => batch}/job.use-case-9.test.js | 10 +++++----- 17 files changed, 88 insertions(+), 87 deletions(-) rename test/acceptance/{ => batch}/batch.test.js (93%) rename test/acceptance/{ => batch}/job.callback-template.test.js (96%) rename test/acceptance/{ => batch}/job.fallback.test.js (99%) rename test/acceptance/{ => batch}/job.query.limit.test.js (94%) rename test/acceptance/{ => batch}/job.test.js (97%) rename test/acceptance/{ => batch}/job.timing.test.js (96%) rename test/acceptance/{ => batch}/job.use-case-1.test.js (93%) rename test/acceptance/{ => batch}/job.use-case-10.test.js (93%) rename test/acceptance/{ => batch}/job.use-case-2.test.js (94%) rename test/acceptance/{ => batch}/job.use-case-3.test.js (94%) rename test/acceptance/{ => batch}/job.use-case-4.test.js (94%) rename test/acceptance/{ => batch}/job.use-case-5.test.js (93%) rename test/acceptance/{ => batch}/job.use-case-6.test.js (91%) rename test/acceptance/{ => batch}/job.use-case-7.test.js (93%) rename test/acceptance/{ => batch}/job.use-case-8.test.js (95%) rename test/acceptance/{ => batch}/job.use-case-9.test.js (94%) diff --git a/Makefile b/Makefile index 1caa1470..50c370f6 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ TEST_SUITE := $(shell find test/{acceptance,unit,integration} -name "*.js") TEST_SUITE_UNIT := $(shell find test/unit -name "*.js") TEST_SUITE_INTEGRATION := $(shell find test/integration -name "*.js") TEST_SUITE_ACCEPTANCE := $(shell find test/acceptance -name "*.js") -TEST_SUITE_BATCH := $(shell find test -name "*job*.js") +TEST_SUITE_BATCH := $(shell find test/*/batch -name "*.js") test: @echo "***tests***" diff --git a/test/acceptance/batch.test.js b/test/acceptance/batch/batch.test.js similarity index 93% rename from test/acceptance/batch.test.js rename to test/acceptance/batch/batch.test.js index c870d3fe..6e1baa36 100644 --- a/test/acceptance/batch.test.js +++ b/test/acceptance/batch/batch.test.js @@ -1,16 +1,17 @@ -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +require('../../helper'); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var _ = require('underscore'); var RedisPool = require('redis-mpool'); var queue = require('queue-async'); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch/index'); -var JobPublisher = require('../../batch/job_publisher'); -var JobQueue = require('../../batch/job_queue'); -var JobBackend = require('../../batch/job_backend'); -var JobService = require('../../batch/job_service'); -var UserDatabaseMetadataService = require('../../batch/user_database_metadata_service'); -var JobCanceller = require('../../batch/job_canceller'); +var JobPublisher = require('../../../batch/job_publisher'); +var JobQueue = require('../../../batch/job_queue'); +var JobBackend = require('../../../batch/job_backend'); +var JobService = require('../../../batch/job_service'); +var UserDatabaseMetadataService = require('../../../batch/user_database_metadata_service'); +var JobCanceller = require('../../../batch/job_canceller'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); describe('batch module', function() { diff --git a/test/acceptance/job.callback-template.test.js b/test/acceptance/batch/job.callback-template.test.js similarity index 96% rename from test/acceptance/job.callback-template.test.js rename to test/acceptance/batch/job.callback-template.test.js index 9fdfbf67..86e88e87 100644 --- a/test/acceptance/job.callback-template.test.js +++ b/test/acceptance/batch/job.callback-template.test.js @@ -1,12 +1,12 @@ -require('../helper'); +require('../../helper'); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); -var server = require('../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); +var server = require('../../../app/server')(); var querystring = require('qs'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); -var jobStatus = require('../../batch/job_status'); +var batchFactory = require('../../../batch/index'); +var jobStatus = require('../../../batch/job_status'); describe('Batch API callback templates', function () { diff --git a/test/acceptance/job.fallback.test.js b/test/acceptance/batch/job.fallback.test.js similarity index 99% rename from test/acceptance/job.fallback.test.js rename to test/acceptance/batch/job.fallback.test.js index f17ed56f..ccde5ebf 100644 --- a/test/acceptance/job.fallback.test.js +++ b/test/acceptance/batch/job.fallback.test.js @@ -1,12 +1,12 @@ -require('../helper'); +require('../../helper'); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); -var server = require('../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); +var server = require('../../../app/server')(); var querystring = require('qs'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); -var jobStatus = require('../../batch/job_status'); +var batchFactory = require('../../../batch/index'); +var jobStatus = require('../../../batch/job_status'); describe('Batch API fallback job', function () { diff --git a/test/acceptance/job.query.limit.test.js b/test/acceptance/batch/job.query.limit.test.js similarity index 94% rename from test/acceptance/job.query.limit.test.js rename to test/acceptance/batch/job.query.limit.test.js index 9ce4e627..5587ecda 100644 --- a/test/acceptance/job.query.limit.test.js +++ b/test/acceptance/batch/job.query.limit.test.js @@ -12,11 +12,11 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); -var JobController = require('../../app/controllers/job_controller'); -var redisUtils = require('../support/redis_utils'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); +require('../../helper'); +var JobController = require('../../../app/controllers/job_controller'); +var redisUtils = require('../../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); var querystring = require('qs'); function payload(query) { diff --git a/test/acceptance/job.test.js b/test/acceptance/batch/job.test.js similarity index 97% rename from test/acceptance/job.test.js rename to test/acceptance/batch/job.test.js index ec4f45ee..5c3f2b5e 100644 --- a/test/acceptance/job.test.js +++ b/test/acceptance/batch/job.test.js @@ -12,11 +12,11 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); describe('job module', function() { diff --git a/test/acceptance/job.timing.test.js b/test/acceptance/batch/job.timing.test.js similarity index 96% rename from test/acceptance/job.timing.test.js rename to test/acceptance/batch/job.timing.test.js index a3d71fa7..932f189d 100644 --- a/test/acceptance/job.timing.test.js +++ b/test/acceptance/batch/job.timing.test.js @@ -1,12 +1,12 @@ -require('../helper'); +require('../../helper'); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); -var server = require('../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); +var server = require('../../../app/server')(); var querystring = require('qs'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); -var jobStatus = require('../../batch/job_status'); +var batchFactory = require('../../../batch'); +var jobStatus = require('../../../batch/job_status'); describe('Batch API query timing', function () { diff --git a/test/acceptance/job.use-case-1.test.js b/test/acceptance/batch/job.use-case-1.test.js similarity index 93% rename from test/acceptance/job.use-case-1.test.js rename to test/acceptance/batch/job.use-case-1.test.js index 4f3786ed..fde821aa 100644 --- a/test/acceptance/job.use-case-1.test.js +++ b/test/acceptance/batch/job.use-case-1.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch/index'); describe('Use case 1: cancel and modify a done job', function () { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-10.test.js b/test/acceptance/batch/job.use-case-10.test.js similarity index 93% rename from test/acceptance/job.use-case-10.test.js rename to test/acceptance/batch/job.use-case-10.test.js index b6172ee5..e7786a56 100644 --- a/test/acceptance/job.use-case-10.test.js +++ b/test/acceptance/batch/job.use-case-10.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch/index'); describe('Use case 10: cancel and modify a done multiquery job', function () { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-2.test.js b/test/acceptance/batch/job.use-case-2.test.js similarity index 94% rename from test/acceptance/job.use-case-2.test.js rename to test/acceptance/batch/job.use-case-2.test.js index 4e83e9e4..35f36f71 100644 --- a/test/acceptance/job.use-case-2.test.js +++ b/test/acceptance/batch/job.use-case-2.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch/index'); describe('Use case 2: cancel a running job', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-3.test.js b/test/acceptance/batch/job.use-case-3.test.js similarity index 94% rename from test/acceptance/job.use-case-3.test.js rename to test/acceptance/batch/job.use-case-3.test.js index 644c0784..e3e5fad6 100644 --- a/test/acceptance/job.use-case-3.test.js +++ b/test/acceptance/batch/job.use-case-3.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch/index'); describe('Use case 3: cancel a pending job', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-4.test.js b/test/acceptance/batch/job.use-case-4.test.js similarity index 94% rename from test/acceptance/job.use-case-4.test.js rename to test/acceptance/batch/job.use-case-4.test.js index d3cdf9d1..0baae3ad 100644 --- a/test/acceptance/job.use-case-4.test.js +++ b/test/acceptance/batch/job.use-case-4.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch'); describe('Use case 4: modify a pending job', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-5.test.js b/test/acceptance/batch/job.use-case-5.test.js similarity index 93% rename from test/acceptance/job.use-case-5.test.js rename to test/acceptance/batch/job.use-case-5.test.js index caab7663..b916ff1d 100644 --- a/test/acceptance/job.use-case-5.test.js +++ b/test/acceptance/batch/job.use-case-5.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch'); describe('Use case 5: modify a running job', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-6.test.js b/test/acceptance/batch/job.use-case-6.test.js similarity index 91% rename from test/acceptance/job.use-case-6.test.js rename to test/acceptance/batch/job.use-case-6.test.js index 971970f3..e046a2ac 100644 --- a/test/acceptance/job.use-case-6.test.js +++ b/test/acceptance/batch/job.use-case-6.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch'); describe('Use case 6: modify a done job', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-7.test.js b/test/acceptance/batch/job.use-case-7.test.js similarity index 93% rename from test/acceptance/job.use-case-7.test.js rename to test/acceptance/batch/job.use-case-7.test.js index 118a5c8f..09c5a054 100644 --- a/test/acceptance/job.use-case-7.test.js +++ b/test/acceptance/batch/job.use-case-7.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch'); describe('Use case 7: cancel a job with quotes', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-8.test.js b/test/acceptance/batch/job.use-case-8.test.js similarity index 95% rename from test/acceptance/job.use-case-8.test.js rename to test/acceptance/batch/job.use-case-8.test.js index 5b992d3e..43ee016b 100644 --- a/test/acceptance/job.use-case-8.test.js +++ b/test/acceptance/batch/job.use-case-8.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch'); describe('Use case 8: cancel a running multiquery job', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); diff --git a/test/acceptance/job.use-case-9.test.js b/test/acceptance/batch/job.use-case-9.test.js similarity index 94% rename from test/acceptance/job.use-case-9.test.js rename to test/acceptance/batch/job.use-case-9.test.js index c68fa383..6d508855 100644 --- a/test/acceptance/job.use-case-9.test.js +++ b/test/acceptance/batch/job.use-case-9.test.js @@ -12,14 +12,14 @@ * HSET rails:users:vizzuality database_name cartodb_test_user_1_db * */ -require('../helper'); +require('../../helper'); -var server = require('../../app/server')(); -var assert = require('../support/assert'); -var redisUtils = require('../support/redis_utils'); +var server = require('../../../app/server')(); +var assert = require('../../support/assert'); +var redisUtils = require('../../support/redis_utils'); var querystring = require('querystring'); var metadataBackend = require('cartodb-redis')(redisUtils.getConfig()); -var batchFactory = require('../../batch'); +var batchFactory = require('../../../batch'); describe('Use case 9: modify a pending multiquery job', function() { var batch = batchFactory(metadataBackend, redisUtils.getConfig()); From 26fe6a16260182a454f10d23a94eb6bc5a05cce0 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 6 Oct 2016 12:27:38 +0200 Subject: [PATCH 76/76] Add readme for batch queries feature --- batch/README.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 batch/README.md diff --git a/batch/README.md b/batch/README.md new file mode 100644 index 00000000..ec56d446 --- /dev/null +++ b/batch/README.md @@ -0,0 +1,91 @@ +# Batch Queries + +This document describes the currently supported query types, and what they are missing in terms of features. + +## Job types + +### Simple + +```json +{ + "query": "update ..." +} +``` + +Does not support main fallback queries. Ideally it should support something like: + +```json +{ + "query": "update ...", + "onsuccess": "select 'general success fallback'", + "onerror": "select 'general error fallback'" +} +``` + +### Multiple + +```json +{ + "query": [ + "update ...", + "select ... into ..." + ] +} +``` + +Does not support main fallback queries. Ideally it should support something like: + +```json +{ + "query": [ + "update ...", + "select ... into ..." + ], + "onsuccess": "select 'general success fallback'", + "onerror": "select 'general error fallback'" +} +``` + +### Fallback + +```json +{ + "query": { + "query": [ + { + "query": "select 1", + "onsuccess": "select 'success fallback query 1'", + "onerror": "select 'error fallback query 1'" + }, + { + "query": "select 2", + "onerror": "select 'error fallback query 2'" + } + ], + "onsuccess": "select 'general success fallback'", + "onerror": "select 'general error fallback'" + } +} +``` + +It's weird to have two nested `query` attributes. Also, it's not possible to mix _plain_ with _fallback_ ones. +Ideally it should support something like: + +```json +{ + "query": [ + { + "query": "select 1", + "onsuccess": "select 'success fallback query 1'", + "onerror": "select 'error fallback query 1'" + }, + "select 2" + ], + "onsuccess": "select 'general success fallback'", + "onerror": "select 'general error fallback'" + } +} +``` + +Where you don't need a nested `query` attribute, it's just an array as in Multiple job type, and you can mix objects and +plain queries.