work on #2693 Separate API Limits by Writes/Reads

This commit is contained in:
Albert Yi
2016-10-17 16:27:03 -07:00
parent ced7a34afa
commit 87447a51c3
3 changed files with 41 additions and 16 deletions

View File

@@ -41,7 +41,7 @@ protected
def api_check
if request.format.to_s =~ /\/json|\/xml/ || params[:controller] == "iqdb"
if ApiLimiter.throttled?(request.remote_ip)
if ApiLimiter.throttled?(request.remote_ip, request.request_method)
render :text => "421 User Throttled\n", :layout => false, :status => 421
return false
end

View File

@@ -1,15 +1,26 @@
module ApiLimiter
def throttled?(ip_addr)
key = "#{ip_addr}:#{Time.now.hour}"
MEMCACHE.fetch(key, 1.hour, :raw => true) {0}
MEMCACHE.incr(key).to_i > CurrentUser.user.api_hourly_limit
def idempotent?(method)
case method
when "POST", "PUT", "DELETE"
false
else
true
end
end
def remaining_hourly_limit(ip_addr)
key = "#{ip_addr}:#{Time.now.hour}"
def throttled?(ip_addr, http_method = "GET")
idempotent = idempotent?(http_method)
key = "api/#{ip_addr}/#{Time.now.hour}/#{idempotent}"
MEMCACHE.fetch(key, 1.hour, :raw => true) {0}
MEMCACHE.incr(key).to_i > CurrentUser.user.api_hourly_limit(idempotent)
end
def remaining_hourly_limit(ip_addr, idempotent = true)
key = "api/#{ip_addr}/#{Time.now.hour}/#{idempotent}"
requests = MEMCACHE.fetch(key, 1.hour, :raw => true) {0}.to_i
CurrentUser.user.api_hourly_limit - requests
end
module_function :throttled?, :remaining_hourly_limit
module_function :throttled?, :idempotent?, :remaining_hourly_limit
end

View File

@@ -611,20 +611,34 @@ class User < ActiveRecord::Base
end
end
def api_hourly_limit
if is_platinum? && api_key.present?
20_000
def api_hourly_limit(idempotent = true)
base = if is_platinum? && api_key.present?
2000
elsif is_gold? && api_key.present?
10_000
1000
else
3_000
300
end
if idempotent
base * 10
else
base
end
end
def remaining_api_hourly_limit
ApiLimiter.remaining_hourly_limit(CurrentUser.ip_addr)
ApiLimiter.remaining_hourly_limit(CurrentUser.ip_addr, true)
end
def remaining_api_hourly_limit_read
ApiLimiter.remaining_hourly_limit(CurrentUser.ip_addr, true)
end
def remaining_api_hourly_limit_write
ApiLimiter.remaining_hourly_limit(CurrentUser.ip_addr, false)
end
def statement_timeout
if is_platinum?
9_000
@@ -644,7 +658,7 @@ class User < ActiveRecord::Base
def method_attributes
list = [:is_banned, :can_approve_posts, :can_upload_free, :is_super_voter, :level_string]
if id == CurrentUser.user.id
list += [:remaining_api_hourly_limit]
list += [:remaining_api_hourly_limit, :remaining_api_hourly_limit_read, :remaining_api_hourly_limit_write]
end
list
end