1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
"""Simple WSGI script to store the usage reports.
"""
import os
import re
import time
DESTINATION = '.' # Current directory
MAX_SIZE = 524288 # 512 KiB
date_format = re.compile(br'^[0-9]{2,12}\.[0-9]{1,3}$')
def store(report, address):
"""Stores the report on disk.
"""
now = time.time()
secs = int(now)
msecs = int((now - secs) * 1000)
submitted_date = filename = None # avoids warnings
while True:
submitted_date = '%d.%03d' % (secs, msecs)
filename = 'report_%s.txt' % submitted_date
filename = os.path.join(DESTINATION, filename)
if not os.path.exists(filename):
break
msecs += 1
lines = [l for l in report.split(b'\n') if l]
for line in lines:
if line.startswith(b'date:'):
date = line[5:]
if date_format.match(date):
with open(filename, 'wb') as fp:
if not isinstance(address, bytes):
address = address.encode('ascii')
fp.write(b'submitted_from:' + address + b'\n')
fp.write(('submitted_date:%s\n' % submitted_date)
.encode('ascii'))
fp.write(report)
return None
else:
return "invalid date"
return "missing date field"
def application(environ, start_response):
"""WSGI interface.
"""
def send_response(status, body):
if not isinstance(body, bytes):
body = body.encode('utf-8')
start_response(status, [('Content-Type', 'text/plain'),
('Content-Length', '%d' % len(body))])
return [body]
if environ['REQUEST_METHOD'] != 'POST':
return send_response('403 Forbidden', "invalid request")
# Gets the posted input
try:
request_body_size = int(environ['CONTENT_LENGTH'])
except (KeyError, ValueError):
return send_response('400 Bad Request', "invalid content length")
if request_body_size > MAX_SIZE:
return send_response('403 Forbidden', "report too big")
request_body = environ['wsgi.input'].read(request_body_size)
# Tries to store
response_body = store(request_body, environ.get('REMOTE_ADDR'))
if not response_body:
status = '200 OK'
response_body = "stored"
else:
status = '501 Server Error'
# Sends the response
return send_response(status, response_body)
if __name__ == '__main__':
use_werkzeug = os.environ.get('USAGESTATS_SERVER_USE_WERKZEUG', 'no')
if use_werkzeug.lower() in ('yes', '1', 'y', 'on', 'true'):
from werkzeug.serving import run_simple
run_simple('localhost', 8000, application)
else:
from twisted.internet import reactor
from twisted.web import server
from twisted.web.wsgi import WSGIResource
resource = WSGIResource(reactor, reactor.getThreadPool(), application)
site = server.Site(resource)
reactor.listenTCP(8000, site)
reactor.run()
|