Pick a subprotocol among those offered by the client. If several subprotocols are supported by both the client and the server, pick the first one in the list declared the server. If the server doesn't support any subprotocols, continue without a subprotocol
(
self,
subprotocols: Sequence[Subprotocol],
)
| 415 | return self.select_subprotocol(subprotocols) |
| 416 | |
| 417 | def select_subprotocol( |
| 418 | self, |
| 419 | subprotocols: Sequence[Subprotocol], |
| 420 | ) -> Subprotocol | None: |
| 421 | """ |
| 422 | Pick a subprotocol among those offered by the client. |
| 423 | |
| 424 | If several subprotocols are supported by both the client and the server, |
| 425 | pick the first one in the list declared the server. |
| 426 | |
| 427 | If the server doesn't support any subprotocols, continue without a |
| 428 | subprotocol, regardless of what the client offers. |
| 429 | |
| 430 | If the server supports at least one subprotocol and the client doesn't |
| 431 | offer any, abort the handshake with an HTTP 400 error. |
| 432 | |
| 433 | You provide a ``select_subprotocol`` argument to :class:`ServerProtocol` |
| 434 | to override this logic. For example, you could accept the connection |
| 435 | even if client doesn't offer a subprotocol, rather than reject it. |
| 436 | |
| 437 | Here's how to negotiate the ``chat`` subprotocol if the client supports |
| 438 | it and continue without a subprotocol otherwise:: |
| 439 | |
| 440 | def select_subprotocol(protocol, subprotocols): |
| 441 | if "chat" in subprotocols: |
| 442 | return "chat" |
| 443 | |
| 444 | Args: |
| 445 | subprotocols: List of subprotocols offered by the client. |
| 446 | |
| 447 | Returns: |
| 448 | Selected subprotocol, if a common subprotocol was found. |
| 449 | |
| 450 | :obj:`None` to continue without a subprotocol. |
| 451 | |
| 452 | Raises: |
| 453 | NegotiationError: Custom implementations may raise this exception |
| 454 | to abort the handshake with an HTTP 400 error. |
| 455 | |
| 456 | """ |
| 457 | # Server doesn't offer any subprotocols. |
| 458 | if not self.available_subprotocols: # None or empty list |
| 459 | return None |
| 460 | |
| 461 | # Server offers at least one subprotocol but client doesn't offer any. |
| 462 | if not subprotocols: |
| 463 | raise NegotiationError("missing subprotocol") |
| 464 | |
| 465 | # Server and client both offer subprotocols. Look for a shared one. |
| 466 | proposed_subprotocols = set(subprotocols) |
| 467 | for subprotocol in self.available_subprotocols: |
| 468 | if subprotocol in proposed_subprotocols: |
| 469 | return subprotocol |
| 470 | |
| 471 | # No common subprotocol was found. |
| 472 | raise NegotiationError( |
| 473 | "invalid subprotocol; expected one of " |
| 474 | + ", ".join(self.available_subprotocols) |
no test coverage detected