util.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. # -*- coding: utf-8 -*-
  2. """
  3. hyper/http20/util
  4. ~~~~~~~~~~~~~~~~~
  5. Utility functions for use with hyper.
  6. """
  7. from collections import defaultdict
  8. def combine_repeated_headers(kvset):
  9. """
  10. Given a list of key-value pairs (like for HTTP headers!), combines pairs
  11. with the same key together, separating the values with NULL bytes. This
  12. function maintains the order of input keys, because it's awesome.
  13. """
  14. def set_pop(set, item):
  15. set.remove(item)
  16. return item
  17. headers = defaultdict(list)
  18. keys = set()
  19. for key, value in kvset:
  20. headers[key].append(value)
  21. keys.add(key)
  22. return [(set_pop(keys, k), b'\x00'.join(headers[k])) for k, v in kvset
  23. if k in keys]
  24. def split_repeated_headers(kvset):
  25. """
  26. Given a set of key-value pairs (like for HTTP headers!), finds values that
  27. have NULL bytes in them and splits them into a dictionary whose values are
  28. lists.
  29. """
  30. headers = defaultdict(list)
  31. for key, value in kvset:
  32. headers[key] = value.split(b'\x00')
  33. return dict(headers)
  34. def h2_safe_headers(headers):
  35. """
  36. This method takes a set of headers that are provided by the user and
  37. transforms them into a form that is safe for emitting over HTTP/2.
  38. Currently, this strips the Connection header and any header it refers to.
  39. """
  40. stripped = {
  41. i.lower().strip()
  42. for k, v in headers if k == 'connection'
  43. for i in v.split(',')
  44. }
  45. stripped.add('connection')
  46. return [header for header in headers if header[0] not in stripped]