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:
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
- Create new Rails app
- Run the StimulusReflex installer
- Configure the ActionCable standalone server
- Configure the
session_store
in your environmentRails.application.configure do config.cache_store = :redis_cache_store, { url: ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } } config.session_store :cache_store, key: "_sessions_development", compress: true, pool_size: 5, expire_after: 1.year end
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
@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
- create a project
- minimal controller with "hello"
- 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:
- 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
- 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