+++ /dev/null
-"""Manage HTTP Response Headers\r
-\r
-Much of this module is red-handedly pilfered from email.message in the stdlib,\r
-so portions are Copyright (C) 2001,2002 Python Software Foundation, and were\r
-written by Barry Warsaw.\r
-"""\r
-\r
-from types import ListType, TupleType\r
-\r
-# Regular expression that matches `special' characters in parameters, the\r
-# existence of which force quoting of the parameter value.\r
-import re\r
-tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')\r
-\r
-def _formatparam(param, value=None, quote=1):\r
- """Convenience function to format and return a key=value pair.\r
-\r
- This will quote the value if needed or if quote is true.\r
- """\r
- if value is not None and len(value) > 0:\r
- if quote or tspecials.search(value):\r
- value = value.replace('\\', '\\\\').replace('"', r'\"')\r
- return '%s="%s"' % (param, value)\r
- else:\r
- return '%s=%s' % (param, value)\r
- else:\r
- return param\r
-\r
-\r
-class Headers:\r
-\r
- """Manage a collection of HTTP response headers"""\r
-\r
- def __init__(self,headers):\r
- if type(headers) is not ListType:\r
- raise TypeError("Headers must be a list of name/value tuples")\r
- self._headers = headers\r
-\r
- def __len__(self):\r
- """Return the total number of headers, including duplicates."""\r
- return len(self._headers)\r
-\r
- def __setitem__(self, name, val):\r
- """Set the value of a header."""\r
- del self[name]\r
- self._headers.append((name, val))\r
-\r
- def __delitem__(self,name):\r
- """Delete all occurrences of a header, if present.\r
-\r
- Does *not* raise an exception if the header is missing.\r
- """\r
- name = name.lower()\r
- self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]\r
-\r
- def __getitem__(self,name):\r
- """Get the first header value for 'name'\r
-\r
- Return None if the header is missing instead of raising an exception.\r
-\r
- Note that if the header appeared multiple times, the first exactly which\r
- occurrance gets returned is undefined. Use getall() to get all\r
- the values matching a header field name.\r
- """\r
- return self.get(name)\r
-\r
- def has_key(self, name):\r
- """Return true if the message contains the header."""\r
- return self.get(name) is not None\r
-\r
- __contains__ = has_key\r
-\r
-\r
- def get_all(self, name):\r
- """Return a list of all the values for the named field.\r
-\r
- These will be sorted in the order they appeared in the original header\r
- list or were added to this instance, and may contain duplicates. Any\r
- fields deleted and re-inserted are always appended to the header list.\r
- If no fields exist with the given name, returns an empty list.\r
- """\r
- name = name.lower()\r
- return [kv[1] for kv in self._headers if kv[0].lower()==name]\r
-\r
-\r
- def get(self,name,default=None):\r
- """Get the first header value for 'name', or return 'default'"""\r
- name = name.lower()\r
- for k,v in self._headers:\r
- if k.lower()==name:\r
- return v\r
- return default\r
-\r
-\r
- def keys(self):\r
- """Return a list of all the header field names.\r
-\r
- These will be sorted in the order they appeared in the original header\r
- list, or were added to this instance, and may contain duplicates.\r
- Any fields deleted and re-inserted are always appended to the header\r
- list.\r
- """\r
- return [k for k, v in self._headers]\r
-\r
- def values(self):\r
- """Return a list of all header values.\r
-\r
- These will be sorted in the order they appeared in the original header\r
- list, or were added to this instance, and may contain duplicates.\r
- Any fields deleted and re-inserted are always appended to the header\r
- list.\r
- """\r
- return [v for k, v in self._headers]\r
-\r
- def items(self):\r
- """Get all the header fields and values.\r
-\r
- These will be sorted in the order they were in the original header\r
- list, or were added to this instance, and may contain duplicates.\r
- Any fields deleted and re-inserted are always appended to the header\r
- list.\r
- """\r
- return self._headers[:]\r
-\r
- def __repr__(self):\r
- return "Headers(%r)" % self._headers\r
-\r
- def __str__(self):\r
- """str() returns the formatted headers, complete with end line,\r
- suitable for direct HTTP transmission."""\r
- return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['',''])\r
-\r
- def setdefault(self,name,value):\r
- """Return first matching header value for 'name', or 'value'\r
-\r
- If there is no header named 'name', add a new header with name 'name'\r
- and value 'value'."""\r
- result = self.get(name)\r
- if result is None:\r
- self._headers.append((name,value))\r
- return value\r
- else:\r
- return result\r
-\r
- def add_header(self, _name, _value, **_params):\r
- """Extended header setting.\r
-\r
- _name is the header field to add. keyword arguments can be used to set\r
- additional parameters for the header field, with underscores converted\r
- to dashes. Normally the parameter will be added as key="value" unless\r
- value is None, in which case only the key will be added.\r
-\r
- Example:\r
-\r
- h.add_header('content-disposition', 'attachment', filename='bud.gif')\r
-\r
- Note that unlike the corresponding 'email.message' method, this does\r
- *not* handle '(charset, language, value)' tuples: all values must be\r
- strings or None.\r
- """\r
- parts = []\r
- if _value is not None:\r
- parts.append(_value)\r
- for k, v in _params.items():\r
- if v is None:\r
- parts.append(k.replace('_', '-'))\r
- else:\r
- parts.append(_formatparam(k.replace('_', '-'), v))\r
- self._headers.append((_name, "; ".join(parts)))\r