Bitbucket

自分用の技術メモ

open-uri and redirection (open-uriのリダイレクト処理)

Rubyのopen-uriで基本認証付のURIをオープンする場合、ユーザ、パスワードが間違っていない場合でも “401 Unauthorized” の例外 (OpenURI::HTTPError) が発生することがある。このような事象が発生しているとき、アクセス先がリダイレクト (3xx) のステータスを返している可能性がある。

open-uri ではリダイレクトが行われた場合には、無条件で基本認証に関する削除しているため、リダイレクト先が同一ホスト・realmであった場合でも認証情報が渡されないためこのような事象が発生する。

open-uri.rb より抜粋
1
2
3
4
5
6
7
if redirect
  ...
  if options.include? :http_basic_authentication
    # send authentication only for the URI directly specified.
    options = options.dup
    options.delete :http_basic_authentication
  end

オプションとして :redirect => true が指定され、同一サーバ・realmであった場合にはリダイレクト先に認証情報を引き継ぐのが正しいと思うが、そもそも realm を見ていないようだ。

リダイレクトされる可能性のあるURIに認証情報を渡す場合 :redirect => false として、OpenURI::HTTPRedirect の例外を捕捉して自前でリダイレクトを処理する必要がある。

1
2
3
4
5
6
7
8
9
10
begin
  fh = open(
    uri,
    {:http_basic_authentication => [user, password],
     :redirect => false}
  )
rescue OpenURI::HTTPRedirect => redirect
  uri = redirect.uri
  retry
end

※実際にはリダイレクト先のURIとrealmを検証するべき。

Comments