'use strict'; require('../helper'); const qs = require('querystring'); const assert = require('../support/assert'); const redis = require('redis'); const rateLimitMiddleware = require('../../lib/api/middlewares/rate-limit'); const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimitMiddleware; const app = require('../../lib/server'); let server; let redisClient; let keysToDelete = []; const user = 'vizzuality'; var request = { url: '/api/v1/sql?' + qs.stringify({ q: 'SELECT * FROM untitle_table_4' }), headers: { host: 'vizzuality.cartodb.com' }, method: 'GET' }; function setLimit(count, period, burst) { redisClient.SELECT(8, err => { if (err) { return; } const key = `limits:rate:store:${user}:sql:${RATE_LIMIT_ENDPOINTS_GROUPS.QUERY}`; redisClient.rpush(key, burst); redisClient.rpush(key, count); redisClient.rpush(key, period); keysToDelete.push(key); }); } function assertRequest (status, limit, remaining, reset, retry, done = null) { assert.response( server, request, { status }, function(err, res) { assert.ifError(err); assert.equal(res.headers['carto-rate-limit-limit'], limit); assert.equal(res.headers['carto-rate-limit-remaining'], remaining); assert.equal(res.headers['carto-rate-limit-reset'], reset); if (retry) { assert.equal(res.headers['retry-after'], retry); } if(status === 429) { const expectedResponse = { error: ["You are over platform\'s limits. Please contact us to know more details"], context: "limit", detail: "rate-limit" }; assert.deepEqual(JSON.parse(res.body), expectedResponse); } if (done) { setTimeout(done, 1000); } } ); } describe('rate limit', function() { before(function() { global.settings.ratelimits.rateLimitsEnabled = true; global.settings.ratelimits.endpoints.query = true; server = app(); redisClient = redis.createClient(global.settings.redis_port); const count = 1; const period = 1; const burst = 1; setLimit(count, period, burst); }); after(function() { global.settings.ratelimits.rateLimitsEnabled = false; global.settings.ratelimits.endpoints.query = false; keysToDelete.forEach( key => { redisClient.del(key); }); }); it("1 req/sec: 2 req/seg should be limited", function(done) { assertRequest(200, 2, 1, 1); setTimeout( () => assertRequest(200, 2, 0, 1, null), 250 ); setTimeout( () => assertRequest(429, 2, 0, 1, 1), 500 ); setTimeout( () => assertRequest(429, 2, 0, 1, 1), 750 ); setTimeout( () => assertRequest(429, 2, 0, 1, 1), 950 ); setTimeout( () => assertRequest(200, 2, 0, 1, null, done), 1050 ); }); });