2020年2月1日土曜日

URI.encode が obsolete だそうなので WEBrick::HTTPUtils.escape に書き換えた

日本語を含むURI文字列をエンコードするために URI.encode を使っていたのですが、Rubocopさんに URI.encode は obsolete だと怒られたので書き換えたい。

W: Lint/UriEscapeUnescape: URI.escape method is obsolete and should not be used. Instead, use CGI.escape, URI.encode_www_form or URI.encode_www_form_component depending on your specific use case.
      encoded_uri = URI.escape(str)
                    ^^^^^^^^^^^^^^^

解決策

これでうまくいった!

irb(main):023:0> require 'webrick/httputils'
=> true
irb(main):024:0> WEBrick::HTTPUtils.escape(str)
=> "http://sample.com/My_Directory/2020/01/20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg"

【参考】 URI.encode (Ruby 2.5.0 リファレンスマニュアル)

Railsのコードに書くときはこんな感じに書きました。

require "net/http"
require "uri"
require "webrick/httputils" # これを追加

module SomeModule
  extend ActiveSupport::Concern
  ...

  def some_method(original_path)
    # 書き換え前
    # encoded_path = URI.escape(original_path)

    # 書き換え後
    encoded_path = WEBrick::HTTPUtils.escape(original_path)
    ...

  end
end

試行錯誤したメモ

元のURIがこのような形で、

str = http://sample.com/My_Directory/2020/01/20200131_日本語の文字列.jpeg

これと同じ結果を得たい。

URI.encode(str)
=> "http://sample.com/My_Directory/2020/01/20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg"

しかし、Rubocopさんがおすすめしてくれている下記メソッドでは、 :/ までエンコードされてしまう。

  • CGI.escape
  • URI.encode_www_form
  • URI.encode_www_form_component

URI.encode (Ruby 2.5.0 リファレンスマニュアル) に載っている下記2つも同じ結果。

  • ERB::Util.url_encode
  • WEBrick::HTTPUtils.escape_form
# : や / までエンコードされてしまう
CGI.escape(str)
=> "http%3A%2F%2Fsample.com%2FMy_Directory%2F2020%2F01%2F20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg"

私はエンコードした文字列を URI.parseに渡して使いたかったのですが、 :/ までエンコードされると正しく解釈されなくて困っていたのでした。

# 正しくURI.parseできている時
irb(main):016:0> uri = URI.parse("http://sample.com/My_Directory/2020/01/20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg")
=> #<URI::HTTP http://sample.com/My_Directory/2020/01/20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg>
irb(main):017:0> uri.scheme
=> "http"
irb(main):018:0> uri.host
=> "sample.com"
irb(main):019:0> uri.port
=> 80
irb(main):020:0> uri.path
=> "/My_Directory/2020/01/20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg"
# URI.parseできない
irb(main):011:0> uri = URI.parse("http%3A%2F%2Fsample.com%2FMy_Directory%2F2020%2F01%2F20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97
%E5%88%97.jpeg")
=> #<URI::Generic http%3A%2F%2Fsample.com%2FMy_Directory%2F2020%2F01%2F20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg>
irb(main):012:0> uri.scheme
=> nil
irb(main):013:0> uri.host
=> nil
irb(main):014:0> uri.port
=> nil
irb(main):015:0> uri.path
=> "http%3A%2F%2Fsample.com%2FMy_Directory%2F2020%2F01%2F20200131_%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97.jpeg"

バージョン

Ruby 2.5.3
Rails 5.2.4.1

0 件のコメント:

コメントを投稿