[Twisted-Python] [PATCH] Accept and accept-language parsing

mattam at netcourrier.com mattam at netcourrier.com
Sat Sep 21 19:23:43 EDT 2002


Hi twisters,

	here's a patch for parsing accept and accept-language HTTP headers.
	They are contained in a priority queue which can also be
	retrieved as a list. Perhaps some other methods could be
	convenient, but as it's late I let you advise which. I added a
	parseHeaders() method for Request which is called just after 
	parseCookies() in HTTPChannel.allHeadersReceived.


Bye!

M at t


-------------- next part --------------
--- twisted/python/priorityqueue.py.orig	2002-09-22 00:39:08.000000000 +0200
+++ twisted/python/priorityqueue.py	2002-09-22 00:35:38.000000000 +0200
@@ -0,0 +1,70 @@
+
+# Twisted, the Framework of Your Internet
+# Copyright (C) 2001 Matthew W. Lefkowitz
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+""" A priority queue. """
+
+class PriorityQueue:
+
+    """
+    Elements are ordered using the comparison function f,
+    which return value is negative if x < y, 0 if x == y
+    and positive if x > y.
+
+    """     
+    
+    def __init__(self, comparison):
+        self.list = []
+        self.cmpf = comparison
+
+    def add_elements(self, priority, elements):
+        """ Add a sequenct of elements at the given priority """
+
+        length = len(self.list)        
+        if length == 0:
+            self.list = [(priority, list(elements))]
+        else:
+            res = self.cmpf(priority, self.list[0][0])
+            if res > 0:
+                self.list = [(priority, list(elements))] + self.list
+            elif res == 0:
+                self.list[0] = (priority, self.list[0][1] + list(elements))
+            else:
+                i = 1
+                while i < length and self.cmpf(priority, self.list[i][0]) < 0:
+                    i += 1
+                if i == length:
+                    self.list.append((priority, list(elements)))
+                elif self.cmpf(self.list[i][0], priority) == 0:
+                    self.list[i] = (priority, self.list[i][1] + list(elements))
+                else: 
+                    # self.list[i][0] < priority
+                    tmp = self.list[i:]
+                    
+                    self.list = self.list[:i] + [(priority, list(elements))]
+                    
+                    if tmp is not None:
+                        self.list = self.list + tmp
+    
+    def add(self, priority, element):
+        self.add_elements(priority, [element])
+        
+    def getlist(self):
+        """ I return the list of elements in decreasing order """
+        res = []
+        for prio, elems in self.list:
+            res += elems
+        return res
--- twisted/protocols/http.py.orig	2002-09-22 00:01:53.000000000 +0200
+++ twisted/protocols/http.py	2002-09-22 00:42:16.000000000 +0200
@@ -36,7 +36,7 @@
 
 # twisted imports
 from twisted.internet import interfaces, reactor, protocol
-from twisted.python import log
+from twisted.python import log, priorityqueue
 
 
 protocol_version = "HTTP/1.1"
@@ -226,7 +226,15 @@
     return rest[:length], rest[length+2:]
 
 
-
+def qualityComparison(x, y):
+    """ Compares quality values (as in accept-language) """
+    if x == y:
+        return 0
+    if float(x) > float(y):
+        return 1
+    else:
+        return -1
+        
 class StringTransport:
     """
     I am a StringIO wrapper that conforms for the transport API. I support
@@ -383,7 +391,31 @@
                     self.received_cookies[k] = v
                 except ValueError:
                     pass
-    
+
+    def _parse_priorities(line):
+        priorities = priorityqueue.PriorityQueue(qualityComparison)
+        i = line.find(';q=0.')
+        if i != -1:
+            while i != -1:
+                j = line.find(',', i)
+                if j == -1:
+                    prio = line[i+3:]
+                else:
+                    prio = line[i+3:j]
+                priorities.add_elements(prio, line[1:i].split(','))
+                line = line[j:]
+                i = line.find(';q=0.')
+        else:
+            priorities.add_elements("1.0", line.split(','))
+        return priorities
+
+    def parseHeaders(self):
+        for header in ["accept, accept-language"]:
+            data = self.getHeader("accept")
+            if data:
+                self.setHeader(header, self._parse_priorities(accept))
+
+        
     def handleContentChunk(self, data):
         """Write a chunk of data."""
         self.content.write(data)
@@ -746,9 +778,10 @@
     def allHeadersReceived(self):
         req = self.requests[-1]
         req.parseCookies()
+        req.parseHeaders()
         self.persistent = self.checkPersistence(req, self.__version)
         req.gotLength(self.length)
-    
+
     def checkPersistence(self, request, version):
         """Check if the channel should close or not."""
         connection = request.getHeader('connection')


More information about the Twisted-Python mailing list