mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-04-05 03:00:15 -04:00
Use HTTP code 429 "Too Many Requests" when throttling.
This commit is contained in:
@@ -42,6 +42,17 @@ from cStringIO import StringIO
|
||||
import sys, tempfile, urllib, re, os, sha, subprocess
|
||||
from httplib import HTTPConnection
|
||||
|
||||
# hack in Paste support for HTTP 429 "Too Many Requests"
|
||||
from paste import httpexceptions, wsgiwrappers
|
||||
|
||||
class HTTPTooManyRequests(httpexceptions.HTTPClientError):
|
||||
code = 429
|
||||
title = 'Too Many Requests'
|
||||
explanation = ('The server has received too many requests from the client.')
|
||||
|
||||
httpexceptions._exceptions[429] = HTTPTooManyRequests
|
||||
wsgiwrappers.STATUS_CODE_TEXT[429] = HTTPTooManyRequests.title
|
||||
|
||||
#from pylons.middleware import error_mapper
|
||||
def error_mapper(code, message, environ, global_conf=None, **kw):
|
||||
from pylons import c
|
||||
@@ -52,7 +63,7 @@ def error_mapper(code, message, environ, global_conf=None, **kw):
|
||||
|
||||
if global_conf is None:
|
||||
global_conf = {}
|
||||
codes = [304, 401, 403, 404, 503]
|
||||
codes = [304, 401, 403, 404, 429, 503]
|
||||
if not asbool(global_conf.get('debug')):
|
||||
codes.append(500)
|
||||
if code in codes:
|
||||
|
||||
@@ -72,13 +72,32 @@ redditbroke = \
|
||||
'''
|
||||
|
||||
toofast = \
|
||||
'''<html>
|
||||
<head><title>service temporarily unavailable</title></head>
|
||||
'''<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Too Many Requests</title>
|
||||
<style>
|
||||
body { font: small verdana, arial, helvetica, sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
the service you request is temporarily unavailable. please try again later.
|
||||
<h1>whoa there, pardner!</h1>
|
||||
<p>reddit's awesome and all, but you may have a bit of a
|
||||
problem. we've seen far too many requests come from your ip address
|
||||
recently.</p>
|
||||
<p>if you think that we've incorrectly blocked you or you would like
|
||||
to discuss easier ways to get the data you want, please contact us
|
||||
any of the following ways.</p>
|
||||
<ul>
|
||||
<li><a href="http://webchat.freenode.net/?channels=reddit-dev">#reddit-dev on freenode</a></li>
|
||||
<li><a href="http://groups.google.com/group/reddit-dev">the reddit-dev google group</a></li>
|
||||
<li><a href="mailto:ratelimit@reddit.com">ratelimit@reddit.com</a></li>
|
||||
</ul>
|
||||
<p>as a reminder, we recommend that clients make no more than one
|
||||
request every two seconds to avoid being blocked like this.</p>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
'''
|
||||
|
||||
class ErrorController(RedditController):
|
||||
"""Generates error documents as and when they are required.
|
||||
@@ -146,6 +165,10 @@ class ErrorController(RedditController):
|
||||
else:
|
||||
return pages.Reddit404().render()
|
||||
|
||||
def send429(self):
|
||||
c.response.status_code = 429
|
||||
return toofast
|
||||
|
||||
def send503(self):
|
||||
c.response.status_code = 503
|
||||
if 'retry_after' in request.environ:
|
||||
@@ -186,6 +209,8 @@ class ErrorController(RedditController):
|
||||
return pages.TakedownPage(link).render()
|
||||
elif code == 403:
|
||||
return self.send403()
|
||||
elif code == 429:
|
||||
return self.send429()
|
||||
elif code == 500:
|
||||
randmin = {'admin': rand.choice(self.admins)}
|
||||
failien_name = 'youbrokeit%d.png' % rand.randint(1, NUM_FAILIENS)
|
||||
|
||||
@@ -419,7 +419,7 @@ def ratelimit_agents():
|
||||
if s and user_agent and s in user_agent.lower():
|
||||
key = 'rate_agent_' + s
|
||||
if g.cache.get(s):
|
||||
abort(503, 'service temporarily unavailable')
|
||||
abort(429)
|
||||
else:
|
||||
g.cache.set(s, 't', time = 1)
|
||||
|
||||
@@ -430,7 +430,7 @@ def ratelimit_throttled():
|
||||
ip, slash16 = ip_and_slash16(request)
|
||||
|
||||
if throttled(ip) or throttled(slash16):
|
||||
abort(503, 'service temporarily unavailable')
|
||||
abort(429)
|
||||
|
||||
|
||||
def paginated_listing(default_page_size=25, max_page_size=100, backend='sql'):
|
||||
@@ -616,7 +616,7 @@ class MinimalController(BaseController):
|
||||
and request.method.upper() == 'GET'
|
||||
and (not c.user_is_loggedin or c.allow_loggedin_cache)
|
||||
and not c.used_cache
|
||||
and response.status_code != 503
|
||||
and response.status_code not in (429, 503)
|
||||
and response.content and response.content[0]):
|
||||
try:
|
||||
g.rendercache.set(self.request_key(),
|
||||
|
||||
Reference in New Issue
Block a user