Ruby で書いたスクリプトが redirection forbidden という RuntimeError 例外を吐いてコケた。
/usr/lib/ruby/1.8/open-uri.rb:174:in `open_loop': redirection forbidden: http://twitpic.com/show/full/e38i7l -> https://d3j5vwomefv46c.cloudfront.net/photos/large/851962161.jpg?1399536621 (RuntimeError)
from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri'
from /usr/lib/ruby/1.8/open-uri.rb:518:in `open'
from /usr/lib/ruby/1.8/open-uri.rb:30:in `open'
どうやら、http から https へのリダイレクトが禁止されているらしい。
たとえば、仮にopen-uriがPUTをサポートしたとしたら、無条件に
untaintしてredirectするのはまずいですよね。
# RFC2616でもredirectはGET/HEADのみということになってますが。
open-uriの場合は、
unless OpenURI.redirectable?(uri, redirect)
raise "redirection forbidden: #{uri} -> #{redirect}"
end
でredirectが妥当かどうかをチェックしているので、何らかの危険性
があると判断されるようなredirectはここで蹴って、その後でuntaint
するのがよいのではないでしょうか。
[ruby-dev:26485] Re: $SAFE=1 の open-uri で redirect 時にエラー
OpenURI.redirectable? のソースコードはこのへん http://svn.ruby-lang.org/repos/ruby/tags/v1_8_7_358/lib/open-uri.rb にあるので該当箇所を見てみると、
def OpenURI.redirectable?(uri1, uri2) # :nodoc:
# This test is intended to forbid a redirection from http://... to
# file:///etc/passwd.
# However this is ad hoc. It should be extensible/configurable.
uri1.scheme.downcase == uri2.scheme.downcase ||
(/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
end
正規表現さっぱりわからん(;・∀・)
とりあえず、エラーになってしまうスクリプトは http -> https を https -> https に修正して対処できた。ふぅ。
もうちょっと探してみると、http から https へのリダイレクトをエラーにしないようにしてくれるライブラリがあった。
This gem applies a patch to OpenURI to optionally allow redirections from HTTP to HTTPS, or from HTTPS to HTTP.
jaimeiniesta/open_uri_redirections · GitHub
やっぱり、他にも困っている人がいたということで。
tags: ruby
Posted by NI-Lab. (@nilab)