thelinmichael / spotify-web-api-node

A Node.js wrapper for Spotify's Web API.
http://thelinmichael.github.io/spotify-web-api-node/
MIT License
3.11k stars 497 forks source link

Throttle HTTP requests #149

Closed epsil closed 7 years ago

epsil commented 7 years ago

Is there a way to throttle HTTP requests?

I note that this project depends on superagent in order to make HTTP requests. superagent has a plugin, superagent-throttle, which allows one to adjust how many requests can be sent in a given time interval.

Off the bat, there are a number of implementation possibilities:

  1. Add throttling options directly to spotify-web-api-node.
  2. Expose spotify-web-api-node's superagent instance to end users.
  3. Make the superagent instance replaceable via dependency injection.

The motivation for throttling is that Spotify's web API employs rate limits. The documentation doesn't say much about what these limits are, but describes them as follows:

To make the API fast for everybody, rate limits apply.

Rate limiting is applied on an application basis (based on client id), regardless of how many users are using it.

A way to reduce the amount of requests is to use endpoints that fetch multiple entities. If you are making many requests to get single tracks, albums or artists, you can use endpoints such as Get Several Tracks, Get Several Albums or Get Several Artists instead.

If you get status code 429, it means that you have sent too many requests. If this happens, have a look in the Retry-After header, where you will see a number displayed. This is the amount of seconds that you need to wait, before you can retry sending your requests.

If one oversteps one's bounds, one may receive an error like the following:

[WebapiError: Too Many Requests]
{
  "name": "WebapiError",
  "message": "Too Many Requests",
  "statusCode": 429
}

To offer a practical example: in my own project, a Spotify playlist generator, I access the web API rather frequently. To avoid overload, I currently wrap each HTTP request in a setTimeout() call with a delay set to 100 ms. I would very much like to make the jump to spotify-web-api-node and leave my own implementation behind, but I need to make sure that my request-intensive code will not cause problems down the line.

This might be related to issue #140.

JMPerez commented 7 years ago

One option would be to have this built in, but we tried to keep the library as light as possible. What I have recommended in the past is to use something like https://github.com/JMPerez/promise-throttle. You can see an example of the library used together with the client-side Spotify JS wrapper on https://github.com/JMPerez/spotify-dedup/blob/b6091581e3700ccbb1e5a0e26dbb59422fa3d15f/app/scripts/main.js#L80.