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

React Native: Received data was not a string or was not recognized encoding #771

Closed
davidgljay opened this issue Aug 24, 2018 · 7 comments
Closed
Labels

Comments

@davidgljay
Copy link

I am trying to create a connection between react native and a flask-socketio application.

I noticed that a normal browser could connect to the backend while react-native could not. Upon further investigation, calls from normal browsers included a sid value in the query, while calls from react-native do not.

It looks like the sid is initially set by a GET request to flask-socketio. When I tried curling that request I got this response.

��0{"sid":"a4ff1b37b91243c7a89a66f7159902f4","upgrades":[],"pingTimeout":60000,"pingInterval":25000}���40

Note the weird characters at the beginning and end. Also, in react native I get a somewhat cryptic error that reads: 'Received data was not a string or was not recognized encoding'.

It SEEMS like normal browsers are enable to interpret this encoding but react native is not. I'd like to get flask-socketio to send paramaters encoded in a more standard way if possible, which will hopefully address the issue in react native. I've tried changing the 'json' parser passed to Flask-socketio and this doesn't seem to help. Here's my code:

Server

import json
from flask_socketio import SocketIO
from config import config

CONFIG_NAME = os.getenv('TS_CONFIG_ENV', 'dev')

APP: Flask = Flask(__name__)
APP.config.from_object(config.CONFIG[CONFIG_NAME])
socketio = SocketIO(APP, async_mode='gevent', json=json)
socketio.run(APP, host=APP.config['HOST'], port=APP.config['PORT'], log_output=True)

I've tried using both polling and websockets on the client, neither seems to work.

@miguelgrinberg
Copy link
Owner

The "weird" characters are the binary encoding of Socket.IO packets. This is a standard format documented in the Socket.IO protocol.

The sid is the Socket.IO session id. It is returned by the server in the response to the initial connection request, along with other settings. The client is supposed to send that sid in the query string of all subsequent requests.

See #716 for a similar issue. In that case the problem was addressed by connecting via websocket without passing through long-polling first.

@davidgljay
Copy link
Author

davidgljay commented Aug 24, 2018

Connecting via websockets didn't work in this case. It looks like the binary encoding isn't being interpreted by react native. Is there a way to try a different encoding?

To be more specific:

Setting transports: ['websocket'] does not resolve the issue.

@davidgljay
Copy link
Author

davidgljay commented Aug 24, 2018

Update: when I try a node implementation of socket.io the encoding on this response is different:

node:

96:0{"sid":"ZddvxiNSLbHI1b8NAAAB","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}2:40

flask-socketio:

�0{"sid":"f985afd2d41846a2bbe7b7955440e7b0","upgrades":[],"pingTimeout":60000,"pingInterval":25000}�40 

(Note, some special characters removed because they were breaking the github comment.)

React native can connect successfully to the node server, but not to the flask-socketio server.

@miguelgrinberg
Copy link
Owner

Yes, this client appears to have trouble with the binary representation, but that is the default. If it wants the text representation it should ask for it by sending b64=1 in the query string, which apparently the second client that you tested uses. See https://github.com/socketio/engine.io-protocol#payload for the best reference regarding these formats.

I should note that none of this applies to WebSocket, and that is why going direct to WebSocket worked for this other person. Not sure why it does not work for you, but I'm certain you must have a different problem since the "payload" encoding is a concept that is only used in HTTP.

@davidgljay
Copy link
Author

davidgljay commented Aug 24, 2018

Thanks so much! Adding query: 'b64=1' resolved the issue in react-native. It's using polling rather than websockets, but I can debug the websockets side of things later.

If I had to guess, I'd say that the XMLHttpRequest handler in react native doesn't know how to deal with binary encoding. I didn't include b64=1 in my request to node, it just defaulted to that, so maybe they're the ones not following the standard?

Thanks again!

@konclave
Copy link

@davidgljay did you made it work? I set the b64 param for the GET request and it made the first request work, so I've got a socket.io session id, but GET request for protocol switch wasn't sent after that.

@glenvollmer
Copy link

glenvollmer commented Sep 16, 2019

Yes, this client appears to have trouble with the binary representation, but that is the default. If it wants the text representation it should ask for it by sending b64=1 in the query string, which apparently the second client that you tested uses. See https://github.com/socketio/engine.io-protocol#payload for the best reference regarding these formats.

Maybe you should include this in the documentation ¯_(ツ)_/¯

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

No branches or pull requests

4 participants