rsocket-js: Buffer type check is broken after upgrade rsocket.js to 0.0.22

rsocket.js introduces new LiteBuffer implementation in recent versions, but in file /rsocket-core/src/RSocketEncoding.js, it still use the raw Buffer.isBuffer to check the type, this change break the working code based on 0.0.19.

Steps to Reproduce

Use BufferEncoders as following:

  const transport = new RSocketWebSocketClient(
    {
      url: getSocketURL(),
      wsCreator: (url: string) => new WebSocket(url),
      debug: true,
    },
    BufferEncoders,
  );

then you will get the error message raised by RSocketEncoding.js

RSocketEncoding: Expected value to be a buffer,

Possible Solution

Update the Buffer.isBuffer check to compatible with LiteBuffer.

Environment

  • RSocket version(s) used: 0.0.22

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 25 (16 by maintainers)

Commits related to this issue

Most upvoted comments

@myklt, @kkojot @lempikaSolutions @yingjieg I did a temporary fix in 0.0.25 which should eliminate that bad experience you all faced before. I recommend updating on 0.0.25 as soon as possible.

@myklt I did a check with 0.0.25 and the app you mentioned before and everything worked like a charm!

Hi @OlegDokuka ,

I’ve faced the same issue, but unfortunately do not have control of webpack default polyfills (using create-react-app). Could you please give me a hint, why the proposed solution by @yingjieg to use LiteBuffer.isBuffer in RSocketEncoding.js wouldn’t work?

For now, a very quick and dirty solution was to set buffer._isBuffer = true to created composite buffer using RSocket utils.

Regards, Mykolas.

Hi @OlegDokuka

Thank you for investigating this issue. you are right, the root cause is the conflict of polyfill Buffer implementation and LiteBuffer, but I think disable webpack-node-libs is not a good choice, lots of UI projects based on polyfill Buffer implementation. Like our project, it heavily depends on Buffer base64 encode/decode.

After investigation, I think following solutions might work.

Make sure Buffer.isBuffer import the LiteBuffer implementation in RSocketEncoding.js

 import type {Encodable} from 'rsocket-types';

// add this import in rsocket-core/src/RSocketEncoding.js
+import {LiteBuffer as Buffer} from './LiteBuffer'; 

then we can import toBuffer, createBuffer from rsocket-core

  import { toBuffer, createBuffer } from 'rsocket-core';

  return encodeAndAddWellKnownMetadata(
    encodeAndAddCustomMetadata(
      createBuffer(0),
      'message/x.rsocket.authentication.bearer.v0',
      toBuffer(token),
    ),
    MESSAGE_RSOCKET_ROUTING,
    toBuffer(String.fromCharCode(ROUTE.length) + ROUTE),
  );

or we can inject LiteBuffer in webpack:

  new webpack.ProvidePlugin({
    Buffer: ['buffer', 'Buffer'],
    LiteBuffer: ['rsocket-core/build/LiteBuffer.js', 'LiteBuffer'],
  }),
export function getMetadata(token: string) {
  return encodeAndAddWellKnownMetadata(
    encodeAndAddCustomMetadata(
      LiteBuffer.alloc(0),
      'message/x.rsocket.authentication.bearer.v0',
      LiteBuffer.from(token),
    ),
    MESSAGE_RSOCKET_ROUTING,
    LiteBuffer.from(String.fromCharCode(ROUTE.length) + ROUTE),
  );
}

What do you think ?

BR Yingjie

Hi, I have experienced this issue with rsocket 0.0.27 as this is a temp demo project I looked for a quick workaround, and I fixed it by just added the following dependency to package.json: "node-polyfill-webpack-plugin": "^2.0.1" leaving it here in case someone will need a temp quick workaround

Getting this error in 0.0.27

Invariant Violation: RSocketEncoding: Expected value to be a buffer, got `)message/x.rsocket.authentication.bearer.v0...

Using CRA and there are no errors in dev mode, only in production builds

I’m getting a buffer warning like this: RSocketEncoding: Expected value to be a buffer, got '���route-here'

Strangely enough, this does NOT occur if using webpack’s devtool: 'eval'. But it happens with anything else. Consequently, it works in dev but breaks in production. 😦

This is with rsocket-core 0.0.25.

We’ve noticed the same issue with 0.0.25, some of the third-party libraries managed to pick up a polyfil and started failing with Error: Not implemented: "base64" encoding.

Hi @OlegDokuka! Thanks a lot, I’ve just tried it out and it works like a charm!

Apparently I got happy too early. It works perfectly while running locally, but something wrong happens, when the production bundle is built: two type of Buffer objects are being created & compared again. I will investigate it further next week, how to avoid the Buffer from Webpack being used.

@OlegDokuka , thanks for the fix! Upgraded to 0.0.23 and it works as expected now.

I had the same issue that @mykit and indeed the solution that he proposed works for me !!!
const metadataBuffer = encodeCompositeMetadata([ [TEXT_PLAIN, Buffer.from(‘Hello World’)], [MESSAGE_RSOCKET_ROUTING, () => encodeRoute(getTokenRoute)], [MESSAGE_RSOCKET_AUTHENTICATION, () => encodeSimpleAuthMetadata(username, password)] ]); // eslint-disable-next-line no-underscore-dangle metadataBuffer._isBuffer = true;

@myklt as I mentioned, Webpack sets its own polyfills which are incompatible with LiteBuffer.

Looks like it is a common issue for the webpack users. I will try to make a workaround. Stay tuned

Cheers, Oleh

Sounds reasonable. I will add a separate issue on moving lite-buffer to a separate module