rails: Rendering a partial outside of a controller results in the wrong host being used in Active Storage URLs
Steps to reproduce
There are various ways to reproduce this. What I did was render an Action Text content field with an image attachment within a Turbo stream using the broadcasts_to
class method (which renders in a background job).
Other issues referring to this behavior:
- https://github.com/hotwired/turbo-rails/issues/54 (closed by the person who opened the issue, who found a workaround for other uses of Active Storage but not for the Action Text case)
- https://github.com/rails/rails/issues/31979 (closed by stale bot, contains full repro steps)
- https://github.com/rails/rails/issues/35578 (fixed, but only for Action Mailer)
It appears that this issue has been around for some time, and that it affects multiple out-of-the box uses of Rails.
Expected behavior
The url in the image tag <src>
generated from the attachment should use the default host. In the case of my example from dev mode, it should be ‘localhost’.
Actual behavior
The attachment host in the <src>
url is ‘example.org’. This differs from the behavior when rendering from a controller.
System configuration
Rails version: 6.1.3.1
Ruby version: 3.0.0
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 17 (12 by maintainers)
Commits related to this issue
- Use routes.default_url_options in AC::Renderer env When a host is not specified for an `ActionController::Renderer`'s env, the host and related options will now be derived from the routes' `default_u... — committed to jonathanhefner/rails by jonathanhefner 2 years ago
- Modify the renderer ENV to include the host name and relative URL root https://community.openproject.org/work_packages/49086 Just modifying the defaults do not work see: - https://github.com/hotwi... — committed to opf/openproject by oliverguenther 10 months ago
Note to self, and to anyone experiencing similar issues - you can’t do:
config.action_controller.default_url_options = { host: "localhost:3020" }
Instead, you must use an explicit port specification
config.action_controller.default_url_options = { host: "localhost", port: 3020 }
Hmmm, good point on rake tasks. I don’t have any great ideas for that, for multi-host apps I think there’s only so much the framework can infer for you.
Yep, that’s not a bad idea.
Thanks for the great detail. This is an interesting bug. Some quick notes:
ApplicationController.render
. So that should respect what you have set forconfig.action_controller.default_url_options
(as you said). I couldn’t see that in your sample app; can you confirm that if you add that config, the bug goes away?request.host
. Similar to https://github.com/rails/rails/pull/32085 and https://github.com/rails/rails/pull/20800@lfalcao Thanks for taking a look at this. I’m not sure I follow what you’re doing. Are you proposing a change in Rails or a monkey patch in my app?
If you mean a change to Rails, then I’m still not sure how to pass in the defaults. This issue is triggered in my case by using library features (Hotwire’s various
:broadcast_later
features) that initiate rendering through some indirection, so I’m not well-positioned to alter rendering arguments through any new pathways.If you mean to suggest that I patch my app, is that solution superior in any way to this?
The code above is my current workaround, which is easy and reliable, but doesn’t work with apps accessible on multiple hosts. Thankfully, I have apps that hit this issue and apps that use multiple hosts, but no apps that do both. 🙂
My understanding of the problem is this:
I wanted to lay this out point-by-point for discussion, but based on your post I’m pretty sure you understand this better than I do, so let me know if I got any of the summary points wrong or misunderstood what you were proposing. Thanks again for looking at this.
Hi @brian-kephart, I was suggesting a possible way to fix into Rails core. But its not the ideal, as it would not work with multipe hosts too. What you and @ghiculescu said, gave me some insights. Later I’ll try to take a look into this again.