Last active
December 20, 2015 08:19
-
-
Save ecin/6100136 to your computer and use it in GitHub Desktop.
How to add a Rails routes helper (tightly-coupled version).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/extensions/action_dispatch/routing/mapper.rb | |
module ActionDispatch | |
module Routing | |
class Mapper | |
module Resources | |
alias_method :old_add_route, :add_route | |
def add_route(action, options) | |
if @scope[:throttle] | |
throttlers = @scope.delete(:throttle) | |
throttlers.each do |throttler| | |
throttle_options = options.dup | |
throttle_options[:constraints] = throttler.method(:matches?).to_proc | |
throttle_options[:to] = throttler.method(:call).to_proc | |
old_add_route(action, throttle_options) | |
end | |
end | |
old_add_route(action, options) | |
end | |
end | |
module Scoping | |
def throttle(throttler) | |
scope(:throttle => throttler) { yield } | |
end | |
private | |
def merge_throttle_scope(parent, child) | |
merged = parent ? parent.dup : [] | |
merged << child if child | |
merged | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/routes.rb | |
Your::Application.routes.draw do | |
class IPThrottler | |
class << self | |
@cache = {} | |
attr_reader :cache | |
end | |
def initialize(ttl = 1.seconds) | |
@ttl = ttl | |
end | |
def matches?(request) | |
cache[request.ip] ||= Time.now | |
# If @ttl time hasn't passed since the last request, throttle it. | |
Time.now - cache[request.ip] > @ttl | |
end | |
def call(env) | |
[429, {}, "Too Many Requests"] | |
end | |
def cache | |
self.class.cache | |
end | |
end | |
# Return 429 status code if 2 seconds haven't passed since the last request (per IP) | |
throttle IPThrottler.new(2.seconds) do | |
get "/expensive", "application#expensive_action" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment