|
11 | 11 | ) |
12 | 12 |
|
13 | 13 | import typing_extensions |
| 14 | +from packaging import version |
14 | 15 |
|
15 | 16 | from .address_helper import validate_address |
16 | 17 | from .consumer import Consumer |
@@ -166,6 +167,82 @@ def _create_connection(self) -> None: |
166 | 167 | password=self._password, |
167 | 168 | ) |
168 | 169 |
|
| 170 | + self._validate_server_properties() |
| 171 | + |
| 172 | + def _validate_server_properties(self) -> None: |
| 173 | + """ |
| 174 | + Validate the server properties returned in the connection handshake. |
| 175 | +
|
| 176 | + Checks that the server is RabbitMQ and the version is >= 4.0.0. |
| 177 | +
|
| 178 | + Raises: |
| 179 | + ValidationCodeException: If server is not RabbitMQ or version < 4.0.0 |
| 180 | + """ |
| 181 | + if self._conn is None or self._conn.conn is None: |
| 182 | + raise ValidationCodeException("Connection not established") |
| 183 | + |
| 184 | + remote_props = self._conn.conn.remote_properties |
| 185 | + if remote_props is None: |
| 186 | + raise ValidationCodeException("No remote properties received from server") |
| 187 | + |
| 188 | + # Check if server is RabbitMQ |
| 189 | + product = remote_props.get("product") |
| 190 | + if product != "RabbitMQ": |
| 191 | + raise ValidationCodeException( |
| 192 | + f"Connection to non-RabbitMQ server detected. " |
| 193 | + f"Expected 'RabbitMQ', got '{product}'" |
| 194 | + ) |
| 195 | + |
| 196 | + # Check server version is >= 4.0.0 |
| 197 | + server_version = remote_props.get("version") |
| 198 | + if server_version is None: |
| 199 | + raise ValidationCodeException("Server version not provided") |
| 200 | + |
| 201 | + try: |
| 202 | + if version.parse(str(server_version)) < version.parse("4.0.0"): |
| 203 | + raise ValidationCodeException( |
| 204 | + f"The AMQP client library requires RabbitMQ 4.0.0 or higher. " |
| 205 | + f"Server version: {server_version}" |
| 206 | + ) |
| 207 | + except Exception as e: |
| 208 | + raise ValidationCodeException( |
| 209 | + f"Failed to parse server version '{server_version}': {e}" |
| 210 | + ) |
| 211 | + |
| 212 | + logger.debug(f"Connected to RabbitMQ server version {server_version}") |
| 213 | + |
| 214 | + def _is_server_version_gte_4_2_0(self) -> bool: |
| 215 | + """ |
| 216 | + Check if the server version is greater than or equal to 4.2.0. |
| 217 | +
|
| 218 | + This is an internal method that can be used to conditionally enable |
| 219 | + features that require RabbitMQ 4.2.0 or higher. |
| 220 | +
|
| 221 | + Returns: |
| 222 | + bool: True if server version >= 4.2.0, False otherwise |
| 223 | +
|
| 224 | + Raises: |
| 225 | + ValidationCodeException: If connection is not established or |
| 226 | + remote properties are not available |
| 227 | + """ |
| 228 | + if self._conn is None or self._conn.conn is None: |
| 229 | + raise ValidationCodeException("Connection not established") |
| 230 | + |
| 231 | + remote_props = self._conn.conn.remote_properties |
| 232 | + if remote_props is None: |
| 233 | + raise ValidationCodeException("No remote properties received from server") |
| 234 | + |
| 235 | + server_version = remote_props.get("version") |
| 236 | + if server_version is None: |
| 237 | + raise ValidationCodeException("Server version not provided") |
| 238 | + |
| 239 | + try: |
| 240 | + return version.parse(str(server_version)) >= version.parse("4.2.0") |
| 241 | + except Exception as e: |
| 242 | + raise ValidationCodeException( |
| 243 | + f"Failed to parse server version '{server_version}': {e}" |
| 244 | + ) |
| 245 | + |
169 | 246 | def dial(self) -> None: |
170 | 247 | """ |
171 | 248 | Establish a connection to the AMQP server. |
|
0 commit comments