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