aishek / axios-rate-limit Goto Github PK
View Code? Open in Web Editor NEWRate limit for axios
License: MIT License
Rate limit for axios
License: MIT License
We have a hard time mocking this library, any help would be appreciated.
As a user of the axios-rate-limit library, I would like to suggest decoupling the built-in in-memory queue implementation and providing an interface for other queue implementations such as redis. This will allow users to easily switch between different queue implementations by configuring the library with the desired queue type.
refer: #37
It could be useful to limit number of requests for more than one process/server.
This can be implemented with a help of rate-limiter-flexible
I am thinking maybe you can persist the queued requests using Redis. This is a feature that I needed several times and is not supported via an easy solution like yours. The alternative is to use some sophisticated scheduling package, and it's always a hassle just to do some simple rate-limiting.
I can help with this feature, but I want to know what the maintaining team thinks about it.
Axios makes 2 requests in parallel, but after 30 seconds, it only makes one request at a time instead of two.
const axiosWithRateLimit = rateLimit(axios_update.create(), { maxRequests: 2, perMilliseconds: 30000 })
This is how load the module:
const axios = require('axios').default;
const rateLimit = require('axios-rate-limit');
http = rateLimit(axios.create(), { maxRPS: 10 })
This is how I'm populating my requests queue:
http.get('https://postman-echo.com/notexistingpage?)
.then(function (response) {
console.log('status: '+response.status);
})
.catch(function (error) {
console.log('Error');
})
.then(function () {
});
Each request is getting an error (because of notexistingpage in the url). After the first 10 sent request 1 request per second is sent. If I change notexistingpage in the url with an existing one, requests are sent at 10/sec.
Why is it slowing down to 1 req/sec on error? Using http.getMaxRPS() I get the correct value (10)
Thank you!
Hello
I wanted to know if it is possible to retry any failed requests? Is axios-rate-limit compatible with axios-retry (https://github.com/softonic/axios-retry)?
Thanks
First, I find this a great library.
My use-case is that I display a large table and for each row, there are 2 requests I need to make. The table uses pagination.
When I go to the next page I cancel all the unfinished requests from the previous page. The old requests don't need to be resolved since they are not going to be displayed, anyway.
I can clearly see that when I jump through the pages in the paginated table, the requests are getting delayed. The old (canceled) requests are getting executed in a "rate-limited" manner. They don't make it to the server but still, they are counted into rate limit. Once the old requests are all done, the new requests are resolved.
I think that this is not a correct behavior and canceled requests should be removed from the rate limiter, thus allowing the new requests getting executed faster.
Do you think that this has the potential to make the implementation of this library more robust?
Here it shows a Promise.all does not longer keep the process alive, it terminates... I guess this ratelimiter was implemented with daemonized scripts in mind?
const axios = require('axios')
const rl = require('axios-rate-limit');
// sets max 2 requests per 1 second, other will be delayed
const http = rl(axios.create(), { maxRequests: 2, perMilliseconds: 1000 });
Promise.all([
http.get('http://httpbin.org/get').then(x => {console.log(1); return x}),
http.get('http://httpbin.org/get').then(x => {console.log(2); return x}),
http.get('http://httpbin.org/get').then(x => {console.log(3); return x}),
]).then(x => {
console.log('after')
})
If you count yourself how many requests you scheduled and if they are all finished or just add a global timeout to keep the process alive it works:
const axios = require('axios')
const rl = require('axios-rate-limit');
// sets max 2 requests per 1 second, other will be delayed
const http = rl(axios.create(), { maxRequests: 2, perMilliseconds: 1000 });
Promise.all([
http.get('http://httpbin.org/get').then(x => {console.log(1); return x}),
http.get('http://httpbin.org/get').then(x => {console.log(2); return x}),
http.get('http://httpbin.org/get').then(x => {console.log(3); return x}),
]).then(x => {
console.log('after')
})
setTimeout(function() {
console.log('kept alive for 5s')
}, 5000)
Would it be possible to add a priority queue feature to the library? I.e. if there are 100 queued requests, could you push 10 requests to the front of the queue?
The rate limiter intercepts requests and responses from axios and doesn't re-throw errors. This causes any errors thrown by axios to be consumed (i.e., you cannot catch them later on in a try catch block).
This can be fixed by simply adding error handling to the interceptors:
AxiosRateLimit.prototype.enable = function (axios) {
this.interceptors.request = axios.interceptors.request.use(
this.requestHandler,
function (error) {
return Promise.reject(error)
}
)
this.interceptors.response = axios.interceptors.response.use(
this.responseHandler,
function (error) {
return Promise.reject(error)
}
)
}
I've submitted a pull request that addresses this issue: #2
Dear Alexandr
Thank you for implementing a rate-limiting feature for Axios. It works very well!
If you find some time, maybe you could address some TypeScript-related issues I am facing:
Export the RateLimitedAxiosInstance
interface, so that we can have a specific type (instead of any
) in our projects
default export axiosRateLimit (instead of export = axiosRateLimit;
). I had to turn on a compiler option (esModuleInterop
) to make axios-rate-limit work in modern es6 projects.
Thank you!
EDIT:
I've just seen this pull request: #19.
It seems like my second suggestion has already been fixed in 1.2.1. However, I still get that problem. What is the correct import statement in TypeScript now?
If you run this:
const http = rateLimit(axios.create(), { maxRequests: 4, perMilliseconds: 20000 })
http.get('http://localhost:4567/__sinatra__/404.png')
http.get('http://localhost:4567/__sinatra__/404.png')
http.get('http://localhost:4567/__sinatra__/404.png')
It will perform the three requests, and then the application will continue running for 20 seconds until the internal timeout is up.
I am working with several APIs on my app and a few of them have limits that are not just simply per sec.
For example one of my apis has the following limits:
So I have tried implementing it the following way:
axiosRateLimit(baseAxios.create(), {
maxRequests: 1, // 1
perMilliseconds: 1200 // per 1.2 seconds
// 100 requests per 2 minutes, 50 requests per 60 seconds, 60 seconds / 50 requests = 1 per 1.2 seconds
});
But it can't take advantage of the 20 requests per 1 second limit, because to adhere to the 100 requests per 2 minutes, I have to limit it to 1 per 1.2 seconds, otherwise if I limit it to 20 per second, I can do 2400 requests in 2 minutes.
So how can I implement both conditions and have them both working together?
What if I need to do only 50 requests every 2 minutes, with the current implementation, it will take me 1 minute for all of them, and I am not taking advantage of the 20 per second (becaus if I do, I can do it in 3 seconds, instead of 1 minute).
Is there a way to accomplish this with this library? Initially I thought that the maxRequests
works with perMilliseconds
and maxRPS
can be used to handle the other case, so when all 3 are supplied I thought it would be like:
{
maxRequests: 100, // 100 max requests
perMilliseconds: 2 * 60 * 1000, // per 2 minutes
maxRPS: 20 // 20 max per second
}
But the docs say:
// sets max 2 requests per 1 second, other will be delayed
// note maxRPS is a shorthand for perMilliseconds: 1000, and it takes precedence
// if specified both with maxRequests and perMilliseconds
const http = rateLimit(axios.create(), { maxRequests: 2, perMilliseconds: 1000, maxRPS: 2 })
So obviously it doesnt work the way I expected it to work, is there a way to achieve what I want?
Currently the axiosRateLimit
function is the only export from the module, but I would like to be able to share rate-limiting between axios clients. That is, I'd like to be able to do something like this:
import axios from 'axios';
import rateLimit, { AxiosRateLimiter } from 'axios-rate-limit'
const limiter = AxiosRateLimiter( { maxRequests: 2, perMilliseconds: 1000, maxRPS: 2 } );
const sheet1 = rateLimit(axios.create({ baseURL: `${SHEETS_API_BASE_URL}/${spreadsheetId1}` }), { rateLimiter: limiter});
const sheet2 = rateLimit(axios.create({ baseURL: `${SHEETS_API_BASE_URL}/${spreadsheetId2}` }), { rateLimiter: limiter});
So that both sheet1
and sheet2
are rate-limited as if they were a single rate limited axios client. I.e. if two requests are done in the same second on client1
, then a third request in the same second for client2
would be rate-limited into the next second.
From what I can see in the code, it's almost ready for that, as the axios
parameter in the constructor for AxiosRateLimit
is only used for the .enable()
call, and in there it's only used to .use()
the interceptors. And though it stores the return values of the .use()
calls, it doesn't actually do anything with them.
So, the below code block doesn't work for nodejs apps, may be you targeted the frontend env.
exports.__esModule = true
exports.name = 'axiosRateLimit'
exports.default = axiosRateLimit
Adding one more line for the nodejs type will do the job:
module.exports = axiosRateLimit
hey thanks for this great module!
quick note - the options for instantiating the module all show as required options, and also maxRPS is not present in the available options
so, for example, this fails with typescript:
const http = rateLimit(axios.create(), {
maxRPS: parseInt(process.env.ENV_VARIABLE, 10) || 50,
})
because:
maxRPS
is not an available option according to the typingsmaxRequests
and perMilliseconds
are not presentHey,
is it possible to change the maxRPS
on the fly?
I'm trying to:
response.data.length === 0
(response is empty) I want to cancel all other requests (using axios CancelToken
)client.setMaxRPS(100000)
before calling cancelToken.cancel()
Is it possible to change the RPS so the tokens get canceled faster / immediately?
Or do you guys suggest some simpler solution?
Thanks!
Thanks first for creating this tools, it was perfect for our use case!
We are using it in conjunction with https://github.com/RasCarlito/axios-cache-adapter, which allows us to cache some requests to speed up the process and reduce network trips.
The problem we have is that the cache requests count for the limit as well, is there a way to maybe expose a hook or similar to prevent a request counting for the limit if it was served from the cache? I can send a PR once we come up with the best solution.
This library has used the axios: ^0.18.0
as a devDependency to pull in the Axios while development.
package.json
to force relevant Axios version constraint as well.{
"dependencies": {
"axios": "^0.18.0",
}
}
This way your package will not be installed in the projects using axios: 1.13.0
.
I used your library to solve the rate limiting Issue in our project, But wasted an entire day as I relied on TS to tell me there wasn't any Error. Found out the Issue doing debugging the runtime values.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.