如何配置Rails内置URL助手生成的协议(Rails 7.0 + CDN SSL终止场景)
我之前碰到过一模一样的情况——Rails 7应用躲在CDN后面做SSL终止,内部用HTTP服务,结果ActiveStorage的直传链接全生成了HTTP,直接被浏览器的安全策略拦了。试了好几个方法,终于搞定了,分享给你:
方法一:让Rails识别CDN传递的真实协议(推荐)
这是最贴合Rails设计思路的方案,核心是让Rails信任CDN作为反向代理,读取它传递的X-Forwarded-Proto头(CDN会把外部用户访问的HTTPS协议通过这个头告诉后端应用)。
打开config/environments/production.rb,添加以下配置:
# 信任CDN的IP地址(建议替换为你的CDN实际IP段,更安全,避免恶意请求伪造头) config.action_dispatch.trusted_proxies = [IPAddr.new('0.0.0.0/0')] # 全局设置URL助手的默认协议为HTTPS config.action_controller.default_url_options = { protocol: 'https' }
配置完成后,Rails会把CDN发送的X-Forwarded-Proto: https当作请求的真实协议,所有URL助手(包括ActiveStorage的rails_direct_uploads_url)都会自动生成HTTPS链接。
方法二:单独覆盖ActiveStorage直传控制器的URL配置
如果方法一没生效,可能是因为ActiveStorage的内部控制器没有继承你的ApplicationController,导致全局配置没覆盖到它。这时候可以直接修改它的URL生成逻辑:
新建或编辑config/initializers/active_storage.rb,添加以下代码:
module ActiveStorageDirectUploadOverride def url_options super.merge(protocol: 'https') end end # 把自定义的URL配置混入ActiveStorage的直传控制器 ActiveStorage::DirectUploadsController.include(ActiveStorageDirectUploadOverride)
这样ActiveStorage直传接口的URL生成时会强制使用HTTPS协议,绕开内部HTTP的限制。
方法三:确保路由加载后设置全局默认协议
你之前尝试修改命名路由的defaults但没生效,大概率是初始化时机不对——路由还没加载完成就修改了配置。可以用Rails的after_initialize钩子,确保路由完全加载后再设置:
打开config/application.rb,添加以下代码:
config.after_initialize do # 全局设置所有命名路由的默认协议为HTTPS Rails.application.routes.default_url_options[:protocol] = 'https' # 也可以单独针对rails_direct_uploads路由做定向配置 Rails.application.routes.named_routes[:rails_direct_uploads].defaults[:protocol] = 'https' end
这个时机下路由已经完全初始化,修改的默认配置会被正确应用到所有URL生成逻辑中。
备注:内容来源于stack exchange,提问作者Shay.

