RFC: 続・Hatena ID Auto-Discovery の仕様

Hatena ID Auto-Discovery の仕様について。長文です。

先日そのページが誰のものなのかを示す識別子を埋め込む仕様を考えているという話を書いた後、さまざまなフィードバックをもらうことができたので、後日Hatena ID Auto-Discovery の仕様というのを書きました。それから新たに幾つかフィードバックをいただきまして、それらを整理しながら方向を修正中です。

しかし、みなさんほんといろいろアドバイスありがとうございます。つくづく自分がウェブの仕様について不勉強だなあと痛感しつつ、ウェブの標準って色々あるんだなあとしきりに感心したり、一人で色々調べてるだけじゃなかなか正解には行き着かないなあというのが正直思ってみたりです。

もとい、

まずそもそも僕が考えた仕様は...という前にまず何をしたいかを明確にしないとですね。僕がしたいのは、はてなダイアリーを含めたインターネット上のウェブページ (Permalink) から、そのページを作った人の「はてなのID」を探し出したい、ということです。

なぜそれをしたいかというと、はてなポイントでページ作者に投げ銭ができるようなシステムを考えているから、なのですが、

僕は「投げ銭」に特化しないほうがいいなあ、と思ってます。例えばツールバーに「この人のはてダに移動」とか「このひとのはてブお気にを一覧」とかいうボタン作るのに役立ちそうだな、と思うもので。

と吉松さん(id:fumiakiy)がコメントに残しているように、PermalinkはてなIDが埋め込まれていると、投げ銭以外の目的にも使えると僕も思っているので rel="payment" や foaf:tipjar のような投げ銭に特化した仕様よりはもう少し広い仕様がいいなと思っています。

また、はてな独自の仕様を採用するよりはウェブの仕組みで今回の目的に使えそうなものがあったらばそちらに従った方が良いだろう、ということで g:webweaver:id:kotastyle さんからいただいたお話を元にDublin Core を採用してみることにしました。それが先日書いた

<link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" />
<link rel="DC.creator" title="id:naoya"
  href="http://www.hatena.ne.jp/user?userid=naoya" />

というものに相当します。

この仕様に関して yohei さんからyohei-y:weblog: Hatena ID Auto-Discovery についていただいたフィードバックによると

  • title 属性は便宜上の助言的情報であり、コンテンツ作者に委ねた方がいいから削除したほうが良い
  • ID としての URI に query string が入っているのは Cool URI じゃない (密結合的)

ということだそうなので、

<link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" />
<link rel="DC.creator" href="http://www.hatena.ne.jp/user/naoya" />

がいいのではないかと修正案を考えました。このとき href 属性で指定している URI はウェブブラウザでアクセスできるネットワーク上のリソースのURIである必要があると思っていて、これまでのはてなのサービス同様 http://www.hatena.ne.jp/naoya/ で何がしかの情報にアクセスできるようにしてそちらを使うのはどうだろう、などと考えていたところ神崎さんから

(1) Dublin Corecreatorは作者 (An entity primarily responsible for making the content of the resource)を示すものである;(2) link要素は、ウェブ文書がhref属性値URIが示すリソースに対して、rel属性値が示すタイプ(関係)のリンクを持つことを表す;この2つの帰結として、link rel="dc.creator"と書いたら、hrefの値は「作者を表すURI」となる。これはRDFとして解釈するかどうかを問わず、Dublin Coreと(X)HTMLのセマンティクスが定めていることだ。

ここで出てくるのが、「作者のホームページ」や「ユーザ情報ページ」のURIを人物を表すURIとして代用したっていいのでは、という考え方だろう。しかしこれは、Architecture of the World Wide Web, Volume OneがURIの衝突 (URI collision) と呼んでいる問題に陥る。

URI の衝突に関するお話が出てきて、解決策としては以下の 3 つのいずれかがいいのではないか、ということでした。

  • href で指定した URI からはステータスコード 2xx は返さずに、303 で作者情報などのページにリダイレクトする
  • dc:creator ではなく「作者のホームページ」を表す独自のプロパティを使う
  • href の値を http: リソースではなくIDとしてのURI、例えば urn:pin: などにする

ところで、吉松さんの日記から再び引用するのですが、

元々id:naoyaさんがRFCしたのは、ある人間をWebページのメタデータから識別する方法ではないだろう。そうではなくて、あるWebページを書いたのは、はてなではどういう風に識別できるエンティティなのか?ということに過ぎない。人間というエンティティそのものを識別しようとするわけではなく、人間エンティティが持つ一つのビューを識別したいということだろう。だから、人間に与えられたURIにWebでアクセスできるのは変だとかいうことは、少なくともid:naoyaさんの当面の目標とはズレた議論だ。

とあります通り、僕がしたいのはどちらかというと人物のURIを定めたいというよりも、IDを埋め込みたい、というところです。つまり、人間のURIを表現できるようにしたいということでも、ホームページのアドレスを指定したいということでもありません。(となると神崎さんが示してくださっている 3 つの解決方法のうちベストなのは3番目のものなのでしょうか。)

また、今回の目標として

  • なるべく配布しやすい(テンプレートなどに記述するのに手間がかからない)形での仕様にしたい
  • User-Agent が簡単に解決できる仕様にしたい

という pragmatic な2点があります。

具体的には、前者は例えば一度はてなの管理画面などで埋め込みのための ID を、はてなアカウントとは別に取得してもらったりはしなくていいように、ということで、後者は User-Agent が目的とするウェブページの GET 1 リクエストで取得したい、ということです。(はてなIDを取得するために Auto-Discovery により別のメタデータを参照したり、何かしらの名前解決のような手段を用いることをしたくない、ということ。)

URI について不勉強なので、ちょっとよくわかってませんが urn:pin: というのははてなIDへの解決手段が別に必要になるという点で、僕が目標にしているところと合わないので難しいのかなと思います。上記の二点を満たすような ID という意味の別 URI があるのかが気になっています。時間軸を使うURIスキーム、tag:がRFCに にある tag: が使えるのでしょうか。でも今回の目的には時間軸は必要ないしなあ。

ということで、現状は

<link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" />
<link rel="DC.creator" href="http://www.hatena.ne.jp/user/naoya" />

という仕様で、www.hatena.ne.jp の /user/naoya は /user?userid=naoya あるいは他のページに 303 リダイレクト、というのが落としどころなのかなと思っていて、よりベターな解法としての最適な URI があるのならそちらを使う、といったところでしょうか。

なお、最終的にプログラムで何をするか、というと URI で指定されている文字列からはてなIDを取得する、ということだけだったりします。つまり、HTML::HatenaIDAutoDiscovery というモジュールを作って(一個前の仕様で動くものはもう作ってみた)、

my @names = HTML::HatenaIDAutoDiscovery->find(
    'http://naoya.dyndns.org/~naoya/mt/archives/001694.html'
);
print $names[0]; # naoya

ということがしたいのでした。

ということで、引き続き Request for Comments です。

# しかしこういう議論は英語でするべきなんだろうが、自分の英語力のなさにちょっと悲観。