Adapt authoring tool UI documentation

v1.0.0-rc.4

adapt-authoring-ratelimiter/lib/RateLimiterModule.js

  1. import { AbstractModule } from 'adapt-authoring-core'
  2. import { RateLimiterMongo } from 'rate-limiter-flexible'
  3. /**
  4. * Module for rate-limiting access to the API
  5. * @memberof ratelimiter
  6. * @extends {AbstractModule}
  7. */
  8. class RateLimiterModule extends AbstractModule {
  9. /** @override */
  10. async init () {
  11. const mongodb = await this.app.waitForModule('mongodb')
  12. const { db } = await mongodb.getStats()
  13. /**
  14. * Reference to the rate limiter instance
  15. * @type {external:RateLimiterFlexible}
  16. */
  17. this.rateLimiter = new RateLimiterMongo({
  18. storeClient: mongodb.client,
  19. dbName: db,
  20. keyPrefix: 'ratelimiter',
  21. points: this.getConfig('apiRequestLimit'),
  22. duration: this.getConfig('apiRequestLimitDuration') / 1000
  23. })
  24. const server = await this.app.waitForModule('server')
  25. server.api.addMiddleware(this.middleware())
  26. }
  27. /**
  28. * Limits the number of requests that can be made to the API
  29. * @return {Function} An Express.js request handler
  30. */
  31. middleware () {
  32. return async (req, res, next) => {
  33. try {
  34. const data = await this.rateLimiter.consume(req.ip)
  35. res.set({
  36. 'Retry-After': data.msBeforeNext / 1000,
  37. 'X-RateLimit-Limit': this.getConfig('apiRequestLimit'),
  38. 'X-RateLimit-Remaining': data.remainingPoints,
  39. 'X-RateLimit-Reset': new Date(Date.now() + data.msBeforeNext)
  40. })
  41. next()
  42. } catch (e) {
  43. res.sendError(this.app.errors.RATE_LIMIT_EXCEEDED)
  44. }
  45. }
  46. }
  47. }
  48. export default RateLimiterModule