我正在编写一个Rails应用程序,它有一个简单的网络爬虫,可以找到域内的所有链接,只要找到一个指向域外的链接就会停止。正如Rails开发人员一样,我已经在我的本地机器上开发并测试了代码,然后将其部署到临时服务器以在现实生活中尝试。
当爬网程序检出重定向到另一个域的URL时,在我的本地计算机上#open
方法返回一个表示重定向的空Tempfile对象。它没有跟随重定向,它只是表明发生了一次。我使用此信息来决定要反馈给用户的消息。
但是,在服务器上,此相同的#open
方法会生成RuntimeError
。我在两种环境中都运行完全相同的Ruby(2.0.0 p576)和Rails(4.0.3)版本。我假设一个给定的Ruby代码片段,对于相同版本的Ruby + Rails和相同的Rails环境,将具有完全相同的行为。发现相同的代码和明显相同的环境可能会产生不同的结果,这令人非常不安。
知道为什么同样的代码在不同的机器上有不同的行为?我应该查看哪些文件或设置,或者我应该运行哪些命令,以尝试确定这种不同行为的来源?我已将问题分离到以下示例中。
提前致谢!
Loading production environment (Rails 4.0.3)
2.0.0-p576 :001 > require 'uri'
=> false
2.0.0-p576 :003 > open 'http://www.ruby-doc.org/' # loads fine
=> #<Tempfile:/var/folders/hz/czmbmhds46s37t_pz8j198g40000gn/T/open-uri20141029-42188-51i9ls>
2.0.0-p576 :002 > open 'http://ndic.com' # loads fine
=> #<Tempfile:/var/folders/hz/czmbmhds46s37t_pz8j198g40000gn/T/open-uri20141029-42188-12kbadl>
Loading production environment (Rails 4.0.3)
2.0.0-p576 :001 > require 'uri'
=> false
2.0.0-p576 :004 > open 'http://www.ruby-doc.org/' # loads fine
=> #<Tempfile:/tmp/open-uri20141029-11034-1sq9rtm>
2.0.0-p576 :002 > open 'http://ndic.com' # error!?
RuntimeError: redirection forbidden: http://ndic.com -> https://ndic.com/
from /usr/local/rvm/rubies/ruby-2.0.0-p576/lib/ruby/2.0.0/open-uri.rb:223:in `open_loop'
from /usr/local/rvm/rubies/ruby-2.0.0-p576/lib/ruby/2.0.0/open-uri.rb:149:in `open_uri'
from /usr/local/rvm/rubies/ruby-2.0.0-p576/lib/ruby/2.0.0/open-uri.rb:689:in `open'
from /usr/local/rvm/rubies/ruby-2.0.0-p576/lib/ruby/2.0.0/open-uri.rb:34:in `open'
from (irb):2
from /usr/local/rvm/gems/ruby-2.0.0-p576/gems/railties-4.0.3/lib/rails/commands/console.rb:90:in `start'
from /usr/local/rvm/gems/ruby-2.0.0-p576/gems/railties-4.0.3/lib/rails/commands/console.rb:9:in `start'
from /usr/local/rvm/gems/ruby-2.0.0-p576/gems/railties-4.0.3/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
一位评论者询问问题是否可能是第二个环境(最新的CentOS)缺少发出HTTPS请求的软件包。我对OpenURI库的理解是,这无关紧要;如果http://请求将重定向到https://,则初始#open
调用应该只返回一个解释重定向的对象(类似于HTTP响应)。我已尝试直接加载类似https://ndic.com的HTTPS网址,而在两个情况下,这都会导致OpenSSL::SSL::SSLError
错误。所以我仍然坚持为什么http://(可重定向)请求只在一个环境中出错。