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