Skip to content

fix(client): validate outgoing topic aliases against server limit - #97

Open
AndreyGatsuk wants to merge 1 commit into
faststream-community:masterfrom
AndreyGatsuk:fix/topic-alias-limit
Open

AndreyGatsuk wants to merge 1 commit into
faststream-community:masterfrom
AndreyGatsuk:fix/topic-alias-limit

Conversation

@AndreyGatsuk

Copy link
Copy Markdown

Summary

Implement outgoing Topic Alias validation according to MQTT 5.0 §3.2.2.3.8 (Topic Alias Maximum) and §3.3.2.3.4 (Topic Alias).

Before sending PUBLISH:

  • Reject values outside 1..65535 or above the server's Topic Alias Maximum.
  • Reject aliases when the server omits the maximum or sets it to zero.
  • Use the current connection's limit, including after reconnect.
  • Keep publications without a Topic Alias unaffected.

Closes #78

Validation

  • Added tests for invalid aliases (-1, 0, 65536), missing/zero/exceeded server limits, valid boundary values, updated limits after reconnect, publications without aliases, and MQTT 3.1.1 compatibility (6 test functions, 40 cases).

  • Full test suite on Python 3.11 with all five brokers: 732 passed, 24 skipped (existing protocol/broker-specific skips).

  • Ruff lint and formatting, mypy, mkdocs build --strict, uv build, and Bandit passed.

  • Final docstring and documentation edits passed git diff --check.

  • Tests were added or updated when behavior changed

  • Documentation was updated when the public API changed

  • The PR title follows Conventional Commits, for example feat(client): add reconnect timeout

@borisalekseev
borisalekseev self-requested a review September 9, 2026 19:14
Comment thread src/zmqtt/client.py
Comment on lines 613 to +625
if properties is not None and self._version != "5.0":
msg = "properties require MQTT 5.0"
raise RuntimeError(msg)
if properties is not None and properties.topic_alias is not None:
alias = properties.topic_alias
if not 1 <= alias <= _MAX_TOPIC_ALIAS:
msg = "topic_alias must be between 1 and 65535"
raise ValueError(msg)
connack_properties = self.connection_info.properties
maximum = 0 if connack_properties is None else (connack_properties.topic_alias_maximum or 0)
if alias > maximum:
msg = f"topic_alias {alias} exceeds server Topic Alias Maximum {maximum}"
raise ValueError(msg)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's refactor it into `self._validate_publish_properties(properties)

Comment thread tests/test_topic_alias.py
Comment on lines +118 to +120
@pytest.mark.parametrize("maximum", [None, 0, 1, 5])
@pytest.mark.parametrize("resumed", [False, True])
async def test_reconnect_uses_new_alias_limit(maximum: int | None, resumed: bool) -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this tests is unnecessary, too complex.

Comment thread tests/test_topic_alias.py
Comment on lines +112 to +113
with pytest.raises(RuntimeError, match=r"properties require MQTT 5\.0"):
await client.publish("test/topic", b"payload", properties=PublishProperties(topic_alias=1))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we test it using the e2e test case (for less coupling to library internals)?

Comment thread tests/test_topic_alias.py

@pytest.mark.parametrize("maximum", [None, 0, 3])
@pytest.mark.parametrize("properties", [None, PublishProperties(content_type="text/plain")])
async def test_publication_without_alias_is_independent_of_server_limit(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this test measure? I believe it should be eliminated.

@borisalekseev borisalekseev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many tests, and the tests are too complicated and coupled with the library's internals. We prefer writing only end-to-end (e2e) tests that measure the public API and behaviour of the library, as these tests are more compatible with refactoring. Unit tests that know about the protocol class and other internal details are allowed only if it is impossible to easily simulate the broker's behaviour in an e2e testing scenario.

I will extend the contribution guide and the project harness soon. Sorry that these concepts weren't explicitly described in the project.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MQTT 5: validate outgoing Topic Aliases against the server's limit

2 participants