Comparing version 2.0.0 to 2.0.1
"use strict"; | ||
// var vows = require('vows'); | ||
// var assert = require('assert'); | ||
// var RateLimiter = require('../lib/rateLimiter'); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -6,0 +3,0 @@ const RateLimiter_1 = require("./RateLimiter"); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const TIMING_EPSILON = 10; | ||
const TokenBucket_1 = require("./TokenBucket"); | ||
const clock_1 = require("./clock"); | ||
const TIMING_EPSILON = 10; | ||
describe("TokenBucket", () => { | ||
@@ -7,0 +7,0 @@ describe("capacity 10, 1 per 100ms", () => { |
@@ -1,3 +0,3 @@ | ||
export * from "./RateLimiter"; | ||
export * from "./TokenBucket"; | ||
export * from "./RateLimiter.js"; | ||
export * from "./TokenBucket.js"; | ||
//# sourceMappingURL=index.js.map |
@@ -1,3 +0,3 @@ | ||
import { TokenBucket } from "./TokenBucket"; | ||
import { getMilliseconds, wait } from "./clock"; | ||
import { TokenBucket } from "./TokenBucket.js"; | ||
import { getMilliseconds, wait } from "./clock.js"; | ||
/** | ||
@@ -4,0 +4,0 @@ * A generic rate limiter. Underneath the hood, this uses a token bucket plus |
@@ -1,5 +0,2 @@ | ||
// var vows = require('vows'); | ||
// var assert = require('assert'); | ||
// var RateLimiter = require('../lib/rateLimiter'); | ||
import { RateLimiter } from "./RateLimiter"; | ||
import { RateLimiter } from "./RateLimiter.js"; | ||
describe("RateLimiter", () => { | ||
@@ -6,0 +3,0 @@ describe("interval validation", () => { |
@@ -1,2 +0,2 @@ | ||
import { getMilliseconds, wait } from "./clock"; | ||
import { getMilliseconds, wait } from "./clock.js"; | ||
/** | ||
@@ -3,0 +3,0 @@ * A hierarchical token bucket for rate limiting. See |
@@ -0,4 +1,4 @@ | ||
import { TokenBucket } from "./TokenBucket.js"; | ||
import { wait } from "./clock.js"; | ||
const TIMING_EPSILON = 10; | ||
import { TokenBucket } from "./TokenBucket"; | ||
import { wait } from "./clock"; | ||
describe("TokenBucket", () => { | ||
@@ -5,0 +5,0 @@ describe("capacity 10, 1 per 100ms", () => { |
@@ -1,2 +0,2 @@ | ||
Copyright (C) 2011 by John Hurliman | ||
Copyright (C) 2011-2021 by John Hurliman | ||
@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
{ | ||
"name": "limiter", | ||
"description": "A generic rate limiter for the web and node.js. Useful for API clients, web crawling, or other tasks that need to be throttled", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"author": "John Hurliman <jhurliman@jhurliman.org>", | ||
@@ -25,3 +25,3 @@ "type": "module", | ||
"lint": "eslint --fix src", | ||
"prepack": "yarn tsc -p tsconfig.json && tsc -p tsconfig.cjs.json", | ||
"prepack": "yarn ttsc -p tsconfig.json && ttsc -p tsconfig.cjs.json", | ||
"test": "jest src" | ||
@@ -40,2 +40,3 @@ }, | ||
"@typescript-eslint/parser": "^4.22.0", | ||
"@zoltu/typescript-transformer-append-js-extension": "^1.0.1", | ||
"babel-jest": "^26.6.3", | ||
@@ -46,2 +47,3 @@ "eslint": "^7.25.0", | ||
"prettier": "^2.2.1", | ||
"ttypescript": "^1.5.12", | ||
"typescript": "^4.2.4" | ||
@@ -48,0 +50,0 @@ }, |
149
README.md
@@ -1,2 +0,2 @@ | ||
# limiter # | ||
# limiter | ||
@@ -6,36 +6,33 @@ [![Build Status](https://travis-ci.org/jhurliman/node-rate-limiter.png)](https://travis-ci.org/jhurliman/node-rate-limiter) | ||
Provides a generic rate limiter for node.js. Useful for API clients, web | ||
crawling, or other tasks that need to be throttled. Two classes are exposed, | ||
Provides a generic rate limiter for the web and node.js. Useful for API clients, | ||
web crawling, or other tasks that need to be throttled. Two classes are exposed, | ||
RateLimiter and TokenBucket. TokenBucket provides a lower level interface to | ||
rate limiting with a configurable burst rate and drip rate. RateLimiter sits | ||
on top of the token bucket and adds a restriction on the maximum number of | ||
tokens that can be removed each interval to comply with common API | ||
restrictions like "150 requests per hour maximum". | ||
rate limiting with a configurable burst rate and drip rate. RateLimiter sits on | ||
top of the token bucket and adds a restriction on the maximum number of tokens | ||
that can be removed each interval to comply with common API restrictions such as | ||
"150 requests per hour maximum". | ||
## Installation ## | ||
## Installation | ||
Use NPM to install: | ||
yarn install limiter | ||
npm install limiter | ||
## Usage | ||
## Usage ## | ||
A simple example allowing 150 requests per hour: | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
import { RateLimiter } from "limiter"; | ||
// Allow 150 requests per hour (the Twitter search limit). Also understands | ||
// 'second', 'minute', 'day', or a number of milliseconds | ||
var limiter = new RateLimiter(150, 'hour'); | ||
const limiter = new RateLimiter({ tokensPerInterval: 150, interval: "hour" }); | ||
// Throttle requests | ||
limiter.removeTokens(1, function(err, remainingRequests) { | ||
// err will only be set if we request more than the maximum number of | ||
// requests we set in the constructor | ||
async function sendRequest() { | ||
// This call will throw if we request more than the maximum number of requests | ||
// that were set in the constructor | ||
// remainingRequests tells us how many additional requests could be sent | ||
// right this moment | ||
const remainingRequests = await limiter.removeTokens(1); | ||
callMyRequestSendingFunction(...); | ||
}); | ||
} | ||
``` | ||
@@ -46,21 +43,29 @@ | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(1, 250); | ||
import { RateLimiter } from "limiter"; | ||
limiter.removeTokens(1, function() { | ||
const limiter = new RateLimiter({ tokensPerInterval: 1, interval: 250 }); | ||
async function sendMessage() { | ||
const remainingMessages = await limiter.removeTokens(1); | ||
callMyMessageSendingFunction(...); | ||
}); | ||
} | ||
``` | ||
The default behaviour is to wait for the duration of the rate limiting | ||
that’s currently in effect before the callback is fired, but if you | ||
pass in ```true``` as the third parameter, the callback will be fired | ||
immediately with remainingRequests set to -1: | ||
The default behaviour is to wait for the duration of the rate limiting that's | ||
currently in effect before the promise is resolved, but if you pass in | ||
`"fireImmediately": true`, the promise will be resolved immediately with | ||
`remainingRequests` set to -1: | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(150, 'hour', true); // fire CB immediately | ||
import { RateLimiter } from "limiter"; | ||
// Immediately send 429 header to client when rate limiting is in effect | ||
limiter.removeTokens(1, function(err, remainingRequests) { | ||
const limiter = new RateLimiter({ | ||
tokensPerInterval: 150, | ||
interval: "hour", | ||
fireImmediately: true | ||
}); | ||
async function requestHandler(request, response) { | ||
// Immediately send 429 header to client when rate limiting is in effect | ||
const remainingRequests = await limiter.removeTokens(1); | ||
if (remainingRequests < 0) { | ||
@@ -72,10 +77,14 @@ response.writeHead(429, {'Content-Type': 'text/plain;charset=UTF-8'}); | ||
} | ||
}); | ||
} | ||
``` | ||
A synchronous method, tryRemoveTokens(), is available in both RateLimiter and TokenBucket. This will return immediately with a boolean value indicating if the token removal was successful. | ||
A synchronous method, tryRemoveTokens(), is available in both RateLimiter and | ||
TokenBucket. This will return immediately with a boolean value indicating if the | ||
token removal was successful. | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(10, 'second'); | ||
import { RateLimiter } from "limiter"; | ||
const limiter = new RateLimiter({ tokensPerInterval: 10, interval: "second" }); | ||
if (limiter.tryRemoveTokens(5)) | ||
@@ -87,10 +96,13 @@ console.log('Tokens removed'); | ||
To get the number of remaining tokens **outside** the `removeTokens`-callback | ||
simply use the `getTokensRemaining`-method. | ||
To get the number of remaining tokens **outside** the `removeTokens` promise, | ||
simply use the `getTokensRemaining` method. | ||
```javascript | ||
var RateLimiter = require('limiter').RateLimiter; | ||
var limiter = new RateLimiter(1, 250); | ||
import { RateLimiter } from "limiter"; | ||
// returns 1 since we did not remove a token and our number of tokens per interval is 1 | ||
limiter.getTokensRemaining(); | ||
const limiter = new RateLimiter({ tokensPerInterval: 1, interval: 250 }); | ||
// Prints 1 since we did not remove a token and our number of tokens per | ||
// interval is 1 | ||
console.log(limiter.getTokensRemaining()); | ||
``` | ||
@@ -101,15 +113,23 @@ | ||
```javascript | ||
var BURST_RATE = 1024 * 1024 * 150; // 150KB/sec burst rate | ||
var FILL_RATE = 1024 * 1024 * 50; // 50KB/sec sustained rate | ||
var TokenBucket = require('limiter').TokenBucket; | ||
// We could also pass a parent token bucket in as the last parameter to | ||
// create a hierarchical token bucket | ||
var bucket = new TokenBucket(BURST_RATE, FILL_RATE, 'second', null); | ||
import { TokenBucket } from "limiter"; | ||
bucket.removeTokens(myData.byteLength, function() { | ||
const BURST_RATE = 1024 * 1024 * 150; // 150KB/sec burst rate | ||
const FILL_RATE = 1024 * 1024 * 50; // 50KB/sec sustained rate | ||
// We could also pass a parent token bucket in to create a hierarchical token | ||
// bucket | ||
// bucketSize, tokensPerInterval, interval | ||
const bucket = new TokenBucket({ | ||
bucketSize: BURST_RATE, | ||
tokensPerInterval: FILL_RATE, | ||
interval: "second" | ||
}); | ||
async function handleData(myData) { | ||
await bucket.removeTokens(myData.byteLength); | ||
sendMyData(myData); | ||
}); | ||
} | ||
``` | ||
## Additional Notes ## | ||
## Additional Notes | ||
@@ -122,25 +142,4 @@ Both the token bucket and rate limiter should be used with a message queue or | ||
## License ## | ||
## License | ||
(The MIT License) | ||
Copyright (c) 2013 John Hurliman. <jhurliman@jhurliman.org> | ||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
'Software'), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
MIT License |
@@ -1,5 +0,1 @@ | ||
// var vows = require('vows'); | ||
// var assert = require('assert'); | ||
// var RateLimiter = require('../lib/rateLimiter'); | ||
import { RateLimiter } from "./RateLimiter"; | ||
@@ -6,0 +2,0 @@ import { Interval } from "./TokenBucket"; |
@@ -1,6 +0,6 @@ | ||
const TIMING_EPSILON = 10; | ||
import { TokenBucket } from "./TokenBucket"; | ||
import { wait } from "./clock"; | ||
const TIMING_EPSILON = 10; | ||
describe("TokenBucket", () => { | ||
@@ -7,0 +7,0 @@ describe("capacity 10, 1 per 100ms", () => { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
0
228171
15
1280
140