xinta
xinta

Reputation: 9

WebSocket 1006 Abnormal Closure with Proxy Configuration in Rust Yew and HAProxy

I am developing a web application using Rust Yew framework and have set up WebSocket communication that works fine when I connect directly to the WebSocket server. However, when routing WebSocket connections through a proxy setup using Trunk and HAProxy, the WebSocket connection is terminated with a 1006 Abnormal Closure error, and I do not receive a close frame. Environment:

Frontend: Rust Yew Backend: Rust with WebSocket support Proxy: HAProxy with additional routing via Trunk

Issue: Direct WebSocket connections to ws://192.168.64.100:5000/api/ws?user_name=user1 work perfectly. However, when I attempt to connect through my proxy setup at ws://127.0.0.1:8888/api/v1/ws?user_name=user1, the connection is established but then immediately closes with a 1006 error, indicating an abnormal closure. The backend logs show Error (Error { inner: Protocol(ResetWithoutClosingHandshake) }).

Here's the relevant part of my Rust WebSocket service setup:

`impl WebSocketService {
 pub fn new(
    url_name: &str,
    on_message_callback: Callback<String>,
    on_open_callback: Callback<()>,
    session_id: String,
) -> Rc<Self> {
    debug!("***************** websocket address = {}", url_name);
    let resources = WebResources::default();
    let ws_res=resources.base_path();
    let ws = WebSocket::open(&format!("{}/api/v1/ws?user_name={}",ws_res, url_name)).unwrap();
    let (write, read) = ws.split();
    let ws_write = Rc::new(RefCell::new(write));
    let ws_read = Rc::new(RefCell::new(read));

    let (in_tx, mut in_rx) = futures::channel::mpsc::channel::<String>(1000);
    let message_queue = Rc::new(RefCell::new(Vec::new()));
    let is_open = Rc::new(RefCell::new(false));
    let ping_interval = Rc::new(RefCell::new(None));
    let session_id = Rc::new(RefCell::new(session_id));
    let (open_tx, _open_rx) = oneshot::channel();
    let open_notifier = Rc::new(RefCell::new(Some(open_tx)));

    let message_queue_clone = message_queue.clone();
    let is_open_clone = is_open.clone();
    let on_open_callback_clone = on_open_callback.clone();
    let open_notifier_clone = open_notifier.clone();
    let ws_write_clone = ws_write.clone();
    let ws_read_clone = ws_read.clone();
    let _session_id_clone = session_id.clone();
    let _ping_interval_clone = ping_interval.clone();
    #[allow(clippy::await_holding_refcell_ref)]
    spawn_local({
        let ws_write_clone = ws_write_clone.clone();
        async move {
            while let Some(s) = in_rx.next().await {
                debug!("Attempting to send message: {}", s);
                match ws_write_clone.borrow_mut().send(Message::Text(s)).await {
                    Ok(_) => debug!("Message sent successfully"),
                    Err(e) => {
                        console::log_1(&format!("Error sending message: {:?}", e).into());
                        break;
                    }
                }
            }
        }
    });
    #[allow(clippy::await_holding_refcell_ref)]
    spawn_local({
        let ws_read_clone = ws_read_clone.clone();
        async move {
            while let Some(msg) = ws_read_clone.borrow_mut().next().await {
                debug!("Received message or error: {:?}", msg);
                match msg {
                    Ok(Message::Text(data)) => {
                        console::log_1(&format!("from websocket: {}", data).into());
                        let v: WsUiResponseMessage =
                             serde_json::from_str(&data).unwrap_or_else(|_| WsUiResponseMessage     
                                success: false,
                                session_id: String::new(),
                                requested_action: WsRequestedAction::ALLOCATED,
                                state: 0,
                                api_error: None,
                            });
                        }
                    }`

Trunk.toml Configuration

 [build]
   dist = "dist"
   [serve]
   address = "127.0.0.1"
   port = 8888
   open = true
   no_autoreload = false
   filehash = false
   ws_protocol = "ws"
   [[proxy]]
   backend = "ws://192.168.64.100:5000/api/ws"
   [[proxy]]
   rewrite = "/api/"
   backend = "http://192.168.64.100:5000/api/"
   insecure = true

HAProxy Configuration

frontend main
bind *:5000
acl PATH_ws path_beg -i /api/v1/ws
use_backend be_rust if PATH_ws
backend be_rust
server S1 127.0.0.1:8080

Problem:

Direct connection works. Proxy connection gives a 1006 Abnormal Closure error with no close frame received. I suspect there may be a misconfiguration with my proxy handling for WebSockets or a deeper issue with how WebSockets are handled in my Rust setup. How should I adjust my proxy or server settings to maintain a stable WebSocket connection through the proxy? What could be causing these abrupt WebSocket closures and how can I debug this effectively?

Upvotes: 0

Views: 91

Answers (0)

Related Questions