[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