diff --git a/README.md b/README.md index 269f299..224a039 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ You can set these up locally by simply copying `sample.env` to `.env` and changi ### 0.3.9 +* Improvement: Added a Retry-After header as suggested by the HTTP docs for HTTP code 503 for when the throttle cap is reached. The Retry-After header indicates when the site is available for the client again, which is implemented as when the all of the queued fetches are expected to have been made. + ### 0.3.8 * Bug fix: Shouldn't fail on pages with non-http(s) links like mailto: diff --git a/lib/classes/webmentionping.js b/lib/classes/webmentionping.js index 5009aba..1a526cb 100644 --- a/lib/classes/webmentionping.js +++ b/lib/classes/webmentionping.js @@ -54,6 +54,14 @@ throttleByKey = function (key, onWaitCallback) { console.log('Reached throttle cap of', options.throttleCap, 'for key:', key); err = new Error('Too many mentions from source host at the moment.'); err.status = 503; + // Suggest that they ping again once we have emptied the queue so that we can fill it back up again + // The requests will get throttled right away if they do this, but it will ensure that we utilize + // the defined throttleSpan to the fullest and never stand idle for a millisecond. + // + // This should perhaps be set to just the time when there's any free spot in the queue at all, even + // if that would mean that the throttleCap would be reached immediately again. Would follow the spec + // more closely though: http://tools.ietf.org/html/rfc7231#section-7.1.3 + err.retryAfter = Math.ceil(((time + throttledKeys[key] - 1) * options.throttleSpan - now) / 1000); reject(err); return; diff --git a/lib/routes/api.js b/lib/routes/api.js index 723380b..9ef32ce 100644 --- a/lib/routes/api.js +++ b/lib/routes/api.js @@ -129,6 +129,10 @@ pingErrorResponse = function (res, err) { response.message = err.message; } + if (err.status === 503 && err.retryAfter) { + res.set('Retry-After', err.retryAfter); + } + res.format({ 'application/json': function () { res.send(status, response);