Handle the Sec-WebSocket-Extensions HTTP response header. Check that each extension is supported, as well as its parameters. :rfc:`6455` leaves the rules up to the specification of each extension. To provide this level of flexibility, for each extension ac
(self, headers: Headers)
| 174 | self.subprotocol = self.process_subprotocol(headers) |
| 175 | |
| 176 | def process_extensions(self, headers: Headers) -> list[Extension]: |
| 177 | """ |
| 178 | Handle the Sec-WebSocket-Extensions HTTP response header. |
| 179 | |
| 180 | Check that each extension is supported, as well as its parameters. |
| 181 | |
| 182 | :rfc:`6455` leaves the rules up to the specification of each |
| 183 | extension. |
| 184 | |
| 185 | To provide this level of flexibility, for each extension accepted by |
| 186 | the server, we check for a match with each extension available in the |
| 187 | client configuration. If no match is found, an exception is raised. |
| 188 | |
| 189 | If several variants of the same extension are accepted by the server, |
| 190 | it may be configured several times, which won't make sense in general. |
| 191 | Extensions must implement their own requirements. For this purpose, |
| 192 | the list of previously accepted extensions is provided. |
| 193 | |
| 194 | Other requirements, for example related to mandatory extensions or the |
| 195 | order of extensions, may be implemented by overriding this method. |
| 196 | |
| 197 | Args: |
| 198 | headers: WebSocket handshake response headers. |
| 199 | |
| 200 | Returns: |
| 201 | List of accepted extensions. |
| 202 | |
| 203 | Raises: |
| 204 | InvalidHandshake: To abort the handshake. |
| 205 | |
| 206 | """ |
| 207 | accepted_extensions: list[Extension] = [] |
| 208 | |
| 209 | extensions = headers.get_all("Sec-WebSocket-Extensions") |
| 210 | |
| 211 | if extensions: |
| 212 | if self.available_extensions is None: |
| 213 | raise NegotiationError("no extensions supported") |
| 214 | |
| 215 | parsed_extensions: list[ExtensionHeader] = sum( |
| 216 | [parse_extension(header_value) for header_value in extensions], [] |
| 217 | ) |
| 218 | |
| 219 | for name, response_params in parsed_extensions: |
| 220 | for extension_factory in self.available_extensions: |
| 221 | # Skip non-matching extensions based on their name. |
| 222 | if extension_factory.name != name: |
| 223 | continue |
| 224 | |
| 225 | # Skip non-matching extensions based on their params. |
| 226 | try: |
| 227 | extension = extension_factory.process_response_params( |
| 228 | response_params, accepted_extensions |
| 229 | ) |
| 230 | except NegotiationError: |
| 231 | continue |
| 232 | |
| 233 | # Add matching extension to the final list. |
no test coverage detected