Block Rockin’ Codes

back with another one of those block rockin' codes

Blog を引っ越しました

新しい技術などを自分で色々試せるように、自分のドメインの、自分で作ったブログに移行しました。

ここの記事も、いくつかはアップデートがてら移行していく予定です。

あたらしいブログは以下です。

よろしくお願いします。

次世代 Web カンファレンスを開催しました #nextwebconf

intro

次世代 Web カンファレンスを開催しました。

next web conf logo

実施概要

概ね開催概要の通りです。

jxck.hatenablog.com

やったこと

やったことはシンプルです。

テーマ毎に、今 Web がどうなっていてこれからどうなっていくのか をひたすら議論するセッションのみのカンファレンス

やらなかったこと

以下はこのカンファレンスではやりませんでした。

  • スポンサー募集
  • Tシャツ/ステッカー/チラシ作成
  • 公式サイト作成/ドメイン取得
  • 公式懇親会
  • LT大会/ドラ
  • 基調講演
  • メディア連携/対応
  • 何かの宣伝
  • お金を扱うこと全て

セッション

  • テーマ毎に 60 or 80 分のセッションを行う
  • 3 トラック並行で実施
  • セッションオーナー(まとめ役) + 2~3 人の登壇者で実施
  • スライドやデモ・台本などは用意しない
  • プロジェクタは固定スライドを表示
  • 資料が無いので、資料公開はない。代わりにセッション自体の配信、録画を公開。
  • 登壇者の発言は、所属する組織とは関係なく、個人の発言である」を全体共通とする。

登壇者にお願いした事

全ての登壇者に以下をお願いしました。

  • 何かを宣伝する目的で出ないでください
  • 登壇者の発言は、所属する組織・団体とは関係なく、個人の発言である」を前提としてください
  • (初心者など)聞き手のレベルを意識せず、話したいレベルで話してください
  • 録画を公開させてください(声だけも可)
  • 資料やデモなどの準備はいりません
  • 細かく打ち合わせしすぎると、当日話す事がなくなり失敗するので、打ち合わせしすぎないでください
  • ひたすら日頃思っている事を議論してください
  • 登壇者にスタッフも兼ねてもらいます
  • 出演費・移動費など、お金は一切出ません
  • 実施形態に納得できない場合は出演を断ってください

録画

405(#nextwebconf405)


次世代Webカンファレンス 405 #nextwebconf - YouTube

406(#nextwebconf406)


ライブ配信|次世代Webカンファレンス 406 #nextwebconf - YouTube

407(#nextwebconf407)


次世代Webカンファレンス 407 #nextwebconf - YouTube

outro

登壇者・スタッフのみなさん、最後までおつきあい頂き本当にありがとうございました!


議論というものにフォーカスを絞ってやってみました、決して簡単とは言わないが、こういうのもありなんじゃないかと思う。

次回とかは考えてない。またあるかもしれないし、二度とないかもしれない。

Jxck

「次世代 Web カンファレンス」を開催します

Intro

2015/10/18(日) に、「次世代 Web カンファレンス」を開催します。

  • 名称: 次世代 Web カンファレンス
  • 日時: 2015/10/18(日)
  • 場所: 法政大学
  • hash: #nextwebconf
  • 公式: connpass
  • 参加費: 無料

Motivation

「Web について話す場」

というか「Web そのものをテーマにした場」というのが、意外と少ないなとずっと思っていました。 (もちろん、結果として Web について話しているカンファレンスや勉強会はたくさんありますが。)

そして、スライドなどを用いて何かを「発表する」ニュアンスではなく、進化の早い Web で「今何が起こっているか?」と「これからどうなっていくのか?」という、答えの無いもの、でもみんなが気になり考えていること、今だからこそ考えないといけないことを真っ向から議論する場というのが、もっとあっても良いのではないかと考えていました。

今回開催するカンファレンスは、この「議論」だけからなるものです、それ以外のことはしません。 この趣旨に賛同してくださった、各分野のプロフェッショナルに協力頂き、「次世代 Web カンファレンス」として、開催させていただくことになりました。

やること

やることはシンプルです。

テーマ毎に、今 Web がどうなっていてこれからどうなっていくのか をひたすら議論するセッションのみのカンファレンス

やらないこと

以下はこのカンファレンスではやりません。

  • スポンサー募集
  • Tシャツ/ステッカー/チラシ作成
  • 公式サイト作成/ドメイン取得
  • 公式懇親会
  • LT大会/ドラ
  • 基調講演
  • メディア連携/対応
  • 何かの宣伝
  • お金を扱うこと全て

セッションは録画し後日公開します。配信はベストエフォートで実施します。

セッション

  • テーマ毎に 60~80 分のセッションを行う(調整中)
  • 3 トラック並行で実施
  • セッションオーナー(まとめ役) + 2~3 人の登壇者で実施
  • スライドやデモ・台本などは用意しない
  • プロジェクタは固定スライドを表示
  • 資料が無いので、資料公開はない。代わりにセッション自体の配信、録画を公開。
  • 登壇者の発言は、所属する組織とは関係なく、個人の発言である」を全体共通とする。

登壇者にお願いしてる事

全ての登壇者に以下をお願いしています。

  • 何かを宣伝する目的で出ないでください
  • 登壇者の発言は、所属する組織・団体とは関係なく、個人の発言である」を前提としてください
  • (初心者など)聞き手のレベルを意識せず、話したいレベルで話してください
  • 録画を公開させてください(声だけも可)
  • 資料やデモなどの準備はいりません
  • 細かく打ち合わせしすぎると、当日話す事がなくなり失敗するので、打ち合わせしすぎないでください
  • ひたすら日頃思っている事を議論してください
  • 登壇者にスタッフも兼ねてもらいます
  • 出演費・移動費など、お金は一切出ません
  • 実施形態に納得できない場合は出演を断ってください

予定しているセッション

今決まっているセッションのみ、テーマ名は仮です。

theme owner speaker
serverside_arch @ryushi @kuenishi, @yugui, @making
frontend_app @hokaccha @koba04, @armorik83, @laco0416
client_perf @summerwind @_furoshiki, @ahomu
server_perf @mirakui @xcir, @cubicdaiya
monitoring @songmu @fujiwara, @mikeda
js_next @teppeis @t_wada, @constellation, @vvakame
css @cssradar @hiloki, @morishitter_
security @hasegawayosuke @nishimunea, @kinugawamasato
webrtc @iwashi86 @voluntas, @tonofo
http2 @jxck_ @tatsuhiro_t, @jovi0608, @kazuho
authZ/authN @mad_p @nov, @kura_lab, (TBD)
standardization @myakura @azu_re, @lef, @ourmaninjapan

その他詳細は、募集開始時に Connpass に掲載します。

Jxck

HTTPS 化する Web をどう考えるか

Update

  • 2015/5/8: 指摘頂いたタイポや誤訳などを更新しました。
  • 2015/5/8: 構成を一部修正しました。

Intro

4/30 mozaiila のセキュリティブログに下記のようなエントリが投稿されました。

Deprecating Non-Secure HTTP | Mozilla Security Blog

エントリはそこまで長くないので、ここに翻訳の全文を記載します。 そして、元エントリのライセンスである CC BY-SA 3.0 に則り、 本エントリも同じく CC BY-SA 3.0 とします。

Deprecating Non-Secure HTTP

原文: Deprecating Non-Secure HTTP

今日は、 non-secure な HTTP から、徐々に廃止していくという方針についてアナウンスします。

HTTPS が Web を前進させる手段であるという点は、広く同意が得られています。 ここ数ヶ月でも、 IETF, IAB (こっちの IAB でも), W3C, そして アメリカ政府 においても、 インターネットのアプリケーションでは、暗号化通信を広く使おうという声明が出ています。 Web について言えば、それは HTTPS です。

コミュニティ ML での活発な議論を踏まえ、 Mozilla はセキュアな Web の開発に新しい開発リソースを投入し、セキュアでない Web から機能を取り除き始めていくという合意にいたりました。 この計画は、大きく二つの要素から成ります。

  1. 期限となる日を決め、その日以降はセキュアな Web サイトでしか、すべての新しい機能が使えなくします。
  2. 特に、ユーザにとってセキュリティやプライバシー上のリスクが発生する可能性がある機能については、徐々にセキュアではない Web からはアクセスできないようにしていきます。

最初のステップとしては、この期限をコミュニティで決める必要があります。そして、どれが「新しい」機能なのかを定義する必要があります。 例えば、「新しい」を「Polyfill できない機能」と定義するなどが考えられます。 これなら、 CSS や他のレンダリングの機能は、ページ上で (<canvas> などを使って) 再現することで、引き続きセキュアではない Web でも使うことができます。 しかし、例えばハードウェアの機能にアクセスするようなものは、制限されます。

このプランの二つ目の要素は、セキュリティと互換性のトレードオフを踏まえて進む必要があります。セキュアでない Web から機能を削れば、壊れるサイトも出るかもしれません。 そのため、私たちはその破損具合をモニタし、セキュリティ的なメリットとのバランスを取る必要があります。 同様に私たちは既に、セキュアではないサイトから使われる機能のより緩い制限についても考えています。 例えば、 Firefox はすでにカメラやマイクへのアクセス権限の恒久的な取得を、セキュアでない Web には許していません。(訳注: http:// だと毎回聞かれるという意味) セキュアではない Cookie のスコープについても制限する提案がなされています。

注意して頂きたいのは、このプランは URI スキーマとしての "http" が古いコンテンツでも使えなくなるという意味ではないことです。 HSTS や CSP の upgrade-insecure-requests 属性を使うことで、 http:// スキーマがブラウザによって自動で https:// と解釈され、セキュアになります。

この取り組みのゴールは、 Web 開発者コミュニティに、 Web をセキュアにするべきだというメッセージを送ることであり、この取り組みは Web のコミュニティと強調して進めることで最も成果が得られます。 私たちは、まもなくW3C の WebAppSec Working Groupに対して何らかの提案を作成するつもりです。

この ML で議論に参加してくれた多くの人に感謝します。 Web をよりセキュアにしましょう!

Richard Barnes, Firefox Security Lead

要するにどういうことか

簡単に言えば、「これからの Web を http:// を使わず https:// を中心としたセキュアな世界にしていこう」という提案です。

これまでも、それを実現するためも「呼びかけ」というレベルでは MozillaGoogle 含め多くの人が多くの場所で行ってきました。 しかし、 Web にはすでに HTTP で公開されたサービスが多く有り、これは徐々にしか移行していくことができません。

そこで、「これから公開する Web については、極力 HTTPS にする」という状態を促すために、「これから Web に入る新しい機能は、 HTTPS のサイトじゃないと使えなくする」ようにすることで、開発者にHTTPS への移行を促すということです。

そのための作業として、まず以下があります。

  • それをいつからやるか?
  • 新しい機能ってどれのことか?

より詳細なプランはここに書かれています。

Insecure HTTP Deprecation Plan

何がおこっているのか?

言うまでもありませんが、 Web が一般化し、その使われ方も多岐にわたるようになりました。 しかも家で PC を開くときだけでなく、普段持ち歩く様々な端末が Web につながり、 その上で SNS やメールや金融取引まであらゆることを行います。

人がそこに依存すれば、同時に攻撃するメリットもどんどん増えていきます。

空港やカフェで Wifi を使えば、そのパケットはだれかに盗み見られているかもしれません。 どこかから送られて来たメール内のリンクは、罠サイトに通じているかもしれません。 そして、スノーデン事件によって NSA という米国機関までもが、大規模な盗聴を実施していた可能性がでてきました。

とはいえ、 Web のユーザの多くは、プロトコルや暗号の知識など無いでしょう。 そうした人にも安全に使えるように、安全側に倒されていくのは必然かと思います。

ログイン画面だけ HTTPS で後は HTTP という構成も多く有るかと思いますが、 誰がどこで何を盗聴しているかがわからない以上、「どれを暗号化すべきか」ではなく「基本的に全て暗号化する」という考えに移行し、 実際そういったサービスは増え始めています。 GoogleTwitterGithub のコンテンツは、もしかしたら今までなら「ログイン画面と設定画面以外は平文で良いだろう」と思われていたかもしれませんが、実際これらサービスはフル HTTPS 化が完了しています。

また、新しく出てくる Web の APIプロトコルには、セキュリティ上の理由から HTTPS で無いと使用できないものもあります。(後述)

一方で、 HTTP で公開され続けている古いコンテンツや、新しいにもかかわらず HTTP で公開されるコンテンツはまだまだあります。

Mozilla だけでなく Google を始めとする多くの団体や企業が、これから新しく公開されるコンテンツについては極力 HTTPS に移行するように呼びかけてきました。 今回の提案は、それをより加速するために、一定の制約を設けることで、開発者の HTTPS への移行を促すものと解釈できるでしょう。

どうなっていくのか?

端的に言えば「暗号化すべきかどうか」ではなく、「暗号化しない理由があるか」を考えることになっていくんだと思います。つまり、基本は HTTPS という世界です。

個人的にはずっと扱ってきたテーマでもありますが、 Web の HTTPS 化っていうのは結構前から始まっていました。 しかし、いよいよ本格的にそういう時代になっていくんだなという気がします。

もちろん、 Web に携わっている人なら思うところはあるでしょう。でももうそういう事を言ってられる局面ではないのかもしれません。

そして、 API 的に言っても「新しいことをやりたければ HTTPS」になっている実感はありました。

でも今回の提案はそれを逆手に取るというか、より「HTTPS じゃないと新しいことができない」のニュアンスを強めるということでしょう。

俺自身は、特に「ビジネス用途」で「これから作る」ものであれば、 HTTPS を選ばない理由はあまり無いと思っています。

しかし、 Web は別にビジネスだけの基盤ではありません。どんな使い方もできて、何をしてもいい。

それをふまえて一番気になっているのは、

「それが Web を窮屈にするのかどうか」

です。

確かに、デバッグしにくいなどの気持ちもわかります。自分も自分のサイトワイルドカード証明書を入れ年間 26000 円くらい払っています。

でも、例えば遊びで作った WebRTC や ServiceWorker が悪用されて誰かに迷惑をかけた場合どうでしょう。 そういう事例があった場合、証明書で検証できないドメインで公開されたデモアプリは手軽に試せるでしょうか? 俺にはまだその答えはわかりません。 でも、これはこれからの Web を考える上で重要な問題だと思います。

単純に是非だけで割り切れる問題ではないし、個々の立場やコンテキストによって結論は変わっていくでしょう。 必要があれば声を上げる必要が有るし、必要に応じて準備をしていく必要が有ります。

今回は、そうした議論をする上で知っておくべき動きについて知っている範囲で紹介します。

知っておきたい動き

もう少し技術的な側面から、 HTTPS が要求される流れやその理由を紹介します。

新しいプロトコルからの視点

新しいプロトコルを Web にデプロイするには、中間に入る全てのネットワーク機器(Proxy, FireWall, NAT など、 Intermedialies や Middle Box と言われる) が、そのパケットを正しく通過させる必要があります。

例えば WebSocket や HTTP2 の平文通信が使っている Upgrade ヘッダは、 Middle Box で意図的に落とされてしまい接続が確立できない場合が報告されています。 また、新しいプロトコルを新しいポートに割り当てるには、全ての FireWall でそのポートを空ける必要もあります。

このパターンに対処する一番簡単かつ確実な方法の一つが、経路を暗号化してしまう事です。 End-to-End で暗号化されていれば、 Middle Box は Upgrade ヘッダはもとより、自分を経由したパケットを一切見る事ができないため、基本的には丸っと通すしかなくなります。 そして HTTPS のデフォルトポートである 443 を通してしまえば、新たな穴を空ける必要も有りません。

HTTP2 や QUIC がそうであるように、今後出てくる新しいプロトコルについても、同様に TLS+443 という組み合わせに載ってくる可能性が予想されます。

新しいブラウザ API からの視点

最近ブラウザに追加された新しい機能の中には、非常に重要な情報やハードウェアへのアクセスを行う API があります。 こうしたものは、仕様自体が最初から暗号化前提で作られているものがあります。

例えば WebRTC の通信は DTLS での暗号化が必須になっています。

ServiceWorker は、 HTTPS でないと登録することすらできません。

そして、 WebRTC とセットでよく使われる getUserMedia によるカメラやマイクのアクセスは、 HTTPS では初回のみ使用許可を求められますが、 HTTP の場合は毎回求められます。

最近の流れで言えば、ブラウザのかなり低レベルな機能へアクセスする API が整備されつつ有ります。 こうした仕様の策定は、セキュリティサンドボックス化が非常に重要になり、慎重に設計されています。

こうした理由からも、これから出てくる新しい API について、 HTTP ではそもそも使えない、もしくは制限がかかるものは増えていくと予想されます。

移行を助ける仕様など

全てを暗号化前提にするといっても、現実的に難しい場面があることは既知の問題です。 そうした問題に対する解決策や、それに準ずる回避策として、最近ある話題について紹介しておきます。

Explicit Trusted Proxy

すべての通信が暗号化されると逆に困る場面も考えられます。 例えば、ペアレンタルコントロールやウイルス対策のようなフィルタリングサービスを、プロバイダなどが提供していた場合、 通信が暗号化されていては、中身が見えないのでフィルタリングできません。 同じように、平文だったから提供できたサービスは実は色々あります。

そこで、そうしたサービスが提供する Proxy を「ユーザが信頼した上で明示的に許可」することで、 その Proxy が途中で通信をほどいて、そうしたサービスが提供できるようにするための仕様が考えられています。 要するに MITM を明示的に許すというイメージです。

これを "Explicit Trusted Proxy"(明示的に信頼された Proxy) と呼ばれ、議論されています。

Opportunistic Encription

HTTPSTLS で暗号化するため、 TLS の持つ証明書検証の仕組みなどを使います。そのためクライアントは、サーバが提示する証明書を CA に問い合わせて検証し、相手を確認する必要があります。

ところが、NSA のような大規模な盗聴を考えると、「相手の検証」といった HTTPS の大事な部分を犠牲にしてでも 「とりあえず通信経路を暗号化」できるとうれしいという考え方もできます。

これを実現するのが "Oppotunistic Encription"(通称 OE) と呼ばれる方式で、日本語では "日和見暗号" と呼ばれます。

ALT-SVC というヘッダを用いてクライアントを暗号化通信に誘導します。 そもそも検証が行われないことが前提なため、証明書はいわゆる「オレオレ証明書」でサーブできます、ただしエラー画面は出ません。

もちろん検証が行われないため TLS の仕組みから見て「安全な通信」とは言い切れません。 移行が可能であれば TLS にし、そうできない場面への対応というとこになるでしょう。

Upgrade Insecure Request

HTTPS で提供されたコンテンツの中に HTTP で提供される JS や画像や iframe などのコンテンツが含まれる場合、 HTTP のコンテンツが改ざんされるとそこを経由して HTTPS のコンテンツも攻撃される可能性があります。

こうした混在したコンテンツは Mixed Content と呼ばれ、現状ブラウザはコンテンツに応じて以下のようなアフォーダンスを提供します。

  • HTTPS でも、 URL バーの TLS 表示にマークが付く
  • コンソールに warn や error メッセージを表示する
  • HTTP コンテンツをブロックする

特にコンテンツがブロックされる場合、正しい表示にならなくなります。 これは、多くのコンテンツが http:// の URL でハードコードされたコンテンツにとっては頭の痛い問題で、 これが HTTPS への移行を妨げる原因になる場合があります。 (ドラフト では BBC や NYT などの膨大なレガシーコンテンツを例に出しています。)

この Mixed Contents への対策として提案されているのが Upgrade Insecure Requests です。

これは CSP のヘッダに Upgrade Insecure Requests を指定すると、コンテンツ内の http:// リンクを https:// に書き換えてリクエストを発行してくれるというものです。 これにより URL がハードコードされたコンテンツも、コンテンツを一切いじらずサーバの設定変更だけで HTTPS オンリーに移行できるということです。

content-security-policy: upgrade-insecure-requests

しかし、ここまで単純な例ばかりではないため、実際はより細かい設定が可能になっています。

ちなみに最後のデモは、レスポンスヘッダではなく meta タグで指定されています。

Let's Encrypt

TLS の証明書取得には、種類などあれどそれなりの費用がかかります。 もちろん、ビジネスでやっているのであればしかるべき証明書を買うべきだと思いますが、 個人で趣味でやっているサイトなどで証明書を入れるのは、手軽とは言えない現実もあります。

そこで、 MozillaCiscoAkamai などが共同で作ったのが "Let's Encrypt" であり、 これは誰でも無料で手軽に証明書を取得できるというものです。

無料なため、例えば組織の身元を証明するような機能は無く、単純にドメインの所有権が正しいかを見る(DV 証明書)だけのものになっており ビジネス用途で使うものではありませんが、個人が趣味で使うドメインなどに使うことができます。

パフォーマンス関連

TLS にすれば、 TCP の 3-way-handshake に加えていくつかのやり取りが両者間で発生します。 通信する両者だけでなく、 CA など外部とのやり取りも発生します。 接続が確立した後は、平文の HTTP に比して暗号/複合の計算コストも追加されます。

しかし、こうした問題は既知であり、最適化の手段も整備されつつある印象です。

例えば、以下のようなものがあります。

  • Session Resumption/Session Ticket などによる接続開始の簡略化
  • OCSP-Stapling による失効確認の最適化
  • AES-NI によるハードウェアサポートによる高速化

この辺は、そのうちまた別途まとめて書きたいと思います。

Acknowledgement

翻訳部分は @jovi0608 さんにレビュー頂きました。

また公開後以下の方々にフィードバックを頂きました。

有難うございました!

Ajax 誕生から 10 年とこれから

Intro

誕生と言うのが正しいか微妙だけど、多分誕生でいいと思います。 というのも、「Ajax」という名前の出典は以下の記事で、この記事が書かれたのが今日からちょうど 10 年前でした。

f:id:Jxck:20150218010312p:plain

Ajax: A New Approach to Web Applications

(当時から、 URL が一回変わっている)

Web 初めてまだ 10 年たって無いんで、全部見てきたってわけではないですが、個人的にはちょっと思い出深い記事だったりするので、ちょっと振り返ってみます。

Ajax: A New Approach to Web Applications

筆者の Jesse James Garrett 氏は UX のコンサルティング会社である Adaptive Path の創立メンバーの一人で、 UX エンジニアです。 この記事の趣旨は、当時既にあった Google MapsGmailGoogle Suggest といったアプリの挙動について分析し、それを Ajax と名付けるものでした。

当時、特に Google Map が世に出た時に、時代的には多くの人はその UX を「Flash で実現しているんだろう」と思ったでしょう。 ああやってグリグリ動かせるマップを作る事は、従来の Web の考え方ではできませんでした。

ちなみに当時の地図といえば、概ねこんな感じでしたね。

f:id:Jxck:20150218010114p:plain

地図の周り 8 方向の矢印や拡大率は全部リンクで、クリックするとその場所や拡大率を表示したページを遷移する。なんと懐かしい UI だろう、今だとイライラして最悪な UX ですが、昔の地図とはこうだったと思います。

Yahoo 地図 は今でも、この画面遷移タイプの地図が残っていました。

ちなみに地図をクリックで掴んでずらそうとすると、こうなるwww (この地図もそのうち消えるだろうし、せっかくなので考古学の資料として残しておこう)

f:id:Jxck:20150218010241p:plain

で、 Google Map は Flash が入っていなくても画面なんか遷移せずグリグリ動かす事ができ、今ではどの地図もだいたいそうなっています(もちろん Yahoo の地図も)。

他にもブラウザでのメールはリロードして受信して、メールを開くのは画面遷移だったし、入力フォームも今のように候補を出してくれたりはしなかったし、検索結果も勝手に絞り込まれたりしなかった。

Garrett 氏が書いたこのエントリは、こうしたアプリが Flash を使わずにどうやってその UX を実現しているのかを解析し、そこに名前を付けるものでした。 だから実際彼がこのエントリを書く前から、 Ajax 的なものは少しづつ出ていて、彼がそれに受けの良さそうな名前を付けたというもの。

Ajax の何が良かったのか

何よりもインパクトが大きかったのは、それが Flash のようにプラグインのインストールを必要とせず、 HTML + CSS + JS (+ XML) だけで成り立っていたという事だったと思います。 導入にインストーラはいらなかったし、ということは手順書もいらなかった。 そして、当時新しい技術は「ベンダ」が主導していくのが主流だったところ、 Ajax はブラウザが持ってる標準技術だけでできた。平たく言えばどこかに高いライセンス料を払う必要がなく実現できた。

そして、この記事が「New Approach」と言っているの通り、使っている技術はすでにあるもので、その組み合わせ方が新しかった。

これによってそれまで文書(Document)を閲覧(browse)するために使われていた Web が、アプリを動作させるプラットフォームとしてスタートしたきっかけだったのは確かだと思います。 (そういえばそれを Web2.0 とか言ってましたね)

まあ実際それで Google Map 並みのアプリを作るのがどれだけ大変かは別としても、夢は広がっていたんだと思います。

当時の JavaScript なんて、マウスカーソルに変な装飾を施したりする程度のものと、完全におもちゃ扱いされていた頃でした。 そしてセキュリティ的な事情から、ブラウザで JS をオフにしているユーザが沢山いることを理由に 「JS 無しでも動く」が Web 開発の用件としてよくあったらしいし、動いたとしてもブラウザの実装差異なんて目も当てられない状態だったと思います。 (この時期に Google Map とか実現していたということを考えるとヤバ。)

Ajax の由来

記事では Asynchronous JavaScript + XML の略だと書かれています。

The name is shorthand for Asynchronous JavaScript + XML

通信フォーマットは XML だ!みたいな感じがしており、このおかげで 「Ajax でやりとりするのは XML だ!」 みたいな無益な原理厨を産んだという意味では害悪しか無い名前ですが、 一応このエントリの FAQ にも 「XML じゃなくてもいいよ、 JSON とかいいよ!」って書かれてます。

なんでかというと、正直これは単なる洗剤の語呂合わせだと言われています。(もし省略なら普通 AJAX と全部大文字にする)

f:id:Jxck:20150218010044j:plain

なんで洗剤かというと、そのころ SOAP (石けん)という技術があってだなという話らしいけど、まあ名前なんてそんなもんですよ。 大事なのは響き。そしてたぶん本人の想像以上に成功したんじゃないでしょうか。今コレが何の略かなんて誰も気にしてないだろうし。

その後の流れ

まず、 JS が見直されましたよね。書く人が圧倒的に増え始めた。 ツールやエコシステムが出始めて、 jQuery が出たのはこの翌年だそうです。 $.ajax() なんて冷静に考えれば酷いメソッド名ですね。

そして、閲覧ソフトだったブラウザ(Browser)の重要性があがり、この 3 年後の 2008 年には Google 自身もブラウザを作り、Chrome の beta が公開されました。 同時に、ブラウザ同士が差別化のために独自機能をつけまくってた時代が終わり(というか立ち行かなくなり)、ちゃんと標準化しようという流れになって、 だんだん HTML, CSS, JS の仕様が重要性を増して行きました。それが HTML5 という盛大なお祭りに繋がって行きましたね。

XHR を使って Comet でチャットとかが流行だして(Lingr とかもこの時期難じゃないかな)、 XHR でデータ連携で「マッシュアップだ!」みたいな時代あたりから俺も記憶があります。 そして JSONP という裏技を駆使してセキュリティ的にヤバいことに気づいて CORS を含む XHR2 に繋がったり、 Push も含めて WebSocket に繋がっていきました。

HTTP + JSONAPI を公開するサービスが増え、アーキテクチャとしての REST がやたらと見直されたり、認証として OAuth なんかも出てきたりした。

2009 年には、 V8 をサーバに仕立てた Node.js を Ry が作って、いきなり Socket.IO というキラーライブラリが出てきて、リアルタイム的な話と盛り上がった。

プロトコルとエコシステムとブラウザの API がそろい始めると、いよいよフロントで完結するロジックが増えて SPA 的な話が出たり、 フロントエンド含めてフレームワークが雨後のタケノコ並に現れては消えてった。

そうやって、 HTML も JS もブラウザもプロトコルもこれでもかというほどに進化してきたなぁという気がします。もちろんまだまだ足りてないものはたくさんありますが。あと CSS 頑張れ、超頑張れ。

その後も色々なことが起こったけど、結局いまだにこの記事に書かれていることと、そう変わらない発展系をやっているだけで、 つまりこの 10 年間は、 Ajax をひたすら消化した期間だったのかなぁという気がします。

WebSocket も WebRTC も面白いけど、結局通らなかったりするけど、最後に Ajax は必ず通る。 その安心感とシンプルさが今の Web をかなり支えている気がします。

これから

今読んでみればもちろんなんてことは無い記事なんだけど、 Web のことを勉強し始めてしばらくしてからこの記事の存在を知って、読みながらワクワクしてた気がします。 多分、自分自身が Web が面白いと本格的にのめり込むきっかけだったのかもしれません。

Web がアプリケーションプラットフォームとしてのスタートを切ってから 10 年たっても、未だに人の欲は尽きず、まだまだ進化の余地を見せている気はします。 新しい事は放っておいても起こるし、その途上を体感できるので、タイミング的には凄く楽しい。

一方で、ブラウザとかもう人類がゼロから作るには複雑すぎる存在になってしまし、もはや OS になろうとしている。ブラウザを積むデバイスも増えたし、 Web に載せるアプリも増えた。 あと、作るという立場で言うと Web って勉強するのがもの凄く大変になってしまった気がしています。初心者が「どこから始めたらいいのか」と思うのも無理は無い。 最近は正直 Web 自体が、その自重でつぶれないかと思う事がたまにあります。

それでも Web 自体は良くなっていこうとしてるし、それはもう少し続くんじゃないかな。今はまだ人にとって欠かせないものになっていると思うし。 何より、自分は「Web が好きだ」と思えているので、Web がこれからも良くなって行けばいいなと思うし、そうしていきたいと思っている。 Web が「今どうなっているのか」、「これからどうなっていくのか」も、もうしばらく真剣に考えてみたいと思ってる。楽しいし。

次の 10 年はどうだろう、もしかしたらそろそろ Web の次が出てきて、それに引導を渡して行く 10 年になるかもしれない。 であれば、 Web の最後がどう息を引き取るのか、何が次の世界を作っていくのか。それもまた楽しみかもしれない。

なぜ html の form は PUT / DELETE をサポートしないのか?

注意

内容については一切保証しません。

ここでは、主に W3C ML での議論や各種仕様などに基づいて書いています。 ここに書かれていることが正しいかどうかは、自身で判断して下さい。 事実としておかしいところなどは、コメントでどんどん指摘して下さい。遠慮はいりません。

ただし、このエントリでは「form が PUT/DELETE をサポートするべきかどうか?」の議論はしません。 「REST の是非」や「PUT/DELETE の意義」についても議論する気はありません。 ここでやっているのは、あくまでもどういった議論の末現状があるのかの調査です。 そうした意見がある場合は、 W3C などに投稿するのが最も有益だと思います。

History

  • 2014/03/29: 公開
  • 2014/03/29: XForm と XHTML の関係を明確化(thanx koichik)
  • 2014/03/29: HTTP/1.1 と XHTML1.1 の時間関係を明確化、それにより HTML3.2 の項は大幅修正 (thanx koichik)
  • 2014/04/09: HTML Form Extension のサンプルを追加
  • 2014/04/10: Cameron 氏とのメールやり取りの結果、「今後」がわかったので追記
  • 2014/04/10: 関連エントリをリンク

Intro

HTML の Form は「歴史的経緯」だとか「セキュリティ的な理由」
により GET と POST しかサポートしない、
というよう分かったような分からないような説明はよく見るけど、
実際は何故なのか。

というのが話の始まりで、それを事あるごとに調べようとするけれど、よくわからずにいました。

ということで呟いてみたところ、色々な方から反応を頂きました。 その反応については、以下にまとめています。

なぜ html の form は PUT / DELETE をサポートしないのか? - Togetterまとめ

f:id:Jxck:20140329075224p:plain

わかったことは、過去についてはそこまではっきりと書かれたリソースはなさそうなこと。 そして、色々な条件が重なって、現在の仕様に落ちつているようであること。 また、新しい仕様についての提案はあり、議論はまだ続いているということ。

ここまでの話をあらためて調べて、まとめてみました。

前提

今回話題にしたいのは、 HTML の form の仕様が HTTP のメソッドの "GET", "POST" 部分しかサポートしていない理由です。

具体的には以下の method 属性です。

<form action="http://example.com/users" method="post">
   <label for="name">name: </label>
   <input type="text" id="name">
   <input type="submit" value="send">
</form>

HTTP/1.1 では、メソッドとして以下の 8 つを定義しています。

GET
POST
PUT
DELETE
HEAD
OPTIONS
TRACE
CONNECT

この中で実質リソースの操作に用いられるのは GET, POST, PUT, DELETE の 4 つです。

REST の考え方が普及して以降は、この 4 つのメソッドを用いてリソースの操作を実行する API を提供するサービスも増え、プログラム間の通信や、 Ajax を用いたリクエストでは PUT/DELETE を用いた操作は実際に行われています。

しかし、 HTML の Form は GET/POST 以外をリクエストすることができません。 そこで現状は、 POST リクエストに hidden 属性で _method パラメータを付与したり、 submit イベントを JavaScript でフックして、 Ajax で PUT/DELETE リクエストを代行するなどの方法で回避されています。

時系列

今回の件は、仕様の時系列にも関係があるので、まとめてみました。 各仕様は、 IETF, W3C などそれぞれのワークフローで更新されており、下記はその主だったバージョンのみを載せています。 

仕様(HTTP)

HTTP の各仕様を見てみます。

PUT/DELETE という method が最初に出てきたのは HTTP/1.0 です。

http://tools.ietf.org/html/rfc1945#appendix-D.1

これは、 appendix の Additional Request Methods 扱いです。 ここでは PUT, DELETE, LINK, UNLINK があり、独自拡張としてこれらのメソッドの実装があったため、その注意を促す目的だったようです。(実際どの実装だったのかは、わかりません。)

HTTP/1.1 からは intro で紹介した 8 つのメソッドが定義され、 PUT, DELETE は正式な HTTP メソッドになりました。

仕様(HTML)

HTML の各仕様を見てみます。いずれも Form の method には GET/POST しか定義されていません。

HTML3.2 http://www.w3.org/TR/REC-html32#form

method
When the action attribute specifies an HTTP server,
the method attribute determines which HTTP method
will be used to send the form's contents to the server.
It can be either GET or POST, and defaults to GET.

HTML4.0 http://www.w3.org/TR/1998/REC-html40-19980424/interact/forms.html#adef-method

HTML4.01 http://www.w3.org/TR/html401/interact/forms.html#adef-method

method = get|post [CI]
This attribute specifies which HTTP method
will be used to submit the form data set.
Possible (case-insensitive) values are
"get" (the default) and "post".
See the section on form submission
for usage information.

HTML5 http://www.w3.org/TR/html5/forms.html#attr-fs-method

The method and formmethod content attributes are
enumerated attributes with the following keywords and states:

The keyword get, mapping to the state GET,
indicating the HTTP GET method.

The keyword post, mapping to the state POST,
indicating the HTTP POST method.

HTML3.2

HTML3.2 のドラフトには、参照する HTTP のバージョンは明記されていないようです。 しかし、 HTTP/1.1 が出たのは HTML3.2 のたった 2 週間前であるため、現実的には HTTP/1.0 を参照していたとかんがえるのが妥当でしょう。

少なくとも、その 2 週間の間で PUT/DELETE の存在を意識した上で HTML3.2 の仕様に取り込まなかったというよりは、 PUT/DELETE の存在は一旦おいておき HTTP/1.0 ベースで HTML3.2 の仕様を(ほとんど決まっていたものを)出したという方が自然だと考えられます。

PUT/DELETE にしても、 HTTP/1.0 から存在はしており、それを HTTP/1.1 で採用するかは 1996 年後半ではもう議論に上がっていただろうし、 HTML3.2 の議論をしている側も完全に知らなかったということは無いでしょう。

ここは、 HTML3.2 は HTTP/1.0 をベースとし、 HTTP/1.1 への追従は後のバージョンで行う。 とするのが妥当な判断だっただろうと想像できます。

よって、問題は次のバージョン HTML4 に移ります。

HTML 4.0, 4.01

HTML4.0 からは、 HTTP/1.1(RFC2068) への参照が明示されています。つまりここからが HTTP/1.1 を前提に Form に PUT/DELETE を入れないことを選択したドラフトと言えるでしょう。

http://www.w3.org/TR/1998/REC-html40-19980424/references.html#ref-RFC2068

HTML4.0 は HTTP/1.1 が出てから 11 ヶ月後、 HTML4.01 は 2 年空いています。 しかし、該当部分の仕様はいずれのバージョンも変更がありません。

ここの期間には謎が多く、実際に「Form に PUT, DELETE を入れるべきか?」という議論が、あったのかどうかもわかりません。(見つけられませんでした、見つけた方は教えて下さい)

しかし、この時代(1997~1999) は、まだ WebDAVAjax、 REST の論文などは出ておらず、 PUT/DELETE によって何かを行うという需要がそこまで強くなかったのでは無いかと考えられます。

また、1997/4/4 には、 Apache HTTP Server の開発者から Apache HTTP Server に PUT を実装する場合の、セキュリティ的なリスクや、それを回避するために試行錯誤した結果が紹介されています。

Publishing Pages with PUT

ここで紹介されている手法は、あくまで「新規文書をサーバに置く(PUT)」というユースケースであり、Netscape Navigator Gold, AOLPress, Amaya という、オーサリング機能を備えた当時のブラウザが PUT をサポートしたことが読み取れます。

Apache でもまだ、実装の面でそこまでこなれていなかったことや、 Web ページの編集という、今の Ajax などと比べると限定的なユースケースからも、 PUT というものが、まだそこまで広く使われていたものではなかっただろうことが想像できます。

なお、当時ブラウザの開発に携わっていた @ さんにお聞きしたところ、やはり積極的な人がいなかったという雰囲気だったようです。

XForms

HTML では、仕様に取り込まれることがなかった PUT/DELETE ですが、実は XForms という仕様には 1.0 で PUT が、 1.1 で DELETE が追加されていました。(XForms 1.0 には 2nd, 3rd Edition がありますが、該当部は変わっていません。)

  • 2003/11/14: XForms 1.0 (GET, POST, PUT)
  • 2009/10/20: XForms 1.1 (GET, POST, PUT, DELETE)
  • 20xx/xx/xx: XForms 2.0(策定中) (GET, POST, PUT, DELETE)

XFormsXML を用いて、よりリッチな機能を持つ Form を実装するための仕様です。 XHTML2.0 には XForms が含まれる予定だったため、 XHTML2.0 が主流となっていればそれが使えたかもしれません。 しかし、 XHTML2.0 は策定活動が 2012/12/17 で終了しました。また XForms を実装しているブラウザは無いため、これらの機能は使うことができません。

HTML5

2010 年に、 HTML5 の仕様として、以下のスレッドでこの件に関する議論が行われました。 issue は HTTP の策定活動にもコミットしている Julian Reschke 氏です。

Bug 10671 - consider adding support for PUT and DELETE as form methods

これは Ajax が主流になって以降であり、かつ Rails などを中心に REST が普及した後です。 しかし、問題の提起は「Form に PUT/DELETE を入れよう!」という短絡的なものではなく、より慎重なもののようです。 Julian 氏の発言の一部を抜粋します。

#c0(最初の発言)

It seems that we currently do not understand how
PUT and DELETE will be useful for HTML forms.

For DELETE, it's indeed easy to create a useful request.
However, server implementations usually respond with 200
and a minimal response body ("deleted")
or 204 (no content).
So it's not clear how this can be used in a web application.

For PUT, it seems there's no real use case as long as
the web page doesn't have full control
over the payload, and also can set the content type.

Please consider removing this feature until there's a clearer
understanding about what it's good for.

#c5

The tricky question is how to actually *use*
PUT and DELETE with HTML forms.
The bug was raised because I think the spec (as it was back then)
wasn't specific enough to make this work,
and thus early adoption (such as in FF4) would
make it very hard to do the right thing later on.

PUT や DELETE を Form でサポートする前に、サーバとのインタラクションや Form では HTTP ヘッダなどが変更できない点につていて、まだ Form の仕様自体にキチンと解決すべき問題があるという、問題提起が主のようです。

しかし、この議論は Hixie こと Ian Hickson によって突然 Reject されます。

#c16

Status: Rejected
Change Description: no spec change
Rationale: PUT as a form method makes no sense,
you wouldn't want to PUT a form payload.
DELETE only makes sense if there is no payload,
so it doesn't make much sense with forms either.

DELETE はペイロードを必要としないし、 Form のデータを PUT したいわけではない。 Form でこれらをやるのは make no sense であるとしています。いわゆる Wont' Fix という感じです。 2011/12/2 のことでした。

HTML Working Group

ところが、この議論は 2011/12/7 に public-html-comments という別の ML で再発します。

Follow-up about PUT and DELETE in form methods

どうやら ML 初心者のようで「先週のあの議論、どうなったの?」という感じの質問です。 しかも、 bug 10671 で一度も指摘されていなかった Mike Amundsen という人の以下のドラフトが参照されています。書かれたのは 2011/4/1 、つまり 10671 の議論の最中ですね。

Supporting PUT and DELETE with HTML FORMS

この Follow-up about PUT and DELETE in form methods はかなり長い議論になり、そこでは具体的な仕様に落としこむために必要な Form の拡張などについて議論されていたようです。

それがひと通り終わった 2012/1/14 に Julian 氏は HTML Working Group に二つの issue を上げます。

タイトルの通り、 HTML の Form を HTTP のリクエストに対して拡張するための議論と、 HTTP のレスポンスに対するユーザエージェントの挙動についての議論です(こちらは、前段としてブラウザごとの挙動の調査もあります)。

いずれの issue も CLOSE されており、 ISSUE-195 については以下の結果がみつかりました。

前者は Cameron Jones 氏のもので、 Form を拡張する提案(proposal) がなされています。 後者は Edward Oconnor 氏のもので、 Cameron 氏の提案の複雑性や実装時の懸念などを指摘しているようです。

また ISSUE-196 の最後 で Cameron 氏はこの提案をより具体化した Unofficial Draft を 2013/2/22 に作成し Github で公開しています。

HTML Form HTTP Extensions

このドラフトが、現時点で追えた最後の議論の結果です。少し見てみます。

HTML Form HTTP Extensions

http://cameronjones.github.io/form-http-extensions/index.html

このドラフトでは、 Form から、生成される HTTP リクエストをより柔軟に変更できるように Form の拡張を行う仕様です。 PUT/DELETE のサポートという狭い範囲ではなく、本質的に Form に足りていなかった機能を拡張しています。

たとえば payload 属性を追加することで、 Form から HTTP のヘッダ情報を追加できるようにすることで、単に method が PUT/DELETE その他をサポートするだけでは解決できなかった問題にも対応できるようにしています。

ドラフト中の PUT と DELETE のサンプルを見てみます。

<form action="http://www.example.com/cms/hogmanay" method="PUT">
  <input name="If-Unmodified-Since"
         type="hidden"
         value="Tue, 1 Jan 2013 12:00:00 GMT"
         payload="_header"/>
  <textarea name="content">
    // content
  </textarea>
  <button type="submit">Update</button>
</form>
<form action="http://www.example.com/logs" method="DELETE">
  <label for="since">Since</label>
  <input name="since" type="datetime"/>
  <button type="submit">Delete</button>
</form>

DELETE は割りとそのままな感じですが、 PUT は input タグの payload 属性を用いて直接 HTTP ヘッダを追加しています。

他にも、ヘッダを触れるということは Bacis 認証が Form だけで(ブラウザ組み込みの UI ではなく)できます。 実際には、専用の username, password を使用します。

<form action="http://www.example.com/login" method="POST">
    <label for="_username_">Username</label>
    <input name="_username_" type="text"/>
    <label for="_password_">Password</label>
    <input name="_password_" type="password"/>
    <button type="submit">Login</button>
</form>

また、メールの送信も定義されているようです。

<form action="mailto:">
    <label for="to">To</label>
    <input name="to" type="email" payload="_action"/>

    <label for="cc">Cc</label>
    <input name="cc" type="email" payload="_header"/>

    <label for="bcc">Bcc</label>
    <input name="bcc" type="email" payload="_header"/>

    <label for="subject">Subject</label>
    <input name="subject" type="text" payload="_header"/>

    <label>Content</label>
    <textarea size="50"/>

    <button type="submit">Send</button>
</form>

結構な拡張ですね。

今後

Cameron 氏のドラフト以降、この議論は止まっているようで、特に 2013年後半くらいからの議論は見つかりませんでした。 現状どうなっているのかがわからず、 Cameron 氏のドラフトについても扱いがよくわからなかったため、本人にメールで質問をしてみました。

いきなりの質問でもそこは標準化ガイ、快く返してくれました。 それによると、以下のような感じ。

  • このドラフト自体は、完成している(出せる状態である)という認識。
  • HTMLWG への提出はまだしてないけど、もう少し頑張ってそこまでもっていきたい。
  • 近いうちに FPWD(First Public Working Draft) として ML に提出する予定。
  • HTML5.0 の策定プロセスに乗せて、実際には HTML5.1 あたりで入れたい。

ということで、近いうちにこのドラフトが ML に投稿されて、そこでまた今回の話を含めた Form というもの自体の今後についての議論が起こることと予想されます。 Cameron 氏は、投稿時には BBC に自分を入れてくれるとのことなので、動きがあったらまたここにアップデートを書きたいと思います。

まとめ

まとめると、以下のような感じかと思います。

  • HTML4.x 以前: 需要があまりなく、積極的に仕様に追加する人もおらず、 HTTP3.2 からの仕様を引き継いでいた。
  • XForms: 仕様には取り込んだが、それを含む予定だった XHTML2.0 の策定が終了し、普及しなかった。
  • HTML5: 議論は何度かあり、現在 Cameron 氏のドラフトあたりが有力で、これはそのうち ML に投げられる模様。
  • HTML5.1?: Cameron 氏のドラフトが議論され、承認されればこの辺で入るかもしれない。入らない可能性は大いにあると思われる。

Cameron 氏のドラフトについて意見がある場合は、 W3C の ML などを通じて Cameron 氏にフィードバックすることで、今後の議論に寄与することができると思います。

最後に、再度書きますが、もし何か間違いなどがあったら遠慮なく指摘して下さい。 必要なものについては追記し、アップデートします。

今回の調査にご協力いただいた皆様、本当にありがとうございました!

関連リンク

Jxck

Trigger と Stream ベースの Reactive スタイルについて考える

intro

先日 Meteor について調べて発表するにあたり色々調べたり、そのあと何人かの方々とお話させて頂いた中で、
思うところが出てきたので、アウトプットしたいと思います。


Meteor について発表してきました。 - Block Rockin’ Codes


Meteor 以前からも思っていたところもありますが、ちょうどいいので Meteor も対比に出しながら書いてみます。

Reactive Programming

@ さんも書いてたように、やはり一番大きいのはここだと思います。


Meteor.js - naoyaのはてなダイアリー


簡単に説明すると、

よく Excel に例えられますが、あるセルに他のセルの値を用いた計算式を埋めておくと、
その参照先のデータが変わった時に、式を埋め込んだセルの値も連動して変わるようなあれです。


プログラミングで見るなら、
例えば以下の場合、 b を出した後、
a の値を変えても、 b の値は変わりませんが、、

var a = 1;
var b = a + 1;

a = 2
console.log(b); // 2

リアクティブプログラミング的には
a が変わると、連動して b も変わる感じ。

var a = 1;
var b = a + 1;

a = 2
console.log(b); // 3

になるという感じです。


Reactive スタイルな Web

"Reactive なプログラミング" 自体は、先ほどの説明の通り「言語自体のサポート」無しでは書けません。
(先のようなコードは、 JS では動かないという意味)


しかし、このアイデアは「データソースに変更があると、 View に反映される」という置き換えを行うことで、
Web アプリ全体のアーキテクチャとして持ち込むことができます。


Meteor の場合は、バックにある DB 内のデータと、フロントの View に埋め込まれた変数を bind しておくと、
DB の変更が WebSocket で通知されたタイミングで、bind 先の View が更新されるようになっています。


こうした動作を Sock.js という Socket.IO みたいなモジュールを使って WebSocket(など) を用いた形で行なっています。
言語自体が Reactive な動作(?) をサポートしているわけではありませんが、全体のアーキテクチャが Reactive なスタイルというイメージです。


Meteor には多くの機能がありますが、自分が一番良いと思ったのは、この Reactive スタイルなアプリ開発を、
うまいこと抽象化して、それなりに簡単に実現できるようにしているところです。

なぜ Reactive か?


「リアルタイム Web」とくくられるアプリケーションに共通しているのは、
おそらく「サーバの変化を、素早く View に持ってきている」パターンだと思います。
チャットなども、 PtoP で無い限り、サーバを介しているので同じように考えられます。


そして、サーバの変化をフロントに持ってくるには、

  1. サーバの変化のイベントを取得
  2. そのイベントでリモートにイベント(やデータ)を Push
  3. クライアントはイベントを受け取ったら View を更新
  4. これら全体のハンドリング

というような形になります。


これを、先ほどの Reactive なスタイルを適応すると、とても素直に実現できます。


ちなみに Meteor では、それぞれ

  1. Pub/Sub をベースとしたイベント通知
  2. Socke.js を用いた Push
  3. liveui を用いた bind による更新
  4. ReactiveContext


を用いて実現しているようです。


ちょっとこれと照らし合わせて詳しく見てみます。

1.DB トリガーの再発見(かどうかはわからないけど)


発表でも言ったんですが、
最近は、 "DB トリガー" があれば、このアーキテクチャの 1 の部分がとてもすっきり書き直せるんじゃないかと思います。


トリガーは、例えばインサートが走った時に、そのクエリの終了時にイベントを発生し、
登録しておいた処理を実行するような機能です。


もし DB がトリガーをサポートしていなかったら、DB へのインサートをフックしたい場合、
プログラム側でイベントを生成する必要が出るでしょう。


変更を取得するために、 DB をポーリングする必要があるかもしれません。
Meteor では、インサートと同時に Pub/Sub でそれを通知しているようです。


こうした処理を、自前でやるのは、イベントの生成、例外処理、場合によっては MQ なども絡んできて割と面倒です。
ポーリングはパフォーマンスの問題も出ます。


しかし、トリガーがあると、インサートが(成功/失敗問わず)完了したことを、DB からのイベントとして取得することができます。
プログラムはトリガーからのイベントを待つだけで、面倒なところの大半をトリガーがやってくれるので、非常に見通しがよくなると思います。


しかし、リアルタイム性の高いアプリに DB の Trigger を持ち込むと、 Trigger 自体のパフォーマンスがかなり重要になってきます。
これらを踏まえた上で、今現実的に「使える」 Trigger を持つ DB がどのくらいあるのかは、自分は把握できていないんですが(多分 Oracle はいけるけど、お高い。。)
今後 DB 自体にこうした機能があるととても嬉しい場面は多いと思います。


感覚的にあまり取り上げられることが少ないように思うこの Trigger という機能が、今こそもっと見直されるべきだと思います。
そして、このままだと、リアルタイム Web のバックとしては、必須の機能になるんじゃないかと、個人的には思います。


そのうち、各 DB のトリガーのパフォーマンスも調べてみたいところです。
(ちなみにブラウザの localStrage なんかも change イベントを発生するんですが、これは別のタブに通知するためらしい。。なぜ。。)


2.通信手段

「リアルタイム Web」などと言われている文脈の中で、WebSocket なんかが一緒に盛り上がってる感じもありますが、
結局 WebSocket でリアルタイム感が出ているのは「サーバが Push をすることができる」という点が重要で、


つまり本当は WS でなくてもできます。ただ、 WS でやったほうが、効率がいい場合が多いということになります。
というか、 WS はそのためのプロトコルだし、これ以外にも ServerSentEvent や SPDY なんかもこれを実現するために使えるでしょう。
すべてを生 WebSocket でやる必要は無いと思います。


純粋な通信以外(認証、ネームスペース etc) はいらないなら、 Socket.IO じゃなくてもいい。


ここは完全に、通信量やパフォーマンスなどで使い分ける必要があると思います。

3.bind

View にバインドするパターンは MVVM 由来でいくつかあるらしいです。
knockout.js や Derby.js あたりがそうみたいだけど、あまり詳しくないのでわからない。

Reactive と Stream


やさしいFunctional reactive programming(概要編) - maoeのブログ から引用すると

Wikidediaから抜粋するとFRPにおいて重要なポイントは次の通りです。

入力はbehavior(振る舞いとかビヘイビア)か時間で変化するイベントストリームとして見える
時間にともない連続的(continuous)に変化する値を扱える(これがbehavior)
時間順に並ぶ離散的(discrete)なevent
時間にともない変化する値は、higer orderかもしれない(要するに普通の値じゃないかもしれない)


その下に behavior と event のわかりやすい説明があります。
ちょっと多いですが、まるっと引用させて頂きます。

behaviorの一番簡単な例は時間です。ある値tが時間を表すbehaviorだとすると、値tは時とともに連続的に変化します。
tを出力するとある時点の時刻が(サンプリングされて)表示されますが、内部的には連続的に変化しています。
他にもユーザが動かしているマウスの座標だったり、日照によって変化するボンネットの温度や、振り子運動しているブランコの速度、
刻々と変化する株価など、behaviorは実にありふれています。

一方で、eventとは時間と値が組になったストリームです。たとえばユーザからのキー入力を表すkeyという値を考えます。
keyはユーザがキーを押した時刻tと、どのキーかを表すcを組にした(t, c)という値のストリームを表しています。
他にもユーザがマウスをクリックするごとに発生するeventや、ボンネットの温度が5度あがるごとに発生するevent、
ブランコの速度が0になるたびに発生するevent、あるいは株式市場で取引の開始・終了を知らせるeventなど、eventもまたありふれています。

さて、これってどこかで聞いたことないでしょうか?

実は、 Node における Stream の概念が、まさしくこれらを抽象化していると見ることができます。


Node の Stream については、かつて以下に書きましたのでご参照下さい。


Node.js の Stream API で「データの流れ」を扱う方法 - Block Rockin’ Codes


簡単に説明すると、 Stream は「時間」と「値」を「データの流れ」として抽象化するためのインタフェース。というような位置づけになります。
連続して変化するデータを、イベントと合わせて扱うことができます。


つまり、 Node の Stream は、Reactive スタイルのアプリケーション開発と非常に相性がよさそうです。


例えば、 DB の変更を Stream として読み込み、データが変更されるたび(data イベントが起こるたびに) WebSocket でそれをフロントに送り、
フロントは WebSocket でデータを受け取るたびに、それを View に反映するといった感じ。


この場合は DB を ReadableStream として抽象化して、 Client (の View) を WritableStream として抽象化したものを、
pipe() で繋いだら完成です。


つまり

ServerReadableStream.pipe(ClientWritableStream);


です。逆も同じ。
つまりアーキテクチャ全体を Stream で抽象化できます。


で、これを 「Stream ベースの Web」として考えたのが、先の Stream の記事の次に書いた、下記の記事です。


Stream.IO というものを作ってます。 - Block Rockin’ Codes


このアイデアから生まれたのが Jxck/stream.io · GitHub です。
ということで、今まで考えてきたことが繋がったなぁと(汗


以上の話で、

  1. DB がイベントを生成するための Trigger
  2. イベント(とデータ) をリモートとやりとりするための WS などの通信手段
  3. View にデータを bind し更新するためのなんらかのエンジン
  4. それらを抽象化、ハンドリング(pipe) するための Stream


があれば、 Meteor とは違った、コンパクトなリアクティブプログラミングフレームワークになりそうです。
でも、3. は knockout.js とか delby.js あたりを使えば良さそうだし、 Stream.IO の責務ではないかな。



実は Stream.IO は、まだブラウザで node の Stream を動かすために EventEmitter, Stream, Assert などを移植して
力尽き 方向性を見失っていたんですが、色々着想が得られたので、もう少し頑張ってみようかなと思います。

outro

そんなことを GW 中考えていました。


リアクティブと合わせてトリガーにちょっと注目して行きたいです。


いつもどおり、ご指摘があればお願いします。