stimulusreflex / stimulus_reflex

Build reactive applications with the Rails tooling you already know and love.

Home Page:https://docs.stimulusreflex.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

StimulusReflex is not compatible with the standalone ActionCable server

marcoroth opened this issue · comments

Bug Report

Describe the bug

Thanks to @javid-gulamaliyev, we were able to figure out that in the current version of StimulusReflex you can't use StimulusReflex and the Session Store if you are running ActionCable as a standalone server.

It fails to commit the session with:

Failed to commit session! undefined method `commit_session' for nil:NilClass
/usr/local/bundle/gems/stimulus_reflex-3.5.0.rc2/app/channels/stimulus_reflex/channel.rb:101

The issue is this part:

store = reflex.request.session.instance_variable_get(:@by)

reflex.request.session is just available in the web-server process and since this is executed in the context of the separate ActionCable server process it has no access to the session, which is also stated in the Rails docs.

> The WebSocket server doesn't have access to the session, but it has access to the cookies. [...]

So I'm not sure if we can actually support the standalone ActionCable server with StimulusReflex, but either we could improve the commit_session method in channel.rb to check if we actually have access to the session and if not show a more helpful warning or trying to detect if ActionCable is running in the standalone mode so we can print a warning and warn the user early.

To Reproduce

Expected behavior

Either it should just work and start to commit to the session and don't show the error or it should catch the exception and warn the user that it might be caused by running the ActionCable server in standalone mode.

Versions

StimulusReflex

  • Gem: 3.5.0.rc2
  • Node package: 3.5.0-rc2

External tools

  • Ruby: 3.2.2
  • Rails: 7.0.4
  • Node: 18.10.0

also the actioncable settings are not honored from root dir app path, unless you reverse proxy the WS:// with port included

image

@mckaygerhard this sounds like a different issue. Just for the record, would you mind sharing what you setup to make it work in your case?

Hi @marcoroth thanks in advance i will detail only relevant steps and at the end i put a reference issue pretty similar but different in context (pdfjs gem)

First using a vanilla project

  1. create a project
  2. minimal controller with "hello"
  3. change root_path as described in documentation: https://guides.rubyonrails.org/configuring.html#deploy-to-a-subdirectory-relative-url-root

In config/application.rb

module App
 class Application < Rails::Application
   ....
   config.relative_url_root = '/applicants'
   ...
 end
end

In config.ru file:

map Rails::Application.config.relative_url_root || "/" do
 run Rails.Application
end

After run rails s is working and serving not from http://localhost:3000 but for http://localhost:3000/applicants as must be.. great! now lest test using the integrated ActonCable and stimulus reflex (that i am a newbie but seems not so big issue)

Second try using a more complex project with stimulus

AS i read seems stimulux reflex uses web socket so it depends of such request to ws://localhost:3000 so lest assume all the steps and going to the details of the config root path:

After implementing stimulus reflex bla bla configure a root path (with default root set to "/" it works) change root_path as described in documentation: https://guides.rubyonrails.org/configuring.html#deploy-to-a-subdirectory-relative-url-root

In config/application.rb

module App
 class Application < Rails::Application
   ....
   config.action_cable.disable_request_forgery_protection = true
   config.relative_url_root = "/applicants"
   config.action_cable.url = "ws://localhost:3000/applicants/cable"
   ...
 end
end

In config.ru file:

map Rails::Application.config.relative_url_root || "/" do
 run Rails.Application
end

This seems do not work and action cable stimulus reflex just request always to ws://localhost:3000/cable event ws://localhost:3000/applicants/cable as i demand in configuration files

my conclusions based on that:

I concluded one of two things:

  1. Is a ghost bug in stimulus reflex that due rails is a Domain oriented framework unfortunately, and developers assumed hijacked root, so stimulus reflex (and also pdfjs gem too) assumed always a hijaked root from service web
  2. Is a bug in vage documentation from both rails and stimulus reflex due missing ways to setup a non domain oriented application and as described in https://www.phaedrasolutions.com/blog/how-to-config-subdirectory-with-rails-nginx-unicorn and also well explained at https://jlintusaari.net/deploying-rails-application-to-subdirectory/

For reference @marcoroth check this similar bug at the pdfjs fixed issue: senny/pdfjs_viewer-rails#74

I am from rails 3 when redmine was started (now we have the great gitea/forgetto/gogs) and years later i found those several inflexible things..

Does anyone have a minimal reproducible example for the original issue? If the standalone server can access Redis, and it has some environment details on the connection I think it should be possible to make a workaround for this... 🤔

Does anyone have a minimal reproducible example for the original issue?

i already make a reproducible kind of.. as example of that stimulus reflex still is not 100% honoring the RAILS configurations

If the standalone server can access Redis, and it has some environment details on the connection I think it should be possible to make a workaround for this... 🤔

this original bug implicit more than only access to resources.. as i explain, address resources are not accedible so its a clear bug..

you @Matt-Yorkley can help up making your own test of course.. just following comments

Here's a Gist with an example setup to get StimulusReflex working with ActionCable running in Standalone mode (with Devise for authentication and Redis for session storage): https://gist.github.com/Matt-Yorkley/3a523be8597f20173ba91a872250e69d

hi @Matt-Yorkley your cited example has map "/" do and if you use subpaths like map "/myapp" do the the action cable will break and fails.. as well explained at https://jlintusaari.net/deploying-rails-application-to-subdirectory/

You can use map "/" if your mount point is set to config.action_cable.mount_path = nil or set it to map "/whatever" and use config.action_cable.mount_path = "/whatever", and it'll work either way, it's a separate ru file from the main app. There's a meta tag you have to set in the head as well (mentioned in the docs) so the client side knows what to connect to.

and use config.action_cable.mount_path = "/whatever", and it'll work either way, it's a separate ru file from the main

a meta tag? Do you mean that for stimulus/reflex is not enough to set config.action_cable.mount_path = "/whatever",? Which documentation are you referring to? Stimulus documents or rails documents?

because I do all the things that https://jlintusaari.net/deploying-rails-application-to-subdirectory/ mentions there, "tricks" needed to implements property that way... it is already explained in said article