Skip to content

Commit 3f1a90c

Browse files
committed
usage limits / alerts
1 parent 930e400 commit 3f1a90c

File tree

5 files changed

+44
-7
lines changed

5 files changed

+44
-7
lines changed

bin.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ def get(self):
3131

3232
def post(self):
3333
bin = self._get_bin(self.request.path)
34-
self._record_post(bin)
34+
post = self._record_post(bin)
3535
# TODO: This should maybe be a header thing
3636
if 'http://' in self.request.query_string:
3737
params = dict(self.request.POST.items())
3838
params['_url'] = self.request.query_string
3939
urlfetch.fetch(url='http://hookah.progrium.com/dispatch',
4040
payload=urllib.urlencode(params), method='POST')
41-
taskqueue.add(url='/tasks/newpost', params={})
41+
taskqueue.add(url='/tasks/newpost', params={'ip': post.remote_addr, 'size': post.size, 'bin': bin.name})
4242
self.response.set_status(201)
4343
self.response.headers['Location'] = str("/%s" % bin.name)
4444
self.response.out.write('<html><head><meta http-equiv="refresh" content="0;url=/%s" /></head><body>201 Created. Redirecting...</body></html>' % bin.name)
@@ -81,6 +81,7 @@ def _record_post(self, bin, use_get=False):
8181
else:
8282
post.form_data.append([k,v])
8383
post.put()
84+
return post
8485

8586
def _get_bin(self, path):
8687
name = path[1:].split('/')[0]

dos.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ blacklist:
44
- subnet: 67.202.28.20
55
description: tenu8x - Posts too big for datastore API - 9 reqs/min - Aug 7 2010
66
- subnet: 67.202.11.14
7-
description: 1g6plqt - Too much too quickly and pushed us over quota - 15 reqs/min - October 20 2010
7+
description: 1g6plqt - Too much too quickly and pushed us over quota - 15 reqs/min - October 20 2010
8+
- subnet: 107.20.169.236
9+
description: IP exceeded 500MB transfer in 24 hours

main.py

+20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from google.appengine.ext.webapp import template
55
from models import Bin, Post, App
66
from google.appengine.api import datastore_errors
7+
from google.appengine.api import memcache
8+
from google.appengine.api import mail
79
from google.appengine.runtime import DeadlineExceededError
810
import time, yaml
911

@@ -54,6 +56,24 @@ def post(self):
5456
app = App.instance()
5557
app.total_posts += 1
5658
app.put()
59+
ip = self.request.get('ip')
60+
bin = self.request.get('bin')
61+
size = int(self.request.get('size'))
62+
day = datetime.datetime.now().day
63+
64+
daily_ip_key = 'usage-%s-%s' % (day, ip)
65+
daily_ip_usage = memcache.get(daily_ip_key) or 0
66+
memcache.set(daily_ip_key, int(daily_ip_usage)+size, time=24*3600)
67+
if daily_ip_usage > 500000000: # about 500MB
68+
mail.send_mail(sender="[email protected]", to="[email protected]",
69+
subject="PostBin user IP over quota", body=ip)
70+
71+
daily_bin_key = 'usage-%s-%s' % (day, bin)
72+
daily_bin_usage = memcache.get(daily_bin_key) or 0
73+
memcache.set(daily_bin_key, int(daily_bin_usage)+size, time=24*3600)
74+
if daily_bin_usage > 10485760: # 10MB
75+
obj = Bin.get_by_name(bin)
76+
obj.delete()
5777

5878
if __name__ == '__main__':
5979
wsgiref.handlers.CGIHandler().run(webapp.WSGIApplication([

models.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import time, yaml
1+
import time
2+
import yaml
3+
import datetime
24
from google.appengine.ext import db
35
from google.appengine.api import datastore_types
6+
from google.appengine.api import memcache
47
from django.utils import simplejson
58

69

@@ -44,7 +47,18 @@ class Bin(db.Model):
4447
def __init__(self, *args, **kwargs):
4548
kwargs['name'] = kwargs.get('name', baseN(abs(hash(time.time())), 36))
4649
super(Bin, self).__init__(*args, **kwargs)
47-
50+
51+
@classmethod
52+
def get_by_name(cls, name):
53+
return Bin.all().filter('name =', name).get()
54+
55+
def usage_today_in_bytes(self):
56+
day = datetime.datetime.now().day
57+
daily_bin_key = 'usage-%s-%s' % (day, self.name)
58+
return memcache.get(daily_bin_key) or 0
59+
60+
def usage_today_in_megabytes(self):
61+
return self.usage_today_in_bytes() / 1048576
4862

4963
class Post(db.Model):
5064
bin = db.ReferenceProperty(Bin)

templates/bin.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{% block title %}PostBin - {{ bin.name }}{% endblock %}
33
{% block header %}<link href="/{{ bin.name }}/feed" type="application/atom+xml" rel="alternate" title="Feed of PostBin {{ bin.name }}" />{% endblock %}
44
{% block content %}
5-
<p>All POST requests to this URL are logged for you to see here, sorted newest to oldest.</p>
5+
<p>All POST requests to this URL are logged for you to see here, sorted newest to oldest.</p>
66
{% for post in posts %}
77
<div class="post">
88
<a href="#{{ post.id }}" title="A unique ID for this request">#{{ post.id }}</a> @
@@ -35,7 +35,7 @@
3535
</table>
3636
</div>
3737
{% endfor %}
38-
38+
<p>If over 10MB of data is posted in a day, this bin will be deleted. Current usage today: <strong>{{bin.usage_today_in_megabytes}}MB</strong></p>
3939
<a href="/">&larr; Home</a>
4040
<a href="/{{ bin.name }}/feed" style="display: block; float: right;">Atom Feed</a>
4141
{% endblock %}

0 commit comments

Comments
 (0)