LoginSignup
1
0

URIをいい感じに扱うのが意外と難しい話

Posted at

For Agileware Drinkup at RubyKaigi 2023 Lightning Talk

自己紹介

渋谷 充宏 @m4buya

  • 株式会社ファンファーレ Engineering Manager
  • Ruby / SRE / マネジメント
  • https://github.com/mshibuya
  • RailsAdmin/CarrierWave committer
  • 自作キーボード沼に入門しました

この発表について

CarrierWaveというファイルアップロードライブラリには、エンドユーザーからファイルのURLを受け取ってそれをダウンロードし格納する仕組みがあります。そこでURI/URLを扱うのが意外と難しいなぁ…という話をします

image.png


URI

皆様よくご存じ、Uniform Resource Identifier。
Rubyでは標準ライブラリとして URI が存在していて、いろんなURIを便利に扱える。
が、わりと仕様に厳密に即した入力を要求する。


Ruby URIライブラリが扱えないURIの例

これらのURIはRFC違反なので使えません、と言い切ってしまう手もあるが…

irb(main):001:0> URI.parse('https://example.com/file[1].txt')
/Users/mshibuya/.anyenv/envs/rbenv/versions/3.2.1/lib/ruby/3.2.0/uri/rfc3986_parser.rb:66:in `split': bad URI(is not URI?): "https://example.com/file[1].txt" (URI::InvalidURIError)
	from /Users/mshibuya/.anyenv/envs/rbenv/versions/3.2.1/lib/ruby/3.2.0/uri/rfc3986_parser.rb:71:in `parse'

エンドユーザーはURIに対しふわっとした期待を持っている!

???「ブラウザのアドレスバーに入れたらちゃんと出るものがダウンロードできないのはバグでしょ」

特にIDNAが厄介で、この表記がなされたもの自体はURIそのものではなく「規定のエンコードがなされたURIをアプリケーションがよしなに表示できる」という扱い…


そこで Addressable

RubyのIDNA対応URIライブラリとしてポピュラー。
入力にもかなり寛容なので、ユーザーの期待に近い


IDNAを扱うには

#normalize します

irb(main):001:0> Addressable::URI.parse('https://ドメイン名例.jp/').normalize
=> #<Addressable::URI:0x382c URI:https://xn--eckwd4c7cu47r2wf.jp/>

落とし穴

URI全体をnormalizeしてしまうと、pathなども別物になってしまう!

irb(main):001:0> Addressable::URI.parse('https://example.com/o%CC%88.png').normalize
=> #<Addressable::URI:0x7170 URI:https://example.com/%C3%B6.png>

実装された運用

uri = Addressable::URI.parse(source)
uri.host = uri.normalized_host
uri.to_s

とりあえずこんな感じにお茶を濁してます…問題が出ないといいな


まとめ

  • URI、おなじみなんですが考えることが多くて意外と難しい
  • おすすめの方法があったら教えてください
  • 人間はいい加減なのでできるだけURIを書かせてはいけない(戒め)
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0