在Sinatra中使用多个公共目录

6
我的sinatra应用程序包含在一个gem中。这意味着资源(css/js)存储在gem中。该应用程序会动态生成图像并提供服务;目前将其写入并从public目录中提供服务。
我希望不要将生成的图像写入gem目录,而是写入实现此gem的Web应用程序下的某种“缓存”目录。
Gem已安装在/var/www/TE/shared/gems/ruby/1.8/gems/tubemp-0.6.0,因此资源位于例如/var/www/TE/shared/gems/ruby/1.8/gems/tubemp-0.6.0/lib/public/css/
Gem部署在简单的rack-app中/var/www/TE/current/,因此我希望从/var/www/TE/current/public编写和提供缩略图。
但是,自定义公共目录的设置仅允许设置一个目录:
set :public_folder, File.join(Dir.pwd, "public")

打破了资产的服务;Dir.pwd是Rack应用程序的目录。Public现在是Rack应用程序下的目录,但这不是资产所在的位置:它们位于gem中的“public”下。

set :public_folder, File.join(gemdir, "public")

中断生成缩略图的服务。

我可以重写应用程序,使其通过Sinatra提供资产或缩略图,但这似乎有些繁琐。

这是唯一的方法吗?还是有办法让Sinatra从两个或更多公共目录中提供静态项目的服务


1
如果我没有完全清楚正在发生的事情,请原谅我。是什么阻止您将生成的图像写入机架应用程序的公共目录? - ian
什么都没有;但这需要我将该目录设置为“public”,然后突然间与 gem 一起提供的资源(..../1.8/gems/foo-0.0.0/public/javascript/application.js)不再被提供。更新了问题以解释这一点。 - berkes
非常清晰,谢谢。我已经添加了一个答案。 - ian
1个回答

3

我认为可能有几个选项,但这是我如何让一个小应用程序从两个位置(扩展和主应用程序的公共文件夹)提供静态文件的方法:

目录布局

root/
  app.rb
  public/images/foo.jpg
  lib/sinatra/
       gemapp.rb
       gemapp/public/images/bar.jpg

插件

# lib/sinatra/gemapp.rb
module Sinatra
  module GemApp
    def self.registered(app)

      app.set :gem_images, File.expand_path( "gemapp/public/images", File.dirname(__FILE__))

      app.get "/images/:file" do |file|
        send_file File.join( settings.gem_images, file)
      end

      app.get "/gemapp" do
        "running"
      end
    end
  end
  register GemApp
end

主要应用程序

require 'sinatra'

require_relative "./lib/sinatra/gemapp.rb"

get "/" do
  "home"
end

对我来说,它很好地提供了文件服务。


我曾担心通过Sinatra路由提供资产将是唯一的选择。很遗憾,但我可以通过调整nginx从其缓存中提供资产来减轻痛苦。 - berkes
@berkes 这为什么是一件坏事? - ian
据我所知,提供静态资源时,如果不通过Sinatra提供服务,速度会快得多。 - berkes
如果按照这种方式进行,我会使用路由添加缓存头和可能为图像添加唯一URL,并使用助手来帮助查找它。这样,痛苦只有第一次命中,但您可以获得一些通过仅使用Nginx无法获得的好处。否则,是的,Nginx会更快,但然后我会让应用程序写入Nginx提供的目录并跳过Rack。 - ian
1
我认为代码不安全。如果有人在文件名中输入“../.env”会发生什么?他们将可以访问应用程序的机密信息。从用户输入构建路径是不安全的。静态资源需要有一个强制的根目录。 - max pleaner
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接