mclintprojects / actioncable-vue

A Vue plugin that makes integrating Rails Action Cable dead-easy.
MIT License
182 stars 37 forks source link

ActionCable url is not set correctly when using v3 on rail 7.2 #81

Closed iuri-gg closed 1 week ago

iuri-gg commented 2 months ago

Describe the bug url for websocket connection defaults to null when using v3 version of the package with vue 3 and rail 7.2. v2 of the package was working with uid patch.

Temporary fix is to import ActionCable in js and initialize ActionCableVue with connectionUrl: ActionCable.getConfig("url")

To Reproduce Steps to reproduce the behaviour:

  1. Use rails 7.2, vue 3 and latest version of this lib
  2. Try to subscribe to any channel
  3. observe websocket url in dev console trying to connect to null

Expected behaviour It should be using ws url from ActionCable

Plugin version (please complete the following information):

    "@rails/actioncable": "^7.2.100",
    "actioncable-vue": "^3.0.1",
mclintprojects commented 2 months ago

@iuri-gg Can you please share the "setup" code that connects to your ActionCable server?

iuri-gg commented 2 months ago

Sure, I am not using the composition API of vue 3 - still using the options API. I have the following code:

  mounted() {
    this.$cable.subscribe({ channel: "ChannelName", id: this.record.id });
  },
mclintprojects commented 2 months ago

@iuri-gg Please share your app.use(ActionCableVue, { ... }) setup code as well. I just tested locally with my dev Vue 3 project and Rails API, and it connected successfully.

iuri-gg commented 2 months ago

if I uncomment connectionUrl, then it works. I wonder if it is due to connectImmediately: true

  app.use(ActionCableVue, {
    debug: process.env.NODE_ENV === "development", // eslint-disable-line no-undef
    debugLevel: "info",
    connectImmediately: true,
    unsubscribeOnUnmount: true,
    // connectionUrl: ActionCable.getConfig("url"),
  });
mclintprojects commented 2 months ago

@iuri-gg The library requires you to set a connectionUrl, especially if connectImmediately is set to true. I'm creating a patch that prevents connection unless the connectionUrl is provided.

iuri-gg commented 2 months ago

is the readme out of date then? According to it connectImmediately defaults to true and is optional. Also, readme states that connectionUrl is optional and can be omitted for the default behavior. All of that worked with v2, but with v3 it changed and does not work.

mclintprojects commented 2 months ago

@iuri-gg I just released 3.0.4. Please try that and let me know if the issue remains.

iuri-gg commented 2 months ago

still the same issue on v3.0.4. I even tried not passing connectImmediately in app.use, but no difference

mclintprojects commented 2 months ago

@iuri-gg Please share a screenshot of the websocket URL in the dev console.

iuri-gg commented 2 months ago

URL of the page is http://lvh.me:3000/payout_batches/0191af19-35fa-7b9f-884d-5cc3c34847f6

image

mclintprojects commented 2 months ago

@iuri-gg It looks like the URL is correct, but your batch ID isn't being set. Can you please share the code that creates that URL?

iuri-gg commented 2 months ago

It looks like the URL is correct, but your batch ID isn't being set. Can you please share the code that creates that URL?

No, URL is not correct. action cable URL does not change on different pages - it is always the same WebSocket URL. In production it is usually /cable and in development it can be mounted on a different port. For me, it is lvh.me:8080/cable and I can see the value is present in meta tag on the page correctly:

<meta name="action-cable-url" content="ws://lvh.me:8080/cable">
iuri-gg commented 2 months ago

As for the code. if I specify connectionUrl manually, it works correctly. If I don't specify it, then it gets the wrong URL. Default behavior was correct on v2, and with v3 it broke.

    connectionUrl: ActionCable.getConfig("url"),
clemens commented 2 months ago

I ran into a similar problem with Rails 7.1, so I don't think the problem is related to Rails 7.2.

What fixed it for me was to change the environment variable that contains the connection string (in my case import.meta.env.ACTIONCABLE_HOST) to include the VITE_ prefix (so import.meta.env.VITE_ACTIONCABLE_HOST).

Since this is a behavior of Vite and not Rails/ActionCable and there was a recent Vite commit that changed import.meta behavior (see https://github.com/vitejs/vite/pull/17648), I think that's where it might originate. (I updated to Vite 5.4.x not too long ago, probably slightly before or after ActionCableVue 3.0.)

EDIT Turns out this only fixed it on localhost (using vite dev). I'm still at a loss regarding deployed environments, so I've now resorted to using

const connectionUrl = `ws${['development', 'test'].includes(import.meta.env.MODE) ? '' : 's'}://${window.location.host}/cable

This works due to how the app in question is set up.

mclintprojects commented 1 week ago

For v3.x, I didn't change anything other than updating to the latest version of actioncable. The fix for this issue is manually specifying the connectionUrl when connecting.