Skip to content

Instantly share code, notes, and snippets.

@whisher
Created November 7, 2015 20:10

Revisions

  1. whisher created this gist Nov 7, 2015.
    61 changes: 61 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,61 @@
    'use strict';

    /**
    * Module dependencies.
    */
    const Hoek = require('hoek');
    const Limiter = require('ratelimiter');
    const RedisClient = require('../utils/redis');
    const ReplyUtil = require('../utils/reply');

    const internals = {};
    internals.defaults = {
    namespace: 'hrl',
    global: {
    limit: -1,
    duration: 1
    }
    };
    const MILLISECONDS = 1000;

    exports.register = (server, options, next) => {
    const settings = Hoek.applyToDefaults(internals.defaults, options);
    server.ext('onPreAuth', (request, reply) => {
    const route = request.route;
    const currentSettings = route.settings.plugins && route.settings.plugins['hapi-rate-limit'];
    if (currentSettings) {
    const routeSettings = Hoek.applyToDefaults(settings.global, currentSettings);
    const id = settings.namespace + ':' + request.info.remoteAddress + ':' + route.path;
    const limiter = new Limiter({
    id: id,
    db: RedisClient,
    max: routeSettings.limit,
    duration: routeSettings.duration * MILLISECONDS
    });
    limiter.get((err, limit) => {
    if (err) {
    return reply(err);
    }
    request.plugins['hapi-rate-limit'] = {};
    request.plugins['hapi-rate-limit'].limit = limit.total;
    request.plugins['hapi-rate-limit'].remaining = limit.remaining - 1;
    request.plugins['hapi-rate-limit'].reset = limit.reset;
    if (limit.remaining <= 0) {
    const error = ReplyUtil.tooManyRequests();
    error.output.headers['X-RateLimit-Limit'] = request.plugins['hapi-rate-limit'].limit;
    error.output.headers['X-RateLimit-Remaining'] = request.plugins['hapi-rate-limit'].remaining;
    error.output.headers['X-RateLimit-Reset'] = request.plugins['hapi-rate-limit'].reset;
    return reply(error);
    }
    return reply.continue();
    });
    } else {
    return reply.continue();
    }
    });
    return next();
    };
    exports.register.attributes = {
    name: 'hapi-rate-limit',
    version: '1.0.0'
    };