Question

I am encountering errors when I am using Ruby's File.exist? method in middleware. I have no idea why.

This is the background. I am improving some old webapp which hosts around 100GB of photos and growing. I need to replicate production environment on my computer, but I don't want to download all those files. It would be great if app could check if given file exists in my filesystem and either serve it or redirect to production server.

I thought I could do simple rack app as middleware:

require 'rack/utils'

class FetchMissingPicturesMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    if env["PATH_INFO"].starts_with? "/system/attachments/" && !File.exist?(Rails.root.join('public').join(env["PATH_INFO"][1..-1]))
      [307, { "Location" => "http://production.example.com" + env["PATH_INFO"] }, ""]
    else
      @app.call(env)
    end
  end
end

However, following error is thrown (not always, for some pictures it just works):

[2012-11-26 14:28:12] ERROR ThreadError: thread 0x10aed55e8 tried to join itself
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/actionpack-2.3.9/lib/action_controller/reloader.rb:31:in `lock'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/actionpack-2.3.9/lib/action_controller/reloader.rb:31:in `run'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/actionpack-2.3.9/lib/action_controller/dispatcher.rb:108:in `call'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rails-2.3.9/lib/rails/rack/static.rb:31:in `call'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rack-1.1.3/lib/rack/urlmap.rb:47:in `call'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rack-1.1.3/lib/rack/urlmap.rb:41:in `each'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rack-1.1.3/lib/rack/urlmap.rb:41:in `call'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rails-2.3.9/lib/rails/rack/log_tailer.rb:17:in `call'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rack-1.1.3/lib/rack/content_length.rb:13:in `call'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rack-1.1.3/lib/rack/handler/webrick.rb:48:in `service'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:162:in `start'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:95:in `start'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:92:in `each'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:92:in `start'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:23:in `start'
    /Users/skale/.rvm/rubies/ruby-1.8.7-p371/lib/ruby/1.8/webrick/server.rb:82:in `start'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rack-1.1.3/lib/rack/handler/webrick.rb:14:in `run'
    /Users/skale/.rvm/gems/ruby-1.8.7-p371/gems/rails-2.3.9/lib/commands/server.rb:111
    script/server:6:in `require'
    script/server:6

I am surprised with this issue because it's run inside mutex provided by Rack::Lock. Moving this middleware before Rack::Lock does not help. After removing File.exist? errors are gone. This is Ruby 1.8.7 with freshest (1.8.24) rubygems on Rails 2.3.9.

Thanks for your help.

Était-ce utile?

La solution

Actually, the problem was bit different. The last element of the response array should be an array too.

wrong:

[307, { "Location" => "http://production.example.com" + env["PATH_INFO"] }, ""]

good:

[307, { "Location" => "http://production.example.com" + env["PATH_INFO"] }, []]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top