def finalize_response(self, response, record_request=True): """Handle and persist analytics data. @param {object} response: The Werkzeug Response object. @param {bool} record_request: Should this request be persisted? @returns {object}: A WSGI callable response object. If a 'bid' cookie (browser id) has not been set on this browser, we record the new browser in the datastore and set a bid cookie on this browser for future use. If the response is not an HTTP error, we set the cookie to expire a year from now. If `record_request` is True, we persist this request meta data in the datastore and reset the 'rid' (request id) cookie on the browser; which will expire at the end of the browser session. The cache header is set to tell the browser to cache the returned page for 4 days and keep an ETag for it. Lastly, we conditionally return a response body only if the ETag is not a match. """ browser_id = self.request.cookies.get("bid") browser = None request = None user_agent = None status = response.status_code status_ok = status >= 200 and status < 300 or status is 304 # Used to avoid datastore writes during automated testing. no_persist = self.no_persist response = self.set_default_headers(response) # TODO # if not browser_id: # We also send the browser_id as an ETag in some cases # etags = self.request.if_none_match # etag = len(etags) and etags.pop() or None # If ETag length > 32 (md5) it is a browser key and not a real ETag # browser_id = len(etag) > 32 and etag or None if not browser_id: user_agent = self.user_agent_repr browser = dstore.Browser( user_agent=user_agent, init_path=self.request.path, init_referrer=self.request.referrer, init_address=self.request.remote_addr, ) browser.put() browser_id = dstore.browser_key(browser) # Reset the browser id cookie if status_ok: response.set_cookie("bid", value=browser_id, expires=(int(time.time()) + 31556926)) # Exp in 1 year. if record_request: user_agent = user_agent or self.user_agent_repr request = dstore.Request( browser=browser_id, user_agent=user_agent, path=self.request.path, referrer=self.request.referrer, address=self.request.remote_addr, status=(response.status_code or 0), ) k = request.put() if status_ok: response.set_cookie("rid", value=str(k)) # Delete during automated testing. if browser and no_persist: browser.delete() if request and no_persist: request.delete() # Caching is private since we're always setting a cookie. response.headers["Cache-Control"] = "private, max-age=%d" % (86400 * 4) # Do this last for an accurate conditional response. response.add_etag() # Only send a response body if the E-Tag does not match. return response.make_conditional(self.request)
def finalize_response(self, response, record_request=True): browser_id = self.request.cookies.get('bid') browser = None request = None user_agent = None status = response.status_code status_ok = status >= 200 and status < 300 or status is 304 # Used to avoid datastore writes during automated testing. no_persist = self.no_persist response = set_common_headers(response) # TODO #if not browser_id: # We also send the browser_id as an ETag in some cases #etags = self.request.if_none_match #etag = len(etags) and etags.pop() or None # If ETag length > 32 (md5) it is a browser key and not a real ETag #browser_id = len(etag) > 32 and etag or None if not browser_id: user_agent = self.persist_user_agent browser = dstore.Browser(user_agent=user_agent , init_path=self.request.path , init_referrer=self.request.referrer , init_address=self.request.remote_addr) browser.put() browser_id = dstore.browser_key(browser) # Reset the browser id cookie if status_ok: response.set_cookie('bid', value=browser_id, expires=(int(time.time()) + 31556926)) # Exp in 1 year. if record_request: user_agent = user_agent or self.persist_user_agent request = dstore.Request(browser=browser_id , user_agent=user_agent , path=self.request.path , referrer=self.request.referrer , address=self.request.remote_addr , status=(response.status_code or 0)) k = request.put() if status_ok: response.set_cookie('rid', value=str(k)) # Delete during automated testing. if browser and no_persist: browser.delete() if request and no_persist: request.delete() # Caching is private since we're always setting a cookie. response.headers['Cache-Control'] = 'private, max-age=%d' % (86400 * 4) # Do this last for an accurate conditional response. response.add_etag() # Only send a response body if the E-Tag does not match. return response.make_conditional(self.request)