因此,resolve_model_to_route有两个值:

Rails.application.config.active_storage.resolve_model_to_route = 
  :rails_storage_proxy || :rails_storage_redirect

它们都会生成两个不同的URL:

  1. 对于:rails_storage_proxy,URL是这样的:rails/active_storage/blobs/proxy
  2. 对于:rails_storage_redirect,URL是这样的:rails/active_storage/blobs/redirect

这两个URL有什么不同?

我自己发现:URL:rails/active_storage/blobs/proxy会从CDN返回存储文件,而不是像S3那样直接从存储服务提供文件,如果是这样的话,我们在这里哪里提到CDN URL?

推荐答案

resolve_model_to_route是Ruby on rails的active Storage框架中的一个配置选项,用于全局更改active Storage文件的交付方式,它实际上可以有两个值::rails_storage_proxy:rails_storage_redirect.

  • :rails_storage_proxy选项使Active Storage通过应用程序提供文件.这在您希望在提供文件之前应用应用程序逻辑的情况下非常有用,例如身份验证或转换.

  • 另一方面,:rails_storage_redirect选项会导致Active Storage为存储服务(如S3、Azure、Google Cloud等)中的文件生成一个URL,然后将客户端重定向到该URL.这减轻了从应用程序向存储服务提供文件的负担,但这意味着文件将直接提供给客户端,而无需您的应用程序进行任何干预.

亦见"Rails now serves files via proxy"by Swaathi Kakarla


Regarding the CDN: using a CDN with Active Storage generally involves configuring your storage service (like S3) to use the CDN, rather than configuring Active Storage itself.
If your storage service is set up to use a CDN, then when Active Storage generates a URL for a file (using either :rails_storage_proxy or :rails_storage_redirect), that URL will be a CDN URL. The specific process for setting this up would depend on the storage service and CDN you are using.

The proxy feature introduced in Rails 6.1 made this process easier and more flexible. The proxy feature provides a permanent URL to an asset through your Rails application instead of an expiring URL, which enables a CDN to cache the file after the first request.
See "The Complete Guide to using a CDN with Rails Active Storage" by Colleen Schnettler

要将您的Rails应用程序配置为使用具有活动存储的CDN,您需要进行以下更改:

  • storage.yml文件中,将public:true设置添加到您的配置中.

  • 在您的路径中,修改提供文件的方式以提供永久URL.这可以通过修改routes.rb文件来直接使用该路由来完成.然后,在您的视图中,使用像cdn_image_url(@user.avatar)这样的助手通过CDN为您的文件提供服务.

  • 如果要代理所有文件,可以向应用程序添加初始值设定项.在config/initializers中创建一个active_storage.rb文件,其中包含以下行:Rails.application.config.active_storage.resolve_model_to_route = :rails_storage_proxy.这将使所有文件使用代理URL.

  • 您还可以直接使用路由助手来生成代理URL.例如,您可以在视图中使用rails_storage_proxy_path(@user.avatar),它还接受允许您指定CDN主机的参数.

要将CDN连接到您的应用程序,您需要:

  • Select 一个CDN并将您的自定义域名添加到您的应用程序设置中(如果使用Heroku这样的平台).

  • 将目标添加到您的DNSProvider .这通常是在您的主机Provider 添加自定义域之后提供的.

  • 完成您 Select 的CDN的设置.这通常涉及根据您的CDNProvider 的提示添加额外的DNS记录.

  • 等待域名解析,然后完成CDN设置.在您的生产环境中添加CDN_HOST作为环境变量.


I'm using S3 – it is public and in front of Amazon S3, Cloudflare has been enabled via the bucket permission policy. Now, when Rails generates a URL, and I pass the host(host is cdn.myapp.com and this domain is forwarded to Amazon S3), the URL looks like: https://cdn.myapp.com/rails/active_storage/blobs/proxy/....png.
The thing is: Rails app is hosted at myapp.com, and not at cdn.myapp.com.
cdn.myapp.com is for accessing the S3 bucket via Cloudflare, so the 'host' thing does not make sense here.

What works out of box is: ["cdn.myapp.com" + object.key].
But I'm here trying to make sense of how Rails can help us hide this URL, and could redirect a user to this URL automatically.

因此,您确实要在代码中手动构造URL.您可以将字符串"cdn.myapp.com"object.key连接起来,其中object是活动存储对象(例如,文件或图像)的实例,而key是文件在存储系统中的唯一标识符.

此手动URL构造可以在视图或控制器中完成,您可以在需要创建URL以访问存储的文件的任何位置完成,如下所示:

<%= image_tag "https://cdn.myapp.com/#{@user.avatar.key}" %>

Wtih @user.avatar being an Active Storage object and key the unique identifier for the file on the storage service.
That would construct a URL directly to the file on the CDN.

但是,正如您已经注意到的,这会公开文件的直接URL,这可能不是您想要的.

Active Storage提供的代理方法允许创建永久URL,以隐藏文件的实际存储位置,并可与CDN一起使用.这些永久URL以格式https://myapp.com/rails/active_storage/blobs/proxy/...构造.

在您的特定设置中,由于您使用的是CDN,因此需要调整文件的路由和服务才能使用此功能.这可以通过相应地更新您的storage.ymlroutes.rb文件来实现.

如果您想使用Rails自动生成这些URL,您将需要利用Rails的代理功能和一些路由配置.正如我们前面讨论的,代理功能通过您的Rails应用程序提供了一个指向assets资源 的永久URL,然后可以通过您的CDN提供该URL.

因此,请确保您的Rails应用程序设置为使用活动存储的代理.如果要代理所有文件,请在应用程序的初始值设定项中添加以下行(例如,创建一个config/initializers/active_storage.rb文件):

Rails.application.config.active_storage.resolve_model_to_route = :rails_storage_proxy

使用这种配置,标准的Rails视图调用(如<%= image_tag (@user.avatar), width: 500, height: 500 %>)将生成一个代理URL.

在您的Rails应用程序的配置中,将host选项设置为您的CDN的域(即cdn.myapp.com).这可以在您的production.rb文件(或用于测试的development.rb)中使用config.action_controller.asset_host = 'https://cdn.myapp.com'来完成.

最后,用Amazon S3的适当配置更新您的storage.yml,并将其公之于众:

amazon:
  service: S3
  access_key_id: <your_access_key_id>
  secret_access_key: <your_secret_access_key>
  region: <your_region>
  bucket: <your_bucket_name>
  public: true

When you need to display an asset, use the Rails view helpers as you would normally. For example, <%= image_tag @user.avatar %>.
With the proxying and asset host configuration, Rails should automatically generate URLs in the form you have described, like https://cdn.myapp.com/rails/active_storage/blobs/proxy/....png.

这种配置应该允许Rails为您的assets资源 生成适当的URL,这些URL通过您的Cloudflare CDN和Amazon S3存储桶提供.CDN应该处理assets资源 的缓存和交付,从而缩短加载时间并降低服务器负载.Rails生成的URL将是永久性的,不会显示到S3存储桶中的assets资源 的直接链接.

请务必将storage.yml中的占位符<...>替换为您的实际AWS凭据和存储桶信息(并确保不会泄露所述凭据!)


为了确认:PUT为config.asset_host = 'cdn.myapp.com',Rails将生成一个类似"myapp.com/rails/active_storage/blobs/proxy/..png"的URL,并最终重定向到CDN URL?

我之所以这样问,是因为我无法在应用程序或浏览器中的任何地方确认.

不完全是.如果将config.asset_host设置为'cdn.myapp.com',Rails将为您的资源生成以'cdn.myapp.com'开头的URL.它不会重定向到CDN URL,而是assets资源 请求将直接到达CDN.如果CDN上尚未缓存该assets资源 ,CDN会从您的应用服务器中获取该assets资源 ,并进行缓存和服务.

在Rails中为assets资源 生成的URL应该类似于:对于常规assets资源 为'cdn.myapp.com/assets/image.png',对于活动存储assets资源 为'cdn.myapp.com/rails/active_storage/blobs/proxy/..png'(如果您使用代理功能).

但是,请记住,您预期的行为,即CDN URL在浏览器中可见,可能不会像您预期的那样发生.当您配置CDN时,用户在其浏览器中看到的URL可能不会更改以反映CDN URL-CDN在用户和您的服务器之间作为一个透明的层运行.用户从您服务器的URL请求资源,CDN拦截该请求,并在可能的情况下为资源提供服务.如果它不能(因为资源不在其缓存中),它会从您的服务器请求资源,对其进行缓存,然后将其提供给用户.

因此,当使用CDN时,用户可能不会在他们的浏览器中看到不同的URL.您通常可以通过在浏览器的开发工具中判断网络流量,并查看assets资源 请求的头部来验证CDN是否正常工作.像X-Cache: HIT这样的报头将指示CDN正在服务该资源.

Ruby-on-rails相关问答推荐

如何将Form_With用于多个没有控制器的型号

引用连接 Rails 表中枚举的查询

Rails 7 共享刺激控制器功能

别名可能与不同模型的相同别名有许多关联?

Rails 3.1 assets资源 - 奇怪的开发服务

在 Rails 中找不到关联问题

在 Rails 的 ActiveRecord 中,touch 有什么用?

如何在 Rails 上生成 AuthenticityToken

删除链接在 Rails 3 视图中发送Get而不是Delete

未捕获的类型错误:未定义不是函数- 初学者 Backbone.js 应用程序

按周/月/等和 ActiveRecord 分组?

RubyMine - 关闭在空行中间单击的功能

如何仅使用 PostgreSQL 创建简单的模糊搜索?

如何一次显示一条 Ruby on Rails 表单验证错误消息?

Ruby on Rails:如何为 postgresql 编辑 database.yml?

Ruby 1.9.2 和 Rails 3 无法打开 rails 控制台

Rails - 邮件,将正文作为纯文本获取

何时在 Ruby on Rails 中使用 lambda?

在 Rails 中显示主机名和数据库名

为什么 rails bootstrap 这么慢,我该怎么办?