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.
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"] }, []]