Skip to content

Commit

Permalink
Add rate limiting
Browse files Browse the repository at this point in the history
  • Loading branch information
bbindreiter committed Nov 13, 2022
1 parent aab8989 commit c735177
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
29 changes: 29 additions & 0 deletions lib/alexa-remote-ext.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const known = require('./known-color-values.js');
const convert = require('./color-convert.js');
const deltaE = require('./delta-e.js');
const DEBUG_THIS = tools.DEBUG_THIS;
const REQUEST_RATE_LIMIT_EXPIRATION_IN_M = 5;

function requireUncached(mod) {
delete require.cache[require.resolve(mod)];
Expand Down Expand Up @@ -104,6 +105,7 @@ class AlexaRemoteExt extends AlexaRemote {

this.errorMessagesExt = {};
this.smarthomeSimplifiedByEntityIdExt = new Map();
this.smarthomeRequestsRateLimit = new Map();
this.routineByIdExt = new Map();
this.routineByUtteranceExt = new Map();
this.musicProvidersExt = [];
Expand All @@ -129,6 +131,28 @@ class AlexaRemoteExt extends AlexaRemote {
this.logWarn = () => { };
}

_rateLimitRequestHasExpired(date) {
const expirationDate = Date.now() - REQUEST_RATE_LIMIT_EXPIRATION_IN_M * 60 * 1000;

if (expirationDate > date) {
return true;
} else {
return false;
}
}

_requestRateLimitCheck(key) {
if (this.smarthomeRequestsRateLimit.has(key)) {
if (this._rateLimitRequestHasExpired(this.smarthomeRequestsRateLimit.get(key))) {
this.smarthomeRequestsRateLimit.set(key, Date.now());
} else {
throw new Error('Too many request. Try again in ' + REQUEST_RATE_LIMIT_EXPIRATION_IN_M + ' minutes.');
}
} else {
this.smarthomeRequestsRateLimit.set(key, Date.now());
}
}

async initExt(config, proxyActiveCallback = () => { }, logWarn = () => { }, logError = () => { }) {
this.logWarn = logWarn;
this.logError = logError;
Expand Down Expand Up @@ -721,6 +745,8 @@ class AlexaRemoteExt extends AlexaRemote {

// requests like ['Lamp 1', '1234-DEAD-BEEF-5678' }]
async querySmarthomeDeviceStatesExt(requests) {
this._requestRateLimitCheck(JSON.stringify(requests));

const entities = requests.map(request => this.findSmarthomeEntityExt(request.entity));
const nativeRequests = entities.filter(e => e).map(entity => ({
entityType: entity.type,
Expand All @@ -739,6 +765,8 @@ class AlexaRemoteExt extends AlexaRemote {
}

async querySmarthomeDevicesExt(stateRequests) {
this._requestRateLimitCheck(JSON.stringify(stateRequests));

/*
'stateRequests': [
{
Expand All @@ -759,6 +787,7 @@ class AlexaRemoteExt extends AlexaRemote {
}

async executeSmarthomeDeviceActionExt(controlRequests) {
this._requestRateLimitCheck(JSON.stringify(controlRequests));
/*
{
'controlRequests': [
Expand Down
2 changes: 1 addition & 1 deletion nodes/alexa-remote-smarthome.html
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,7 @@ <h3><strong>References</strong></h3>
},
});
const disclaimerHeader = $('<h3>Please avoid polling!</h3>').insertBefore(inputs);
const disclaimerText = $('<p>If your use-case requires it make sure to keep the interval as high as possible.</p>').css({ margin: '0px 0px 24px 0px' }).insertBefore(inputs);
const disclaimerText = $('<p>If your use-case requires it, you must keep the interval above 5 minutes, otherwise an error will be thrown.</p>').css({ margin: '0px 0px 24px 0px' }).insertBefore(inputs);

const select = arSelect(data.option, ['get', 'query', 'action', 'discover', 'forget']);
arFormRow(select, 'Select', 'fa fa-sort').insertBefore(inputs);
Expand Down

0 comments on commit c735177

Please sign in to comment.