Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rumqttc] MqttOptions::parse_url broken for websocket urls #808

Open
brocaar opened this issue Feb 27, 2024 · 1 comment
Open

[rumqttc] MqttOptions::parse_url broken for websocket urls #808

brocaar opened this issue Feb 27, 2024 · 1 comment

Comments

@brocaar
Copy link

brocaar commented Feb 27, 2024

I believe these two options are equal:

let options = MqttOptions::new("123", "localhost", 1883);
let options = MqttOptions::parse_url("mqtt://example.com:1883?client_id=123").unwrap();

The url crate is used to parse the transport, hostname and port. Then the client_id is retrieved by reading the URL parameters, etc...

let host = url.host_str().unwrap_or_default().to_owned();

https://github.com/bytebeamio/rumqtt/blob/main/rumqttc/src/v5/mod.rs#L581

However, when looking at the websocket example, the host argument of MqttOptions::new(...) is not the hostname, but the full websocket URL:

    // port parameter is ignored when scheme is websocket
    let mut mqttoptions = MqttOptions::new(
        "clientId-aSziq39Bp3",
        "ws://broker.mqttdashboard.com:8000/mqtt",
        8000,
    );
    mqttoptions.set_transport(Transport::Ws);

https://github.com/bytebeamio/rumqtt/blob/main/rumqttc/examples/websocket.rs#L10

If using the parse_url for ws://broker.mqttdashboard.com:8000/mqtt?client_id=clientId-aSziq39Bp3 then this would result in host being set to broker.mqttdashboard.com, not ws://broker.mqttdashboard.com:8000/mqtt.

The result is the following error being returned by the eventloop:

  • Invalid Url: Couldn't parse host from url.
@swanandx
Copy link
Member

Hey, thanks for reporting, the way we handle ws / wss differently from tcp is the root of this.

I think it is handled that way because when using websockets, address can have path like /mqtt, which isn't case with normal tcp. So when we treat host as full URL, this can be done:

let mut request = options.broker_addr.as_str().into_client_request()?;

to work around it, instead of using broker_addr directly to convert to request, we can separately extract the path ( if present ) and do:

let mut request = format!("ws://{domain}:{port}/{path}").into_client_request()?;

^ this would allow us to not ignore the port when using websocket and to address this issue.

PS:

I have opened a PR to refactor MqttOptions: #789

this PR would allow users to provide partial / full urls for both tcp & ws! it is still draft because I'm waiting for feedback on design, like shall we return error if we fail to parse, or shall we panic. ( more details in PR desc )

please have a look at that PR as well!

Thank you!

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

No branches or pull requests

2 participants