MAGAZINE

ルーターマガジン

Ruby

RubyでのURLエンコード方法とURI.encodeの代替手段

2025.01.17
Pocket

弊社では開発言語として主にRubyを使用し、クローリングやスクレイピングを業務として行っています。その過程で、プログラム内でURLを扱うことが多々あります。特にURLエンコードは正確なデータ取得や通信の安全性を保つために重要な処理の一つです。

RubyでURLをエンコードする方法を検索するとURI.encodeを利用する例が多く見られますが、現在は非推奨またはバージョンによっては機能そのものが削除されています。

今回は、URI.encode の基本的な使い方と他の代替手段を紹介します。


基本的なURI.encodeの使い方

URI.encode は、ストリングをURLエンコードするために使われていました。以下が使用例になります。

require 'uri'

original_url = "https://example.com/search?q=テスト&lang=ja"
encoded_url = URI.encode(original_url)

puts encoded_url
# 結果: https://example.com/search?q=%E3%83%86%E3%82%B9%E3%83%88&lang=ja

URI.encode は標準仕様に基づき、URLの一部をエンコードします。

URLをエンコードする理由

URLエンコードは、URL内に含まれる特殊文字や非ASCII文字を正確に伝えるために重要です。たとえば、空白や&?のような記号がそのまま含まれると、サーバーが正しく解釈できない可能性があります。URLエンコードを行うことで、これらの文字を安全に送信できる形に変換します。

例:

  • https://example.com/search?q=hello worldhttps://example.com/search?q=hello%20world
  • https://example.com/product?name=カメラ(デジタル)https://example.com/product?name=%E3%82%AB%E3%83%A1%E3%83%A9%28%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%29(日本語、括弧(, )のエンコード)

このように、エンコードは通信の安全性と正確性を保つために必要です。

なぜURI.encodeは非推奨なのか

URI.encode は、しばしばエンコードすべきでない文字もエンコードしてしまったり、一部の情報が欠落してしまうことがあります。たとえば下記のような場合があります。

require 'uri'

original_url_with_semicolon = "https://example.com/search?q=item1;item2"
encoded_url_with_semicolon = URI.encode(original_url_with_semicolon)

puts encoded_url_with_semicolon
# 結果: https://example.com/search?q=item1%3Bitem2
# ';' はエンコードされ、セミコロンが区切り文字として解釈されなくなる

original_url_with_fragment = "https://example.com/search?q=test#section"
encoded_url_with_fragment = URI.encode(original_url_with_fragment)

puts encoded_url_with_fragment
# 結果: https://example.com/search?q=test%23section
# '#' はフラグメントのはずだが、エンコードされてしまう

このような想定外のエンコードが問題を生じるため、URI.encode は非推奨とされるようになりました。なお、URI.encode はRuby 1.9以降非推奨となり、Ruby 3.0で削除されました。

以下では URI.encode の代替手段をいくつか紹介します。

URI::DEFAULT_PARSER.escape

require 'uri'

original_url = "https://example.com/search?q=テスト&lang=ja"
escaped_url = URI::DEFAULT_PARSER.escape(original_url)

puts escaped_url
# 結果: https://example.com/search?q=%E3%83%86%E3%82%B9%E3%83%88&lang=ja

メリット:

  • Ruby標準ライブラリに含まれており、追加のインストールが不要。
  • URI.encode に近いシンプルな操作感。

デメリット:

  • URL全体のエンコードに適しているが、クエリパラメータ専用ではない。

Addressable::URI

require 'addressable/uri'

original_url = "https://example.com/search?q=テスト&lang=ja"
escaped_url = Addressable::URI.encode(original_url)

puts escaped_url
# 結果: https://example.com/search?q=%E3%83%86%E3%82%B9%E3%83%88&lang=ja

メリット:

  • 高度なカスタマイズが可能。
  • 非標準的な要件にも対応できる柔軟性。

デメリット:

  • 外部ライブラリのため、追加のインストールが必要で標準ライブラリに比べて依存が増える。

CGI.escape

require 'cgi'

query = "q=テスト&lang=ja"
escaped_query = CGI.escape(query)

puts escaped_query
# 結果: q%3D%E3%83%86%E3%82%B9%E3%83%88%26lang%3Dja

メリット:

  • クエリ文字列のエンコードに最適。
  • Ruby標準ライブラリに含まれており、インストールが不要。

デメリット:

  • URL全体のエンコードには不向き。
  • クエリパラメータ以外の部分で使用する際に制約が多い。

URI.encode_www_form

require 'uri'

params = { "q" => "テスト", "lang" => "ja" }
encoded_query = URI.encode_www_form(params)

puts encoded_query
# 結果: q=%E3%83%86%E3%82%B9%E3%83%88&lang=ja

メリット:

  • クエリパラメータの生成とエンコードを簡素化。
  • ハッシュや配列を直接エンコードできる。

デメリット:

  • URL全体ではなく、クエリパラメータ専用。
  • クエリ文字列以外で使用する際に制限がある。

まとめ

  1. URI.encode は非推奨であり、Ruby 1.9以降非推奨、Ruby 3.0で削除された。
  2. 代替の方法として、URI::DEFAULT_PARSER.escapeaddressableCGI.escapeURI.encode_www_form を使用する。
  3. URLのエンコードは用途に基づいた正確な方法を選ぶことが重要。

RubyでURLを扱う際にはぜひ気にしてみてください。

Pocket

CONTACT

お問い合わせ・ご依頼はこちらから