1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import calendar
6import datetime
7import json
8import logging
9import webapp2
10import zlib
11
12from google.appengine.api import memcache
13
14LOGGER = logging.getLogger(__name__)
15
16
17class DateTimeEncoder(json.JSONEncoder):
18    def default(self, obj):
19        if isinstance(obj, datetime.datetime):
20            return calendar.timegm(obj.timetuple())
21        # Let the base class default method raise the TypeError.
22        return json.JSONEncoder.default(self, obj)
23
24
25class AlertsHandler(webapp2.RequestHandler):
26    MEMCACHE_ALERTS_KEY = 'alerts'
27
28    # Has no 'response' member.
29    # pylint: disable=E1101
30    def send_json_headers(self):
31        self.response.headers.add_header('Access-Control-Allow-Origin', '*')
32        self.response.headers['Content-Type'] = 'application/json'
33
34    # Has no 'response' member.
35    # pylint: disable=E1101
36    def send_json_data(self, data):
37        self.send_json_headers()
38        self.response.write(data)
39
40    def generate_json_dump(self, alerts):
41        return json.dumps(alerts, cls=DateTimeEncoder, indent=1)
42
43    def get_from_memcache(self, memcache_key):
44        compressed = memcache.get(memcache_key)
45        if not compressed:
46            self.send_json_headers()
47            return
48        uncompressed = zlib.decompress(compressed)
49        self.send_json_data(uncompressed)
50
51    def get(self):
52        self.get_from_memcache(AlertsHandler.MEMCACHE_ALERTS_KEY)
53
54    # Has no 'response' member.
55    # pylint: disable=E1101
56    def post_to_memcache(self, memcache_key):
57        try:
58            alerts = json.loads(self.request.get('content'))
59        except ValueError:
60            warning = 'content field was not JSON'
61            self.response.set_status(400, warning)
62            LOGGER.warn(warning)
63            return
64        alerts.update({
65            'date': datetime.datetime.utcnow(),
66            'alerts': alerts['alerts']
67        })
68        uncompressed = self.generate_json_dump(alerts)
69        compression_level = 1
70        compressed = zlib.compress(uncompressed, compression_level)
71        memcache.set(memcache_key, compressed)
72
73    def post(self):
74        self.post_to_memcache(AlertsHandler.MEMCACHE_ALERTS_KEY)
75
76
77app = webapp2.WSGIApplication([
78    ('/alerts', AlertsHandler)
79])
80