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 def trace(self, *vargs, **kwargs): 46 """ 47 No-op logging. Only level needed for now. 48 """ 49 pass 50 51 52class H2Configuration(object): 53 """ 54 An object that controls the way a single HTTP/2 connection behaves. 55 56 This object allows the users to customize behaviour. In particular, it 57 allows users to enable or disable optional features, or to otherwise handle 58 various unusual behaviours. 59 60 This object has very little behaviour of its own: it mostly just ensures 61 that configuration is self-consistent. 62 63 :param client_side: Whether this object is to be used on the client side of 64 a connection, or on the server side. Affects the logic used by the 65 state machine, the default settings values, the allowable stream IDs, 66 and several other properties. Defaults to ``True``. 67 :type client_side: ``bool`` 68 69 :param header_encoding: Controls whether the headers emitted by this object 70 in events are transparently decoded to ``unicode`` strings, and what 71 encoding is used to do that decoding. This defaults to ``None``, 72 meaning that headers will be returned as bytes. To automatically 73 decode headers (that is, to return them as unicode strings), this can 74 be set to the string name of any encoding, e.g. ``'utf-8'``. 75 76 .. versionchanged:: 3.0.0 77 Changed default value from ``'utf-8'`` to ``None`` 78 79 :type header_encoding: ``str``, ``False``, or ``None`` 80 81 :param validate_outbound_headers: Controls whether the headers emitted 82 by this object are validated against the rules in RFC 7540. 83 Disabling this setting will cause outbound header validation to 84 be skipped, and allow the object to emit headers that may be illegal 85 according to RFC 7540. Defaults to ``True``. 86 :type validate_outbound_headers: ``bool`` 87 88 :param normalize_outbound_headers: Controls whether the headers emitted 89 by this object are normalized before sending. Disabling this setting 90 will cause outbound header normalization to be skipped, and allow 91 the object to emit headers that may be illegal according to 92 RFC 7540. Defaults to ``True``. 93 :type normalize_outbound_headers: ``bool`` 94 95 :param validate_inbound_headers: Controls whether the headers received 96 by this object are validated against the rules in RFC 7540. 97 Disabling this setting will cause inbound header validation to 98 be skipped, and allow the object to receive headers that may be illegal 99 according to RFC 7540. Defaults to ``True``. 100 :type validate_inbound_headers: ``bool`` 101 102 :param normalize_inbound_headers: Controls whether the headers received by 103 this object are normalized according to the rules of RFC 7540. 104 Disabling this setting may lead to hyper-h2 emitting header blocks that 105 some RFCs forbid, e.g. with multiple cookie fields. 106 107 .. versionadded:: 3.0.0 108 109 :type normalize_inbound_headers: ``bool`` 110 111 :param logger: A logger that conforms to the requirements for this module, 112 those being no I/O and no context switches, which is needed in order 113 to run in asynchronous operation. 114 115 .. versionadded:: 2.6.0 116 117 :type logger: ``logging.Logger`` 118 """ 119 client_side = _BooleanConfigOption('client_side') 120 validate_outbound_headers = _BooleanConfigOption( 121 'validate_outbound_headers' 122 ) 123 normalize_outbound_headers = _BooleanConfigOption( 124 'normalize_outbound_headers' 125 ) 126 validate_inbound_headers = _BooleanConfigOption( 127 'validate_inbound_headers' 128 ) 129 normalize_inbound_headers = _BooleanConfigOption( 130 'normalize_inbound_headers' 131 ) 132 133 def __init__(self, 134 client_side=True, 135 header_encoding=None, 136 validate_outbound_headers=True, 137 normalize_outbound_headers=True, 138 validate_inbound_headers=True, 139 normalize_inbound_headers=True, 140 logger=None): 141 self.client_side = client_side 142 self.header_encoding = header_encoding 143 self.validate_outbound_headers = validate_outbound_headers 144 self.normalize_outbound_headers = normalize_outbound_headers 145 self.validate_inbound_headers = validate_inbound_headers 146 self.normalize_inbound_headers = normalize_inbound_headers 147 self.logger = logger or DummyLogger(__name__) 148 149 @property 150 def header_encoding(self): 151 """ 152 Controls whether the headers emitted by this object in events are 153 transparently decoded to ``unicode`` strings, and what encoding is used 154 to do that decoding. This defaults to ``None``, meaning that headers 155 will be returned as bytes. To automatically decode headers (that is, to 156 return them as unicode strings), this can be set to the string name of 157 any encoding, e.g. ``'utf-8'``. 158 """ 159 return self._header_encoding 160 161 @header_encoding.setter 162 def header_encoding(self, value): 163 """ 164 Enforces constraints on the value of header encoding. 165 """ 166 if not isinstance(value, (bool, str, type(None))): 167 raise ValueError("header_encoding must be bool, string, or None") 168 if value is True: 169 raise ValueError("header_encoding cannot be True") 170 self._header_encoding = value 171