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

Workaround - React Native STOMP issue because NULL chopping #55

Open
omars94 opened this issue Dec 31, 2018 · 9 comments
Open

Workaround - React Native STOMP issue because NULL chopping #55

omars94 opened this issue Dec 31, 2018 · 9 comments

Comments

@omars94
Copy link

omars94 commented Dec 31, 2018

I was facing an issue where the stomp client doesn't get connected to server because of the null terminator and the connect message wasn't parsed at server side correctly because it was sent as string instead of binary array.

I did lots of debugging on it and the solution was to make isBinaryBody always true
like so

FrameImpl.prototype.serialize = function () {
       var cmdAndHeaders = this.serializeCmdAndHeaders();
       if (this.isBinaryBody || true) { // to always return as binary array
           return FrameImpl.toUnit8Array(cmdAndHeaders, this._binaryBody).buffer;
       }
       else {
           return cmdAndHeaders + this._body + byte_1.BYTE.NULL;
       }
   };
@kum-deepak
Copy link
Member

Many thanks for this. I do not use React Native myself.

This was earlier reported as slightly different issue
(stomp-js/stomp-websocket#37). The underlying issue seems to be Reactive Native having issue with NULL characters in strings. NULLs in string are needed to support STOMP protocol. See: facebook/react-native#12731

Based on your analysis it seems, sending messages in binary bypasses the issue. I will wait for your results - based on that an option (say alwaysSendBinaryPackets) may be added to the config.

Making this change will control packets sent to the broker. However the communication may fail if the server sends a text packet. Some brokers (like RabbitMQ has an option to always send binary packets).

@kum-deepak
Copy link
Member

A flag is added in configuration forceBinaryWSFrames, this will make outgoing frames to be binary.

@omars94
Copy link
Author

omars94 commented Jan 18, 2019

was it added to the package yet?
I couldn't find this change in change-log

@omars94
Copy link
Author

omars94 commented Jan 18, 2019

Tried it and its working perfectly.

@WhiteHatTux
Copy link

Using only binaryMessages was causing other problems for me, so I found this to handle the error on the spring server:

package com.beskgroup.dst.backend.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;

/**
* Register this in WebSocketConfig
*/
public class CustomWebSocketHandlerDecorator
  extends WebSocketHandlerDecorator {

  private static final Logger logger = LoggerFactory.getLogger(CustomWebSocketHandlerDecorator.class);

  public CustomWebSocketHandlerDecorator(WebSocketHandler delegate) {
    super(delegate);
  }

  @Override
  public void handleMessage(final WebSocketSession session, final WebSocketMessage<?> message)
    throws Exception {
    if (message instanceof TextMessage) {
      TextMessage msg = (TextMessage) message;
      String payload = msg.getPayload();

      // only add \00 if not present (iOS / Android)
      if (!payload.substring(payload.length() - 1).equals("\u0000") && !payload.equals("\n")) {
        final TextMessage message1 = new TextMessage(payload + "\u0000");
        super.handleMessage(session, message1);
        return;
      }
    }

    super.handleMessage(session, message);
  }
}

The register this decorator with your websocket:

public class WebSocketConfig
  extends AbstractWebSocketMessageBrokerConfigurer {

  @Override
  public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
    registration.addDecoratorFactory(CustomWebSocketHandlerDecorator::new);
  }
  ....
} 

@kum-deepak kum-deepak changed the title Stomp not connecting to Spring Server in React Native Workaround - React Native STOMP issue because NULL chopping Feb 2, 2019
@slavikdenis
Copy link

@WhiteHatTux hi, we tried your implementation without any luck :/

@kum-deepak
Copy link
Member

I think it may be worth trying to fix the underlying issue in React Native 😄

@slavikdenis
Copy link

@kum-deepak yeah that would be better 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants