GlobalID の URI パーサーを RFC3986 に切り替えてアンダースコアを許容
GlobalID が内部で使用していたハードコードの RFC2396_Parser を Ruby 標準の RFC3986_Parser に置き換えることで、ホスト名にアンダースコアを含む URI が有効になります。これにより、過去に配布された QR コード等に埋め込まれた ID が破壊的に失敗する問題が解消されます。
背景
GlobalID 1.3.0 からは URI::RFC2396_Parser が固定化され、gid://my_app/User/1 のようなアンダースコアを含むホストは URI::InvalidComponentError を投げていました。#201 で報告された回帰は、Ruby 本体が 2024 年 11 月にデフォルトパーサーを RFC3986_Parser に変更したことと、GlobalID が追随しなかったことが原因です。
この不一致は、QR コードに埋め込まれた ID が物理的に置き換えられない環境で致命的な障害となります。そこで、GlobalID 側でも標準パーサーに合わせる修正が求められました。
技術的な変更
URI パーサー定数の差し替え\nlib/global_id/uri/gid.rb の URI_PARSER 定数を RFC2396_Parser から RFC3986_Parser に変更しました。
- URI_PARSER = URI::RFC2396_Parser.new # :nodoc:
+ URI_PARSER = URI::RFC3986_Parser.new # :nodoc:
この変更により、以降の解析は RFC3986 に準拠したロジックが適用されます。
バリデーションコメントとエラーメッセージの更新\nvalidate_app のコメントは、許容文字を「ハイフンとダッシュ」に変更し、アンダースコア例を追記しました。また、エラーメッセージはアンダースコアも許容対象である旨に更新しました。
- # Validates +app+'s as URI hostnames containing only alphanumeric characters
- # and hyphens. An ArgumentError is raised if +app+ is invalid.
+ # Validates +app+'s as URI hostnames containing only alphanumeric characters,
+ # hyphens and dashes. An ArgumentError is raised if +app+ is invalid.
+ # URI::GID.validate_app('foo_bar') # => 'foo_bar'
@@
- 'App names must be valid URI hostnames: alphanumeric and hyphen characters only.'
+ 'App names must be valid URI hostnames: alphanumeric, hyphen and underscore characters only.'
parse メソッドのコメント修正\nparse が使用する URI_PARSER が RFC3986 であることをコメントに明示しました。
- generic_components = URI.split(uri) << URI_PARSER << true # RFC2396 parser, true arg_check
+ generic_components = URI.split(uri) << URI_PARSER << true # RFC3986 parser, true arg_check
テストの調整\ntest/cases/uri_gid_test.rb ではアンダースコアを含むホスト名の期待結果を追加し、CompositePrimaryKeyModel の ID 表記もアンダースコア対応に修正しました。また、test/cases/global_id_test.rb では GlobalID.app = 'blog_app' が許容されることを確認し、GlobalID.app = 'blog:app' が引き続きエラーになることを検証しています。test/cases/global_locator_test.rb からは「ロケータ名にアンダースコアは不可」というテストが削除され、ロケータ名のアンダースコア許容が暗黙的に保証されました。
設計判断
本変更は 最小限の差分で標準パーサーに合わせる という方針に従い、定数置換とコメント・メッセージの微修正だけで実装されています。新たな設定項目を導入せず、Ruby 本体が提供する URI.parser の切り替え機構に委譲することで、将来的なパーサー変更にもコード修正を回避できる拡張性が確保されています。
まとめ
GlobalID が使用する URI パーサーを RFC3986_Parser に切り替えることで、ホスト名にアンダースコアを含む URI が正式にサポートされ、過去に配布された QR コード等の ID がそのまま利用可能になりました。変更は定数差し替えと軽微なバリデーションの更新のみで済んでおり、既存ユーザーへの影響は最小限です。Ruby 標準のパーサーとの整合性を取ることで、今後のメンテナンス性も向上します。