Skip to content

Virtual Host not supported #66

Open
@amusarra

Description

@amusarra

Describe the bug

Using the convention to specify the Virtual Host on the AMQP connection string as shown here https://www.rabbitmq.com/docs/uri-spec#virtual-host, this is ignored and the connection is always made to the default virtual host.

The following is an example of an AMQP URI where the final part is the virtual host.

amqp://order_sender:OrderSenderP%[email protected]:5672/logistics_vhost

Reproduction steps

Prerequisites

  1. RabbitMQ 4.1 instance started
  2. A virtual host for example logistics_vhost
  3. A user who can consume and produce messages on the previously created virtual host.
Image

Running the test

  1. Use the (getting_started.py) example and change the AMQP url to suit your environment, specifying the virtual host.
  2. Install the client via pip install rabbitmq-amqp-python-client
  3. export PN_TRACE_FRM=1
  4. Run test via python getting_started.py
    Below you can see the modified AMQP uri that include the virtual host address.
diff --git a/examples/getting_started/getting_started.py b/examples/getting_started/getting_started.py
index 6e5e018..0cc27c2 100644
--- a/examples/getting_started/getting_started.py
+++ b/examples/getting_started/getting_started.py
@@ -87,7 +87,7 @@ def main() -> None:
     routing_key = "routing-key"

     print("connection to amqp server")
-    environment = Environment(uri="amqp://guest:guest@localhost:5672/")
+    environment = Environment(uri="amqp://order_sender:OrderSenderP@[email protected]:5672/logistics_vhost")
     connection = create_connection(environment)

     management = connection.management()

Results

The output result is:

Connection amqp://order_sender:OrderSenderP%[email protected]:5672/logistics_vhost disconnected: Condition('amqp:connection:framing-error', 'connection aborted').

Below the output details.

connection to amqp server
[0x111f5aeb0]: SASL:FRAME:  -> SASL
[0x111f5aeb0]: SASL:FRAME:  <- SASL
[0x111f5aeb0]: AMQP:FRAME:0 <- @sasl-mechanisms(64) [sasl-server-mechanisms=@<symbol>[:PLAIN, :AMQPLAIN, :ANONYMOUS]]
[0x111f5aeb0]: AMQP:FRAME:0 -> @sasl-init(65) [mechanism=:PLAIN, initial-response=b"\x00order_sender\x00OrderSenderP@ssw0rd"]
[0x111f5aeb0]: AMQP:FRAME:0 <- @sasl-outcome(68) [code=0x0]
[0x111f5aeb0]: AMQP:FRAME:  -> AMQP
[0x111f5aeb0]: AMQP:FRAME:0 -> @open(16) [container-id="ca577230-5ebc-409a-9019-828744e024e4", hostname="rabbitmq.labs.dontesta.it", max-frame-size=0x8000, channel-max=0x7fff]
[0x111f5aeb0]: AMQP:FRAME:  <- AMQP
[0x111f5aeb0]: AMQP:FRAME:0 -> @close(24) [error=@error(29) [condition=:"amqp:connection:framing-error", description="connection aborted"]]
[0x111f5aeb0]:   IO:FRAME:  <- EOS
Traceback (most recent call last):
  File "/Users/amusarra/dev/github/rabbitmq/rabbitmq-amqp-python-client/examples/getting_started/getting_started.py", line 172, in <module>
    main()
  File "/Users/amusarra/dev/github/rabbitmq/rabbitmq-amqp-python-client/examples/getting_started/getting_started.py", line 91, in main
    connection = create_connection(environment)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/amusarra/dev/github/rabbitmq/rabbitmq-amqp-python-client/examples/getting_started/getting_started.py", line 79, in create_connection
    connection.dial()
  File "/Users/amusarra/.pyenv/versions/3.12.6/lib/python3.12/site-packages/rabbitmq_amqp_python_client/connection.py", line 223, in dial
    self._open_connections()
  File "/Users/amusarra/.pyenv/versions/3.12.6/lib/python3.12/site-packages/rabbitmq_amqp_python_client/connection.py", line 119, in _open_connections
    self._create_connection()
  File "/Users/amusarra/.pyenv/versions/3.12.6/lib/python3.12/site-packages/rabbitmq_amqp_python_client/connection.py", line 158, in _create_connection
    self._conn = BlockingConnection(
                 ^^^^^^^^^^^^^^^^^^^
  File "/Users/amusarra/.pyenv/versions/3.12.6/lib/python3.12/site-packages/rabbitmq_amqp_python_client/qpid/proton/_utils.py", line 464, in __init__
    self.wait(
  File "/Users/amusarra/.pyenv/versions/3.12.6/lib/python3.12/site-packages/rabbitmq_amqp_python_client/qpid/proton/_utils.py", line 634, in wait
    raise ConnectionException(
rabbitmq_amqp_python_client.qpid.proton._exceptions.ConnectionException: Connection amqp://order_sender:OrderSenderP%[email protected]:5672/logistics_vhost disconnected: Condition('amqp:connection:framing-error', 'connection aborted')

While the RabbitMQ log show the below

access to vhost '/' refused for user 'order_sender

2025-05-14 12:45:36.935202+00:00 [error] <0.1338.0> closing AMQP connection <0.1338.0> (192.168.127.1:24830 -> 10.88.0.35:5672, duration: '3s'):
2025-05-14 12:45:36.935202+00:00 [error] <0.1338.0> {handshake_error,waiting_open,
2025-05-14 12:45:36.935202+00:00 [error] <0.1338.0>                  {'v1_0.error',{symbol,<<"amqp:internal-error">>},
2025-05-14 12:45:36.935202+00:00 [error] <0.1338.0>                                {utf8,<<"Reader error: {amqp_error,not_allowed,\n                          \"access to vhost '/' refused for user 'order_sender'\",\n                          none}\n[{rabbit_misc,protocol_error,1,[{file,\"rabbit_misc.erl\"},{line,285}]},\n {lists,foldl,3,[{file,\"lists.erl\"},{line,2146}]},\n {rabbit_amqp_reader,handle_connection_frame,2,\n                     [{file,\"rabbit_amqp_reader.erl\"},{line,442}]},\n {rabbit_amqp_reader,handle_frame,4,\n                     [{file,\"rabbit_amqp_reader.erl\"},{line,360}]},\n {rabbit_amqp_reader,recvloop,2,[{file,\"rabbit_amqp_reader.erl\"},{line,106}]},\n {rabbit_reader,run,1,[{file,\"rabbit_reader.erl\"},{line,469}]},\n {rabbit_reader,start_connection,5,[{file,\"rabbit_reader.erl\"},{line,340}]},\n {proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,329}]}]">>},
2025-05-14 12:45:36.935202+00:00 [error] <0.1338.0>                                undefined}}

Notice from the output of the python script execution, how the virtual host was not passed.

[0x111f5aeb0]: AMQP:FRAME:  -> AMQP
[0x111f5aeb0]: AMQP:FRAME:0 -> @open(16) [container-id="ca577230-5ebc-409a-9019-828744e024e4", hostname="rabbitmq.labs.dontesta.it", max-frame-size=0x8000, channel-max=0x7fff]
[0x111f5aeb0]: AMQP:FRAME:  <- AMQP
[0x111f5aeb0]: AMQP:FRAME:0 -> @close(24) [error=@error(29) [condition=:"amqp:connection:framing-error", description="connection aborted"]]
[0x111f5aeb0]:   IO:FRAME:  <- EOS

Expected behavior

The expected result is that the connection is successful for the specified user and on the specified virtual host. The following logs show the success case.

2025-05-14 12:54:26.486959+00:00 [info] <0.1432.0> accepting AMQP connection 192.168.127.1:59376 -> 10.88.0.35:5671
2025-05-14 12:54:26.487778+00:00 [debug] <0.1432.0> User 'order_sender' authenticated successfully by backend rabbit_auth_backend_internal
2025-05-14 12:54:26.488623+00:00 [info] <0.1432.0> Connection from AMQP 1.0 container '2b4bc1e4-d75c-47ce-b5d1-61fa5e485431': user 'order_sender' authenticated using SASL mechanism PLAIN and granted access to vhost 'logistics_vhost'
2025-05-14 12:54:26.488739+00:00 [debug] <0.1432.0> AMQP 1.0 connection.open frame: hostname = vhost:logistics_vhost, extracted vhost = logistics_vhost, idle-time-out = undefined
2025-05-14 12:54:26.494599+00:00 [debug] <0.1432.0> AMQP 1.0 created session process <0.1437.0> for channel number 0
Image

Additional context

System environment

OS: macOS 15.4.1 24E263 arm64
Kernel: 24.4.0
Python 3.12.6
RabbitMQ 4.1.0 Erlang 27.3.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions