3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

mrubyでURIを構文解析するライブラリを作りました

Last updated at Posted at 2025-12-02

mruby向けのURI構文解析ライブラリ、mruby-uriparserを開発しました。
RFC 3986準拠のCライブラリであるuriparserのバインディングとして実装し、高速・軽量かつ堅牢なURI処理をmruby環境で利用可能にしています。

既存ライブラリの調査

RubyでのURIの構文解析には先駆者がたくさんいます。

まずはmrubyから見ていきます。
mrubyのホームページのmruby Librariesを見ると、Asmod4n/mruby-uri-parserが挙がっています。
こちらのライブラリはZewoGraveyard/uri_parserをCライブラリとして採用しています。
このCライブラリはNode.jsのhttp-parserライブラリのソースから抜粋してモジュール化したものです。
ただし、その元のライブラリのリポジトリnodejs/http-parserは現在アーカイブされており、新しいプロジェクトではllhttpを検討するように推奨しています。

他にもmrubyにはzzak/mruby-uriがあり、純粋にRubyで実装されています。

次にCRubyですが、当然標準のuri gemGitHubリポジトリ日本語のAPI文書)があります。

また、uriparserライブラリを使うtlewin/ruby-uriparserも存在します。
説明を読むと標準のURIライブラリに比べておおよそ7.5倍速いと謳われているように、速度と低メモリ消費を重視しています。

深追いはしませんが、CRubyには他にも多数のライブラリが存在します(参照:「uri parser」での検索結果)。

uriparserの選択理由

uriparserはC言語で書かれたRFC 3986準拠のURIの構文解析ライブラリです。
クロスプラットフォームで高速・軽量、依存関係もないため、組み込み用途で実績のあるmrubyとの相性が良いと考えました。

多くのプロジェクトで採用実績があり、直近ではPHP 8.5のURI拡張モジュールに採用されています。
採用に至った経緯はPHP Foundationのブログ記事で紹介されており、この過程でuriparser側にも複数の新機能が追加されました。

CRubyでも既にこのライブラリを使ったgemが存在し、他の言語でも公式ページに掲載されている通り、様々なバインディングが開発されています。

機能紹介

ここまでの調査で、mruby用のuriparserバインディングはまだ存在しないことが確認できました。
活発に開発されているこのライブラリを活用することで、CRubyなど他言語の実装と同等の品質を実現できると考え、mruby-uriparserを開発しました。

mruby-uriparserには以下の機能が含まれます:

  • URI文字列の構文解析(スキーム、ホスト、パスなどの構成要素を取得)
  • 例外処理によるエラーハンドリング
  • 正規化(不要な ... の除去など)等の変更操作

使用例は以下です。

str = "http://example.com:8000/some-path?some-query"
uri = URIParser.parse(str)
uri.scheme   #=> "http"
uri.host     #=> "example.com"
uri.port     #=> "8000"
uri.query    #=> "some-query"

関連リンクは以下の通り:

開発で学んだこと

C言語の学習

mruby拡張の開発にはC言語の知識が不可欠でしたが、当初は充分な理解がありませんでした。
プログラミング言語C 第2版Build Your Own Lispを通じて、必要な知識を習得しました。

uriparser APIの理解

uriparserは同一機能に対して複数のバリエーションを提供しています。
例えば、API文書にはuriAddBaseUriAuriAddBaseUriExAuriAddBaseUriExMmAといった関数が並んでいます。
公式文書によれば、通常の用途ではA接尾辞の関数で充分です。
また、mrubyのC APIはchar *を使用するため、W接尾辞(ワイド文字用)のバリアントは不要です。

既存実装との互換性確保

CRubyの標準URIライブラリとの互換性を重視し、API文書に機能比較表を掲載しました。
一部の非推奨機能は実装を見送りましたが、実用上必要な機能は網羅しています。

不足機能の補完

例として、uriparserはパス構成要素を連結リストとして提供しますが、パス全体を文字列として取得する機能がありません。
この問題に対しては、UriRecompose.cToStringEngine実装を参考に、mrblib/mrb_uriparser.rbpathメソッドを実装しました。

ドキュメント生成

RDocやYARDはCRuby向けに設計されており、mrubyでの利用にはカスタマイズが必要でした1
本プロジェクトの実装の大部分がC言語であることを考慮し、Doxygenを採用しました。

RubyのAPIについてもDoxygenで記述していますが、相互参照機能により実用上の問題はありません。

ビルド設定の最適化

外部ライブラリとの依存関係管理において、当初はbuild_config.rbでバージョン検出を行う動的な方式を検討しました。
しかし、この方法ではユーザー側で追加設定が必要となり、環境差異による問題も発生しやすくなります。

そこで、uriparserのバージョンを0.9.9以上に固定する方針に変更しました(関連コミット)。
この決定により、ユーザーは必要な環境を明確に把握でき、開発側も安定した動作保証が可能になりました。

mgem-listへの登録

mruby-uriparserを公式のmgem-listに登録しました。
これにより、ユーザーは以下のように依存関係を簡単に追加できます:

conf.gem mgem: 'mruby-uriparser'

登録には、リポジトリ情報を含むYAMLファイルをmgem-listに追加するプルリクエストを送信します。
プルリクエストを作成する際はCONTRIBUTING.mdも参照してください。

バージョン0.9.9への対応

開発当初はuriparser 0.9.8を使用していましたが、0.9.9で追加された以下の機能2が重要と判断し、対応を行いました:

  • URIオブジェクトの複製機能
  • 個別コンポーネントのセッター関数

また、開発環境で使用しているGNU Guixでも最新バージョンを利用できるよう、パッケージ定義の更新に貢献しました。

まとめ

uriparserライブラリにmrubyのバインディングを作りました。
既存のCライブラリを活用して、有用そうなライブラリができてよかったです!

今後は手入れもしつつ、これを使って何か面白いことができればいいなと思っています。

Copyright (c)  2025 gemmaro.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
The license is located at <https://www.gnu.org/licenses/fdl-1.3.html>.
  1. YARDはmrubyのAPI文書で使われています。

  2. これらの機能は前述したPHP 8.5のURI拡張開発で追加されたものです。

3
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?