春告げ抹茶ホイップ

Webmention を実装した

Webmention というものがある。

IndieWeb のコミュニティから出てきた仕組みで、例えばこれを使うと、あるサイト A の記事から別のサイト B の記事ににリンクを貼っていたとき、サイト B のその記事にサイト A のその該当記事のリンクを表示したりということができる。 トラックバックとかの後継版ということになっている。

実際にはそれだけでなく、他のサイトに「いいね」を送るとか「コメントをする」とかも同じ仕組みでできる。 そして受け取り側であるサイト B がその情報をどう処理するかもある程度自由である。 コメントを受け取ったときにそのコメントを自分のサイトに表示してもよいし、サイトには一切表示せず個人の slack に通知を流すだけということもありえるようだ。 HTTP の POST リクエストを投げる特定の方法であり、それを使ってどのような表現をするかはある程度の自由がありそう。

この Webmention があまり流行っていないのは、サイト A とサイト B の両方がこの Webmention というマイナーな規格に対応しないとそもそもリンクを受け取ったりなんだりが何もできないということがある。 自分が実装するだけでは済まず、相手も実装しないと何も起きないし、別にメジャーな仕組みでもないだろうし、大規模に使われているわけではないので流行らない、流行らないから使われない、という感じなのかなあと思っている。


過去に Fediverse とか渡り歩いていたときにこの Webmention に言及している人を見かけたことがあって、それで私は Webmention の存在は知っていた。

しかし、全然流行っていない規格だし、そもそも私自身は他のサイトで私のサイトがどう言及されているかをトラックバックとして自分のサイトに表示してやりたい、という欲求があまりなかったし、コメントやいいねも別に表示したいと思っていなかったので特に採用していなかった。

自分のサイトに載せるコンテンツは自分が管理できるものが良いし、このサイトの記事にコメント欄がないのは static サイトだから技術的に作れないという消極的な理由ではなく、積極的にコメント欄は必要ないと考えて設置していない。 自分が自由に書くためのサイトにコメント欄をつけて反応されたり交流したりするのは、自分の個人的メモとしての性質を持つこのサイトにはあまり望ましくないなあと。 他人と交流するために作っているサイトならコメント欄を作ることには非常に意味があるだろうが、このサイト自体は自分の考えをオープンな場所に置いておくというためだけの場でしかない。 そんなわけでコメント欄みたいなのは設置したいとは思っていなかった。

別に反応があることは良いと思うし、SNS で言及されるとかは良いだろうと思う。 なんだったらこのサイトはどこのサイトからアクセスされているかとかも個人情報を取得しない範囲で umami を利用して見られるようにしているくらいでもある。 そういう意味でも反応を何 1 つ見たくないわけではないと思う。 しかし、その反応を自分のサイトのコンテンツとして置きたくないという感覚があるのだと思う。

例えばはてなブックマークとかのコメント欄とかは結構地獄の様相を呈するときもあり、あまりそういう反応とかも見たりしたくないなあと思うけど、はてなブックマークは完全に自分のサイトとは別でどこかの誰かが勝手に言及しているだけだから無視できるというのがある。 自分のサイト内にそのコメントの内容を表示したりはしたくないなあとは思う。 そういう違いだと思う。

まあそんな感じで、他人にどう言及されているかを表示したいという欲求がなかったので特に実装することも考えずに放置していた。


しかし、ここのところ私が個人的に見るようになった個人 Web サイト的なサイトの中で Webmention を実装されるものが増えてきているように感じている。 実際に例を挙げると、以下のような記事を見た。

(記事内で言及したため、これらのサイトにこの記事からの Webmention が飛んでいるはず。)

そしてこちらの記事[1]によると、現在はこぶりーという個人サイトを束ねているようなサイトに記録されているサイトで Webmention に対応しているサイトは 22 件らしい。 世の中に大量にある Web サイトの中で 22 件のサイトが対応しているって、まあ普及しているというにはだいぶ遠いかもしれないが、一部の個人 Web サイトを作っている人たちが相次いで自分のサイトに Webmention を実装していたりするので、非常に小さな流行のようなものはできている気がする。

こういう流行は個人サイトを盛り上げる上で良いことかもしれない。

私は最近色んな人の個人的なサイトやブログを読んでいて、こういうサイトたちが盛り上がると良いなあと考えており、個人サイトの盛り上がりに何か参与してやりたい気持ちは持っていた。 そして Webmention は双方が実装しないと意味をなさない手法である。 この小さい流行を盛り上げていくには、Webmention を実装する人が増えたほうが良いのだろうと思う。


当初は Webmention は送信するだけの予定だった。

私のサイトの記事で言及した URL に Webmention を飛ばすことで、言及された側の記事の人が私のサイトで言及されたことを知ることができる。 およそ Webmention を実装する人は自分の記事が言及されている言及元が知れるという面白さから Webmention を実装しているのだろうから、そういう風に私のサイトで言及したときに言及したという通知を投げて欲しがっているのだろうかなと思い。

一方で、上に書いたように私自身は他の人からのトラックバックとかを自分のサイトに表示するのは微妙だなあと思っていた。 そのため当初は送信だけして、自分のサイトには何も表示しなくてよいかなと考えていた。

しかし、もう少し考えてみると、送信だけして他の人から受け取らないというのは非対称であり公平ではない気がした。 つまり私のサイトで他の人の Webmention に対応したサイトに言及すれば、その他の人のサイトに私の記事の URL が多くの場合表示されることになる。 一方で、他の人が私のサイトの記事に言及しても何も表示されないとなるとどうだろう。 私のサイトの URL 自体は他の人のサイトにどんどん配置していくのに、他の人のサイトの URL は自分のサイトには一切配置しないというのは、自分だけ自分のサイトを広めるために枠組みにフリーライドしているような公平ではないような、そういう感じを覚えてしまった。

まあ、そこまで深刻に考える必要はないと思うし、世の中の Webmention を自サイトに実装しようと考えている人は、別に人から通知を受け取ってもその URL を表示する義務はないので、通知を受け取ったことを自分の個人用 slack に流すだけでも全く問題ないと思う。

が、私は一応他の人の URL も表示してやる方が公平感があって良いなあと考えることにしたので、他の人のサイトの URL も表示することにした。

また、一読者として考えたときにも、ある記事をその記事だけ見るのではなく、その記事を言及している記事とかを辿れた方が面白いというのもある。 そういう読者として、Webmention を受け取った履歴的なのが見られるのが便利だろうというのも、自サイトに他の人からの Webmention の URL を表示する判断をした理由の 1 つである。


とはいえ、やはり他人のコンテンツが自分のサイトに表示されるのは気持ち悪いという考えは拭いきれないので、受け取った Webmention についてはかなり控えめに表示することにした。

この画像のように、このサイトの記事の下のほうにはちっちゃく薄いグレーで Webmentions というセクションがある。 本文本体とは絶対に混ざることのない非常に控えめな表現となっている。

他の人の作った自分がコントロールできないコンテンツを表示する量を減らすということも徹底している。

まず、コメントを展開して表示することもない。 コメントが来ていてもコメントであるということを示してコメントへのリンクを貼るだけである。

また、アバター画像は表示していないし、名前とかも自由記述欄であることには変わりなく、個人的に望ましいと思えない名前の人のコメントが残って気持ち悪い気分になるのが嫌だったので Webmention 送信側のホスト名を表示して名前は直接表示していない。 ホスト名自体が気に入らなかった場合はまあ諦めることにする。

コメントが展開表示されないのは、コメントしてブログ同士の交流を図りたい人にとっては不満に感じられるかもしれないが、私として Webmention を実装する上で許容できる範囲内での実装となるとこのくらいが限度かなあということで。 個人的に Webmention とかそういう流行とかで個人 Web サイトたちが盛り上がるのは歓迎だけど、やっぱり他人のコメントとかの表示はあまり欲しくないのだと思う。

私のサイトに Webmention を送ってコメントとかしてくれる人がいたとしてもあんまり思うような表示にはならないと思うのでその点は申し訳ないと思う。 まあ、そういうサイトもあるってことで諦めてほしい。


ということで対応状況を適当に書いたが、最後にどういう実装なのかについても記載しておく。


今回実装に当たって受信側は webmention.io[2]に全部丸投げしている。

こういう外部サービスへの依存を持つのはこのサービスが終わったり終わらなくても仕様が変わったらどうするのだという話があったりする。 が、私にとっては Webmention は自サイトの根幹コンテンツではなく、おまけのお楽しみ要素という感じなので別に良いかなと。 webmention.io が使えなくなったら潔く Webmention の受信を止めてもよいだろうし、サイト自体を Webmention の受信必須とは思っていないのでガッツリ webmention.io に依存して楽することにした。

この Webmention で表示されているものについては rel="nofollow ugc" をつけて自分の推薦ではないというような意図を明示しているつもり。


送信側は自分のブログ執筆クライアント[3]からリクエストを投げる形にしている。

このサイトは Astro で作られた Web サイトだが、このサイトには現在の公開されている記事一覧とリビジョンハッシュなどの情報を保持する json を返すエンドポイントを用意している。 これを執筆クライアントが叩くことで、サイトがちゃんとビルドされて記事が公開されたことを確認してから他の人のサイトに Webmention を送れるようになっている。 リビジョンハッシュは記事本文やタイトル、反応の種類や slug などなどから作った Hash である。 過去に Webmention を送ったときの Hash と公開されている記事の json の Hash が異なる場合は以前 Webmention を送ってから記事が更新されているので更新を送る必要がある、という判定をするために与えているものだ。

この JSON は Cloudflare のエッジや Cache-Control で JSON が古いままになる可能性があるので、そこらへんを注意して実装してもらうように Claude Code にお願いした。

記事が言及している URL については、記事の markdown の中に含まれる URL を取り出している。 当初は Claude Code はビルド後の HTML から <a href> を探した方が markdown の方言などにも依存しなくなるのでよいはずだ、と述べていた。 しかし、その手法だと X の発言を埋め込んだときに問題が起きる。 X の発言を X のポストカードとして埋め込んでいるが、ビルド後の埋め込まれたポストの中に URL が含まれていた場合、この記事で私が言及した URL とは別に私が埋め込んだポストの中にあったリンクにまで Webmention が飛んでしまう。 そこで上記の Claude Code の提案は却下してビルド前の markdown から URL をちゃんと探してもらうことにした。

「いいね」や「コメント」などについては Webmention の反応をするには source が必要なので /reactions/.../ という場所に小さいページを作る形にしている。 このページはサイトのトップページからリンクで辿れる必要もないしサイトマップからも除外しているし、検索エンジンに乗る必要もないので content の noindexc を入れている。

執筆クライアント上から他のサイトにいいねやコメントを投げられる UI を一応作っている。

いいねやコメントの削除には 410 Gone が必要だが、Cloudflare Pages がそのままでは 410 に対応していないらしい。 が、Cloudflare functions で 410 の応答を作れるとのことだったので、それで対応ということにしている。


あとは実装で気にしたことというと、個人のローカルで動いているマシンから Webmention を送りつける形になっているので送信先の Webmention の受付先については注意しているつもり。 例えば Webmention の受付先としてローカル IP とか私の家庭内ネットワークのアドレスを指す形にした悪意あるページを公開して、私がそれと知らずにリンクしたりした場合、外部の人が私のローカル内部でのリクエストを投げられることになってしまう。

そこで Webmention の受付先については許可した IP かどうかを確認している。 ローカルの IP とかは弾かれるようになっているはず。 その確認の際には名前解決した IP を検査し、許可した IP へ接続先を固定したうえで HTTP リクエストを送る設計で、HTTPS の証明書検証は元のホスト名に対して維持する感じにしている。 接続前に名前解決して公開 IP だったことを確認し、その後で通常の HTTP クライアントに URL を渡すだけでは不十分で、HTTP クライアントが再び名前解決した際に、別の IP が返る余地があるとかそういうのも考慮して。


送信受信の機能の検証には、Webmention Rocks[4]を使った。

https://webmention.rocks/test/1 のエンドポイントを使い Webmention のリアクションを送って、それが表示されるかを確認したり。

ここではいいねもコメントも全部コメント的に表示されているようだが、それはこのサイトの仕様のようだ。

また、 https://webmention.rocks/receive/1 のエンドポイントを使い、自分のサイトへ Webmention のリアクションを送って自サイトに表示されるかも確認した。

ここでテストに送った Webmention はテストが終わったら必要ないので、webmention.io の管理画面から削除しておいた。


ということで Webmention を実装してみた話だった。

他人の反応を自サイト内部に配置したくない、みたいな個人的なわがままのおかげで非常に主張の薄い目立たないような地味な墨のほうに追いやられた扱いにはなっているけれども。 今後他の個人サイトで Webmention に対応していく流れが続いていくのか、それともあっという間に流行りが終わるのかはわからないけれども、まあこのくらいの仕組みなら置いておいても良いかなという気がするので一旦しばらくは実装を維持するつもり。

今後スパムだとか何かよくないコメントが大量についてくるとか、そういう面倒なことになったらバッサリ Webmention の機能を切り捨てることもあるだろうけれども、まあしばらくは牧歌的に楽しんで扱える程度の人数しか Webmention に対応しないだろうし、その間は実装したまま置いておこうかなあ。

Series

References

  1. 1. Webmention対応ブログは22件のようです!
  2. 2. Webmention.io
  3. 3. ブログ執筆アプリを用意した
  4. 4. Webmention Rocks!

Cited By

Webmentions