| # -*- coding: utf-8 -*- |
| """ |
| h2/config |
| ~~~~~~~~~ |
| |
| Objects for controlling the configuration of the HTTP/2 stack. |
| """ |
| |
| |
| class _BooleanConfigOption(object): |
| """ |
| Descriptor for handling a boolean config option. This will block |
| attempts to set boolean config options to non-bools. |
| """ |
| def __init__(self, name): |
| self.name = name |
| self.attr_name = '_%s' % self.name |
| |
| def __get__(self, instance, owner): |
| return getattr(instance, self.attr_name) |
| |
| def __set__(self, instance, value): |
| if not isinstance(value, bool): |
| raise ValueError("%s must be a bool" % self.name) |
| setattr(instance, self.attr_name, value) |
| |
| |
| class DummyLogger(object): |
| """ |
| An Logger object that does not actual logging, hence a DummyLogger. |
| |
| For the class the log operation is merely a no-op. The intent is to avoid |
| conditionals being sprinkled throughout the hyper-h2 code for calls to |
| logging functions when no logger is passed into the corresponding object. |
| """ |
| def __init__(self, *vargs): |
| pass |
| |
| def debug(self, *vargs, **kwargs): |
| """ |
| No-op logging. Only level needed for now. |
| """ |
| pass |
| |
| |
| class H2Configuration(object): |
| """ |
| An object that controls the way a single HTTP/2 connection behaves. |
| |
| This object allows the users to customize behaviour. In particular, it |
| allows users to enable or disable optional features, or to otherwise handle |
| various unusual behaviours. |
| |
| This object has very little behaviour of its own: it mostly just ensures |
| that configuration is self-consistent. |
| |
| :param client_side: Whether this object is to be used on the client side of |
| a connection, or on the server side. Affects the logic used by the |
| state machine, the default settings values, the allowable stream IDs, |
| and several other properties. Defaults to ``True``. |
| :type client_side: ``bool`` |
| |
| :param header_encoding: Controls whether the headers emitted by this object |
| in events are transparently decoded to ``unicode`` strings, and what |
| encoding is used to do that decoding. This defaults to ``None``, |
| meaning that headers will be returned as bytes. To automatically |
| decode headers (that is, to return them as unicode strings), this can |
| be set to the string name of any encoding, e.g. ``'utf-8'``. |
| |
| .. versionchanged:: 3.0.0 |
| Changed default value from ``'utf-8'`` to ``None`` |
| |
| :type header_encoding: ``str``, ``False``, or ``None`` |
| |
| :param validate_outbound_headers: Controls whether the headers emitted |
| by this object are validated against the rules in RFC 7540. |
| Disabling this setting will cause outbound header validation to |
| be skipped, and allow the object to emit headers that may be illegal |
| according to RFC 7540. Defaults to ``True``. |
| :type validate_outbound_headers: ``bool`` |
| |
| :param normalize_outbound_headers: Controls whether the headers emitted |
| by this object are normalized before sending. Disabling this setting |
| will cause outbound header normalization to be skipped, and allow |
| the object to emit headers that may be illegal according to |
| RFC 7540. Defaults to ``True``. |
| :type normalize_outbound_headers: ``bool`` |
| |
| :param validate_inbound_headers: Controls whether the headers received |
| by this object are validated against the rules in RFC 7540. |
| Disabling this setting will cause inbound header validation to |
| be skipped, and allow the object to receive headers that may be illegal |
| according to RFC 7540. Defaults to ``True``. |
| :type validate_inbound_headers: ``bool`` |
| |
| :param normalize_inbound_headers: Controls whether the headers received by |
| this object are normalized according to the rules of RFC 7540. |
| Disabling this setting may lead to hyper-h2 emitting header blocks that |
| some RFCs forbid, e.g. with multiple cookie fields. |
| |
| .. versionadded:: 3.0.0 |
| |
| :type normalize_inbound_headers: ``bool`` |
| |
| :param logger: A logger that conforms to the requirements for this module, |
| those being no I/O and no context switches, which is needed in order |
| to run in asynchronous operation. |
| |
| .. versionadded:: 2.6.0 |
| |
| :type logger: ``logging.Logger`` |
| """ |
| client_side = _BooleanConfigOption('client_side') |
| validate_outbound_headers = _BooleanConfigOption( |
| 'validate_outbound_headers' |
| ) |
| normalize_outbound_headers = _BooleanConfigOption( |
| 'normalize_outbound_headers' |
| ) |
| validate_inbound_headers = _BooleanConfigOption( |
| 'validate_inbound_headers' |
| ) |
| normalize_inbound_headers = _BooleanConfigOption( |
| 'normalize_inbound_headers' |
| ) |
| |
| def __init__(self, |
| client_side=True, |
| header_encoding=None, |
| validate_outbound_headers=True, |
| normalize_outbound_headers=True, |
| validate_inbound_headers=True, |
| normalize_inbound_headers=True, |
| logger=None): |
| self.client_side = client_side |
| self.header_encoding = header_encoding |
| self.validate_outbound_headers = validate_outbound_headers |
| self.normalize_outbound_headers = normalize_outbound_headers |
| self.validate_inbound_headers = validate_inbound_headers |
| self.normalize_inbound_headers = normalize_inbound_headers |
| self.logger = logger or DummyLogger(__name__) |
| |
| @property |
| def header_encoding(self): |
| """ |
| Controls whether the headers emitted by this object in events are |
| transparently decoded to ``unicode`` strings, and what encoding is used |
| to do that decoding. This defaults to ``None``, meaning that headers |
| will be returned as bytes. To automatically decode headers (that is, to |
| return them as unicode strings), this can be set to the string name of |
| any encoding, e.g. ``'utf-8'``. |
| """ |
| return self._header_encoding |
| |
| @header_encoding.setter |
| def header_encoding(self, value): |
| """ |
| Enforces constraints on the value of header encoding. |
| """ |
| if not isinstance(value, (bool, str, type(None))): |
| raise ValueError("header_encoding must be bool, string, or None") |
| if value is True: |
| raise ValueError("header_encoding cannot be True") |
| self._header_encoding = value |