config.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. # -*- coding: utf-8 -*-
  2. """
  3. h2/config
  4. ~~~~~~~~~
  5. Objects for controlling the configuration of the HTTP/2 stack.
  6. """
  7. class _BooleanConfigOption(object):
  8. """
  9. Descriptor for handling a boolean config option. This will block
  10. attempts to set boolean config options to non-bools.
  11. """
  12. def __init__(self, name):
  13. self.name = name
  14. self.attr_name = '_%s' % self.name
  15. def __get__(self, instance, owner):
  16. return getattr(instance, self.attr_name)
  17. def __set__(self, instance, value):
  18. if not isinstance(value, bool):
  19. raise ValueError("%s must be a bool" % self.name)
  20. setattr(instance, self.attr_name, value)
  21. class DummyLogger(object):
  22. """
  23. An Logger object that does not actual logging, hence a DummyLogger.
  24. For the class the log operation is merely a no-op. The intent is to avoid
  25. conditionals being sprinkled throughout the hyper-h2 code for calls to
  26. logging functions when no logger is passed into the corresponding object.
  27. """
  28. def __init__(self, *vargs):
  29. pass
  30. def debug(self, *vargs, **kwargs):
  31. """
  32. No-op logging. Only level needed for now.
  33. """
  34. pass
  35. class H2Configuration(object):
  36. """
  37. An object that controls the way a single HTTP/2 connection behaves.
  38. This object allows the users to customize behaviour. In particular, it
  39. allows users to enable or disable optional features, or to otherwise handle
  40. various unusual behaviours.
  41. This object has very little behaviour of its own: it mostly just ensures
  42. that configuration is self-consistent.
  43. :param client_side: Whether this object is to be used on the client side of
  44. a connection, or on the server side. Affects the logic used by the
  45. state machine, the default settings values, the allowable stream IDs,
  46. and several other properties. Defaults to ``True``.
  47. :type client_side: ``bool``
  48. :param header_encoding: Controls whether the headers emitted by this object
  49. in events are transparently decoded to ``unicode`` strings, and what
  50. encoding is used to do that decoding. For historical reasons, this
  51. defaults to ``'utf-8'``. To prevent the decoding of headers (that is,
  52. to force them to be returned as bytestrings), this can be set to
  53. ``False`` or the empty string.
  54. :type header_encoding: ``str``, ``False``, or ``None``
  55. :param validate_outbound_headers: Controls whether the headers emitted
  56. by this object are validated against the rules in RFC 7540.
  57. Disabling this setting will cause outbound header validation to
  58. be skipped, and allow the object to emit headers that may be illegal
  59. according to RFC 7540. Defaults to ``True``.
  60. :type validate_outbound_headers: ``bool``
  61. :param normalize_outbound_headers: Controls whether the headers emitted
  62. by this object are normalized before sending. Disabling this setting
  63. will cause outbound header normalization to be skipped, and allow
  64. the object to emit headers that may be illegal according to
  65. RFC 7540. Defaults to ``True``.
  66. :type normalize_outbound_headers: ``bool``
  67. :param validate_inbound_headers: Controls whether the headers received
  68. by this object are validated against the rules in RFC 7540.
  69. Disabling this setting will cause inbound header validation to
  70. be skipped, and allow the object to receive headers that may be illegal
  71. according to RFC 7540. Defaults to ``True``.
  72. :type validate_inbound_headers: ``bool``
  73. :param logger: A logger that conforms to the requirements for this module,
  74. those being no I/O and no context switches, which is needed in order
  75. to run in asynchronous operation.
  76. .. versionadded:: 2.6.0
  77. :type logger: ``logging.Logger``
  78. """
  79. client_side = _BooleanConfigOption('client_side')
  80. validate_outbound_headers = _BooleanConfigOption(
  81. 'validate_outbound_headers'
  82. )
  83. normalize_outbound_headers = _BooleanConfigOption(
  84. 'normalize_outbound_headers'
  85. )
  86. validate_inbound_headers = _BooleanConfigOption(
  87. 'validate_inbound_headers'
  88. )
  89. def __init__(self,
  90. client_side=True,
  91. header_encoding='utf-8',
  92. validate_outbound_headers=True,
  93. normalize_outbound_headers=True,
  94. validate_inbound_headers=True,
  95. logger=None):
  96. self.client_side = client_side
  97. self.header_encoding = header_encoding
  98. self.validate_outbound_headers = validate_outbound_headers
  99. self.normalize_outbound_headers = normalize_outbound_headers
  100. self.validate_inbound_headers = validate_inbound_headers
  101. self.logger = logger or DummyLogger(__name__)
  102. @property
  103. def header_encoding(self):
  104. """
  105. Controls whether the headers emitted by this object in events are
  106. transparently decoded to ``unicode`` strings, and what encoding is used
  107. to do that decoding. For historical reasons, this defaults to
  108. ``'utf-8'``. To prevent the decoding of headers (that is, to force them
  109. to be returned as bytestrings), this can be set to ``False`` or the
  110. empty string.
  111. """
  112. return self._header_encoding
  113. @header_encoding.setter
  114. def header_encoding(self, value):
  115. """
  116. Enforces constraints on the value of header encoding.
  117. """
  118. if not isinstance(value, (bool, str, type(None))):
  119. raise ValueError("header_encoding must be bool, string, or None")
  120. if value is True:
  121. raise ValueError("header_encoding cannot be True")
  122. self._header_encoding = value