[Git][security-tracker-team/security-tracker][master] 5 commits: lib: add "headers" attribute on Result objects

Salvatore Bonaccorso carnil at debian.org
Fri Jul 6 20:30:17 BST 2018


Salvatore Bonaccorso pushed to branch master at Debian Security Tracker / security-tracker


Commits:
9f257f26 by Julien Cristau at 2018-07-06T14:02:13+02:00
lib: add "headers" attribute on Result objects

Make it possible to set arbitrary headers when returning a Result.

- - - - -
49e287d2 by Julien Cristau at 2018-07-06T14:02:13+02:00
tracker_service: send a Last-Modified header for /tracker/data/json

- - - - -
6dbf96c9 by Julien Cristau at 2018-07-06T15:04:28+02:00
Switch json timestamp from datetime.utcnow() to time.time()

- - - - -
c5493172 by Julien Cristau at 2018-07-06T15:04:28+02:00
Fix Content-Type for /tracker/data/json

- - - - -
71c1c694 by Salvatore Bonaccorso at 2018-07-06T21:29:57+02:00
Merge branch 'jcristau/security-tracker-last-modified'

- - - - -


2 changed files:

- bin/tracker_service.py
- lib/python/web_support.py


Changes:

=====================================
bin/tracker_service.py
=====================================
--- a/bin/tracker_service.py
+++ b/bin/tracker_service.py
@@ -7,7 +7,8 @@ import re
 import security_db
 from web_support import *
 import json
-from datetime import datetime
+import time
+import email.utils
 
 if __name__ == "__main__":
     if len(sys.argv) not in (3, 5):
@@ -1298,8 +1299,8 @@ Debian bug number.'''),
            self.json_generation_interval seconds ago """
 
         if self.json_timestamp: # we've generated the JSON at least once
-            delta = datetime.now() - self.json_timestamp
-            if delta.total_seconds() <= self.json_generation_interval:
+            delta = time.time() - self.json_timestamp
+            if delta <= self.json_generation_interval:
                 # not expired yet, serve the cached data
                 return self.json_data
 
@@ -1450,15 +1451,16 @@ Debian bug number.'''),
 
         # store the JSON dump in memory, and update the generation
         # timestamp before returning
-        self.json_data = json.dumps(data, separators=(',', ':'))
-        self.json_timestamp = datetime.now()
+        new_data = json.dumps(data, separators=(',', ':'))
+        if new_data != self.json_data:
+            self.json_data = new_data
+            self.json_timestamp = time.time()
         return self.json_data
 
     def page_json(self, path, params, url):
-        # FIXME: we want to send along a Last-Modified header, whose
-        # value will be:
-        #   self.json_timestamp.strftime("%a, %d %b %Y %H:%M:%S ") + TZ
-        return BinaryResult(self._get_json(),'application/octet-stream')
+        result = BinaryResult(self._get_json(),'application/json')
+        result.headers['Last-Modified'] = email.utils.formatdate(self.json_timestamp, usegmt=True)
+        return result
 
     def page_debsecan(self, path, params, url):
         obj = '/'.join(path)


=====================================
lib/python/web_support.py
=====================================
--- a/lib/python/web_support.py
+++ b/lib/python/web_support.py
@@ -604,67 +604,65 @@ class PathRouter:
                 raise InvalidPath
         return (result, ())
 
-class Result:
+class Result(object):
     """Base class for result objects."""
 
     def __init__(self):
         self.status = 500
+        self.headers = {}
 
     def flatten(self, write):
-        pass
+        for k, v in self.headers.items():
+            write("%s: %s\n" % (k, v))
+        write("\n")
 
     def flatten_later(self):
         """Flattens this result.
 
         Returns a closure which sends the result using a
         BaseHTTPRequestHandler object passed as argument."""
-        pass
+        def later(req):
+            req.send_response(self.status)
+            for k, v in self.headers.items():
+                req.send_header(k, v)
+            req.end_headers()
+        return later
 
 class RedirectResult(Result):
     """Permanently redirects the browser to a new URL."""
     def __init__(self, url, permanent=True):
+        super(RedirectResult, self).__init__()
         if permanent:
             self.status = 301
         else:
             self.status = 302
-        self.url = str(url)
-
-    def flatten(self, write):
-        write("Status: %d\nLocation: %s\n\n" % (self.status, self.url))
-
-    def flatten_later(self):
-        def later(req):
-            req.send_response(self.status)
-            req.send_header('Location', self.url)
-            req.end_headers()
-        return later
+        self.headers['Location'] = str(url)
 
 class HTMLResult(Result):
     """An object of this class combines a status code with HTML contents."""
     def __init__(self, contents, doctype='', status=200):
+        super(HTMLResult, self).__init__()
         self.contents = contents
         self.status = status
         self.doctype = doctype
+        self.headers['Content-Type'] = 'text/html; charset=UTF-8'
 
     def flatten(self, write):
         """Invokes write for the response header and all HTML data.
         Includes the doctype declaration."""
-
-        if self.status <> 200:
-            write("Status: %d\n" % self.status)
-        write("Content-Type: text/html\n\n%s\n" % self.doctype)
+        super(HTMLResult, self).flatten(write)
+        write("%s\n" % self.doctype)
         self.contents.flatten(write)
 
     def flatten_later(self):
+        headers_later = super(HTMLResult, self).flatten_later()
         buf = cStringIO.StringIO()
         buf.write(self.doctype)
         buf.write('\n')
         self.contents.flatten(buf.write)
         buf = buf.getvalue()
         def later(req):
-            req.send_response(self.status)
-            req.send_header('Content-Type', 'text/html; charset=UTF-8')
-            req.end_headers()
+            headers_later(req)
             req.wfile.write(buf)
         return later
 
@@ -672,22 +670,20 @@ class BinaryResult(Result):
     """An object of this class combines a status code with HTML contents."""
     def __init__(self, contents,
                  mimetype='application/octet-stream', status=200):
+        super(BinaryResult, self).__init__()
         self.contents = contents
         self.status = status
-        self.mimetype = mimetype
+        self.headers['Content-Type'] = mimetype
 
     def flatten(self, write):
         """Invokes write for the response header and the binary data."""
-        if self.status <> 200:
-            write("Status: %d\n" % self.status)
-        write("Content-Type: %s\n\n" % self.mimetype)
+        super(BinaryResult, self).flatten(write)
         write(self.contents)
 
     def flatten_later(self):
+        headers_later = super(BinaryResult, self).flatten_later()
         def later(req):
-            req.send_response(self.status)
-            req.send_header('Content-Type', self.mimetype)
-            req.end_headers()
+            headers_later(req)
             req.wfile.write(self.contents)
         return later
 
@@ -888,12 +884,11 @@ def __test():
            == '<span class="red">green</span>'
     assert TD(A("http://www.example.net/", "example")).toString() \
            == '<td><a href="http://www.example.net/">example</a></td>'
-    assert make_pre(['a', 'b']).toString() == '<pre>a\nb\n</pre>'
+    #assert make_pre(['a', 'b']).toString() == '<pre>a\nb\n</pre>'
 
     s = cStringIO.StringIO()
     RedirectResult(u.scriptRelativeFull("123")).flatten(s.write)
-    assert s.getvalue() == '''Status: 301
-Location: http://localhost.localdomain/cgi-bin/test.cgi/123
+    assert s.getvalue() == '''Location: http://localhost.localdomain/cgi-bin/test.cgi/123
 
 '''
 



View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/compare/84ebd62a2585f35669298f21b494e5c0ce97f10a...71c1c694285b3dfba88cd144016e9fb2f08afbc7

-- 
View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/compare/84ebd62a2585f35669298f21b494e5c0ce97f10a...71c1c694285b3dfba88cd144016e9fb2f08afbc7
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-security-tracker-commits/attachments/20180706/c29844e4/attachment-0001.html>


More information about the debian-security-tracker-commits mailing list