YAPC::Asia Tokyo 2015 に参加した #yapcasia

今年はトーク応募もしなかったのだけど、最後のYAPCということではりきって参加してきた。

トークで印象に残ってるのは、kazuhoさんのHTTP/2時代のウェブサイト設計と、Brad FitzpatrickさんのProfiling & Optimizing in Go

kazuhoさんのトークはだいたい毎年聞かせていただいてる気がする。今年の発表もとても丁寧で、HTTP2で何が良くなるのか、といった点をわかりやすく説明していただいて合点がいった。ダウンロードすべきリソースの数をなるべく減らすようなテクニックがHTTP2時代にはむしろ避けるべきであるというような知見は、アプリケーションエンジニアとっても必要だと感じた。

Brad Fitzpatrickさんの発表は、ライブコーディング形式で、有名ハッカーのコーディングの様子がみれて有益だった。Goのデバッギング/プロファイリングはちょっとやったことあるんだけど、Brad Fitzpatrickさんが何かする度に知らないテクニックが披露されて、めちゃくちゃためになった。mackerel-agentを作ってるときにメモリリークがないかをがんばって調べたことがあったので、メモリリークを検知する良い方法がないかを質問してみたりした。昔調べてやってた方法がそんなにはずれてなかったぽくて安心した。

一日目、YAPC::Asia 2007のTシャツをきていたら、Brad Fitzpatrickさんには「そのTシャツぼくももってるよ! 明日着てくる予定さ!」的なことを話かけられてびっくりした。着て来てよかった。

YPACにはじめて参加したのが2007年で、当時は学生だった。その時はほとんど知り合いとかいなかった。YAPCのコミュニティにあこがれて、がんばってPerlを勉強したり、Plaggerのプラグイン書きまくったりして、すこしづつWeb界隈の知り合いもふえて、そのうちコミュニティの雰囲気もわかってくるようになった。そのつながりで、はてなインターンに参加したりしたあとはてなに入社したりしてる。YAPCでは、通常トーク2回、LTも2回発表させていただくことができて、ほんとうに良い経験になった。1000人いるところでLTする経験まじでないので、度胸がついたと思う。

miyagawaさんもYAPCあるあるのセッションでたぶんおっしゃっていたと思うんだけど、自分にとってもYAPCやPerlのコミュニティはエンジニアとしての原点かなーと思う。今参加すると、知ってる人が大勢いて本当に同窓会みたいで、今年で終わってしまうのが、なごりおしい。

僕がWebエンジニアとして楽しく毎日やれてるのも、YAPCあってのことです。2006年から2015年にいたる関係者のみなさま、本当にありがとうございました。

Goによるプライベートネットワークへのアクセスを禁止するHTTPクライアントの実装

クローラのように、ユーザからの入力に応じて任意のURLにHTTPリクエストを発行するソフトウェアは、誤ってプライベートネットワークへのリクエストを処理しないようにする必要があります。悪意のあるユーザが故意にプライベートなネットワークに対してリクエストして、内部情報にアクセスするといった攻撃を行う可能性があるからです。

PerlではLWPx::ParanoidAgentLWPx::ParanoidHandlerといったモジュールが便利です。これらのモジュールは、リクエスト先のURLをチェックしてプライベートネットワークへのリクエストを禁止してくれます。単にIPアドレスをチェックするだけでなく、ホスト名をDNSで解決して得られたIPアドレスをチェックしたり、リダイレクト先のURLをチェックしたりしてくれます。まさに偏執的です。

このLWPx::ParanoidAgentと同様の機能をもったGoのライブラリを実装しました。

github.com

ParanoidhttpはGoの標準ライブラリのnet/httpで提供されているhttp.Clientのparanoidなバージョンを作ってくれるファクトリです。以下のように利用できます。

// DefaultClientを利用すると簡単に利用できます(http.DefaultClientと同じ設定です)
res, _ := paranoidhttp.DefaultClient.Get("http://www.hatena.ne.jp")

// プライベートネットワークへのアクセス時にはエラーが返ります
_, err = paranoidhttp.DefaultClient.Get("http://192.168.0.1")

// attackers-host.net がプライベートネットワークのIPに名前解決されたり、
// プライベートネットワークにリダイレクトされてもエラーになります
_, err = paranoidhttp.DefaultClient.Get("http://attackers-host.net")

// 自分でhttp.Clientを作ってカスタマイズもできます
// 内部で利用されるhttp.Transportやhttp.Dialerのオブジェクトも返却されるので
// 同様にカスタマイズできます
client, transport, dialer := paranoidhttp.NewClient()
client.Timeout = 10 * time.Second
transport.DisableCompression = true
dialer.KeepAlive = 60 * time.Second

便利ですね。

実装的には、http.Tranportをラップしてリクエスト時にリクエスト先のホストをチェックしています。URLのホストがIPアドレスでない場合はDNSに問い合わせてIPアドレスを取得してチェックします。

とにかく使いたい機能だけを実装したという感じで以下のような制限があります。

  • ブラックリスト/ホワイトリスト機能がない
  • 名前解決時のタイムアウトが設定されてない(OSのリゾルバのタイムアウトに依存してる)
  • 名前解決にかかる時間がhttp.Clientのタイムアウトに含まれない
  • IPv6に対応してない(よくわからないのでIPv6では接続できないようにしてある)

がだいたい問題ないと思います。必要あればissueたてたり、PullRequestをおねがいします。一応実環境でも使っています。

以上、どうぞご利用ください。

追記

TOCTOU攻撃に対して脆弱であるとの指摘をいただきました。ホストやIPの安全性チェックの直後に、DNSレコードを変更するような操作によって、危険なIPアドレスへのアクセスをひきおこす可能性がありました。

Goによるプライベートネットワークへのアクセスを禁止するHTTPクライアントの実装 - はこべブログ ♨

外部で名前解決してアドレスチェックしてから、HTTPライブラリ内でもう一度名前解決してるようにみえる / Dialer実装内での名前解決を「置き換える」形で実装しないとTOCTOU攻撃が可能になるのでよくない / 修正された

2015/08/05 10:36
b.hatena.ne.jp

指摘をうけて修正しました。ありがとうございます!

関西2015年夏アニメ 放送時間まとめ

今期も関西における今期のアニメの放送状況を表にまとめました。いつもどおりしょぼいカレンダーのデータを利用させていただいています。ありがとうございます。予約設定時の確認などにお役立てください。

今期の関西最速は前季よりも2作品増え4作品となりました。アニメイズム枠の移動にも負けず、作品数を維持できていてほっとしました。今季は特にABCテレビの2作品が最速になっており、活躍が目立ちますね。関西最速の作品は以下のようになります。

特に期待したいのは 干物妹!うまるちゃんですね。原作は未読なのですが、PVを見るにかわいらしい雰囲気ですし、なんか悪人がでてこなさそうなので気楽にみれそうです。

六花の勇者は王道ファンタジーものですね。7人の勇者の中に裏切り者が一人という謎解き要素もありおもしろそうです。ちょっと中二っぽい感じのテンションなのもいいですね。

GANGSTA. はハードなギャングの世界での能力者バトルものでしょうか。コミックが原作のようです。しぶいおじさんたちの活躍をたのしむといった趣になりそう? 凝ったストーリーがたのしめそうですね。

戦姫絶唱シンフォギアGXはシンフォギアシリーズの最新作です。シンフォギアシリーズももう三期目になるんですね。一期は関西最速をまとめはじめた2012年の冬の新作でしたから、ずいぶん長いシリーズになりました。

関西最速以外でもWORKING!!! やがっこうぐらしなど気になる作品もおおく楽しめそうな季になりそうです。それでは関西のみなさん今期も頑張りましょう。


関西2015年夏アニメまとめ


関西2015年春アニメ 放送時間まとめ

今期も関西における今期のアニメの放送状況を表にまとめました。いつもどおりしょぼいカレンダーのデータを利用させていただいています。ありがとうございます。予約設定時の確認などにお役立てください。

今期の関西最速は前季と同じく2作品となりました。今季はアニメイズムの枠移動により、関西最速の存亡が絶望視されていましたが、なんとか平年どおりの数字となりました。

血界戦線は原作はジャンプスクエア/ジャンプSQ.19で連載されていたコミックのアニメ化です。トライガンを書かれた内藤泰弘さんが書かれているんですね。僕は原作をよく知らないのですが、PVで見られる少しダークな雰囲気が気にいっていて楽しみです。殴る前に技名を言うので有名とのことで、どんな感じになるんでしょうね。

放課後のプレアデス(TVシリーズ)はもともとWebアニメで展開されていた放課後のプレアデスのTVシリーズです。PVを見る限りでは、魔法少女もののように見えますね。魔法の杖からエンジンの音がしたりするなど、スバルのアピールをするかとおもいきや車はでてこないそうです。かわいい雰囲気がするのでぜひチェックしたところです。

実は純粋な関西最速ではこの2件だけですが、関東地方とまったく同じタイミングで放送される作品としては、響け!ユーフォニアムFate/stay night Unlimited Blade Worksなどが増えてきています。アニメイズムの枠移動などもあり、全国的に放送時間を揃えようという動きが強まっているように感じますね。

アニメイズムの枠移動は残念な面もありますが、逆に東西の差がちぢまっているということで、灌漑スべきことなのかもしれませんね。それでは、今季も気を抜かずにがんばっていきましょう!

関西2015年春アニメまとめ


オブジェクト指向入門読み終わった

ちまちま読んでたオブジェクト指向入門を読み終わった。だいたい入門と言っているが、原題は"Object-Oriented Software Construction"で入門感はないし、上下巻あわせて2000ページくらいあって読みきるのが大変だった。

原著は18年前に発売された本だが、内容のほとんどは今でも有益で、全体を通してためになる。オブジェクト指向が解決しようとしている課題や、背景にある理論や考え方について解説してくれるだけではなく、実際にソフトウェアを設計する際にどのようにクラスを見つけ、どんな場面で継承を使い、ソフトウェア全体をどのように形作っていくのかという実践的な議論も充実している。

本の序盤では、ソフトウェアの品質の様々な側面についての解説や、オブジェクト指向以前から使われていたモジュールや型の概念のがもつ諸課題について詳しく解説してくれる。それらの問題をふまえ、次に、ソフトウェアの再利用性や拡張性、そして信頼性を担保する仕組みとしてオブジェクト指向が提案される。オブジェクト指向の考え方の後ろにあるのは抽象データ型の考え方だ。抽象データ型は、型と特性、公理、事前条件によって特徴付けられた抽象的なデータ構造の仕様記述でソフトウェアモデルを厳密かつ、過不足なく表現することができる。実は、オブジェクト指向におけるクラスは実装を伴う抽象データ型であるということが読み進めるとわかってくる。

抽象データ型をクラスとして記述するにあたって、公理をや事前条件をクラスの表記に組み込む必要がある。この本で解説につかっているプログラミング言語*1ではクラスに表明を記述することができ、ルーチンごとの事前条件や事後条件、クラス全体の不変条件を記述できる。ルーチンが呼び出し側に要求する事前条件とルーチンが呼び出し側に保証する事後条件を、契約のようにみなすこともできる(これが契約による設計のメタファだ)。

抽象データ型をベースにした考え方は本の全体で一貫していて、後半の実践部分でも、クラスを見つけるのに大事なのは、ソフトウェアの問題領域に対する適切な抽象を見つけることだと述べている。ソフトウェアが対象にしている問題領域に対する適切な抽象が見つかれば、適切なクラスとクラスがもつべき特性や表明、クラスが何を要求し何を提供してくれるのかといったことに対して、妥当な答えを出すことができるようになる。

最近はこの本で学んだこと参考に、抽象を意識してクラスの設計を考えてみている。別々のモノだと思っていたデータ群が実は同じ抽象に基づいていてひとつのクラスで表現したら見通しがよくなったり、似てるけど別々に実装されていた一連の処理群が実はある抽象に基づいていることに気づいて、特定のインターフェースを実装する形にしたらソフトウェアの他の部分とうまく適合したり、と有益な体験が続いている。機能ベースで考えてたりすると、ある機能を実装するメソッドをどのクラスに所属させるか悩むみたいなことがあったりするけども、悩むのは実はおかしいはずで、どのクラスにも機能追加するのが不自然であれば新たな抽象概念が登場したのではないかとか、いろいろ考えることができるようになった。

大学のころの研究室の先生が、「ソフトウェア開発っていうのは抽象化のことなんだよ」とおっしゃていたが、数年いろいろソフトウェア開発してみて、この本を読んでみると、少しはおっしゃっられていたことが、わかったような気がしたりしなかったりする。

オブジェクト指向入門 第2版 原則・コンセプト (IT Architect’Archive クラシックモダン・コンピューティング)

オブジェクト指向入門 第2版 原則・コンセプト (IT Architect’Archive クラシックモダン・コンピューティング)

オブジェクト指向入門 第2版 方法論・実践 (IT Architects' Archiveクラシックモダン・コンピューティング)

オブジェクト指向入門 第2版 方法論・実践 (IT Architects' Archiveクラシックモダン・コンピューティング)

*1:プログラミング言語の名前は伏せられていて下巻の最後の方でやっと教えてくれる

リアクティブプログラミングの技術を用いてマウスストーカーを実装する

古き良きインターネットアプリケーションであるマウスストーカー*1をリアクティブプログラミングの技術を活用して実装してみるという取り組みをしましたのでご紹介します。リアクティブプログラミングというと主語が大きめですが、ここではbacon.jsを使ってるくらいの意味です。

できたもの

まずは完成したマウスストーカーを紹介します。チェーンのように連なった星がマウスカーソルの軌跡を辿ってついてきます。工夫してうごかすとなかなか綺麗です。下のボタンを押すと実際にこの画面でマウスストーカーを有効にすることができます(requestAnimationFrameに対応したPCブラウザのみ)。いろいろ動かして遊んでみてください。

 f:id:hakobe932:20150308230637g:plain:w300





実装

このマウスストーカーがどのように実装されているか紹介します。ソースコードはGitHubに公開していますので、適宜ご参照ください。手元でビルドして試す場合には、READMEの通りにビルドして、example.htmlを表示してみてください。

では順番に見ていきます。

マウスカーソルの位置の変化をEventStreamに変換する

まずは刻々と変化するマウスカーソルの位置変化を、取り扱いやすいようにbacon.jsのEventStreamに変換しましょう。document要素に対して発生したmousemoveイベントをEventStreamに変換するには以下のようにします。

var mouseCursorStream =
  Bacon.fromEventTarget(document, 'mousemove').map(function(me) {
    return {
      x: me.pageX,
      y: me.pageY
    };
  });

これでマウスカーソルの変化を1つのオブジェクトとして関数に渡したりすることができるようになりました。(pageX/pageYは標準化されていないフィールドですが、polyfillのためのコードを書くことは本題ではないので、ここでは雑に使っています。)

刻々と変化する位置を目指して動くオブジェクトを作る

次はマウスカーソル追いかける星に相当するStalkerオブジェクトを作ります。

このオブジェクトは初期化時に与えられたEventStreamによって表される刻々と変化する位置に向かって、星の画像を移動させます。例えば次のようにStalkerオブジェクトを作ると、マウスカーソルを1つの星が追いかけます。

new Stalker(mouseCursorStream); // マウスカーソルを目指して動くStalkerを作る

f:id:hakobe932:20150308235518g:plain:w300

Stalkerオブジェクトの中では目指す位置のEventStream( = targetStream)の変化があるごとに、自分の現在の目的地を更新します。

function Stalker(targetStream) {
  // ... 
  var targetPosition = {x: 0, y:0};
  targetStream.onValue(function(p) {

    targetPosition.x = p.x;
    targetPosition.y = p.y;
  });
  // ... 
}

ここで出てきたtargetPositionを目指して星を一定速度で移動させるアニメーションのコードは、以下のような雰囲気なりますが、詳細は省略します*2

// Stalker のコンストラクタ内にて
// animationFrameごとにStalkerのpositionを更新する
  animationFrame.onValue(function() {
      position = next();
      elem.style.left = position.x + 'px';
      elem.style.top = position.y + 'px';
    }
  });
刻々と変化するStalkerの位置をEventStreamにする

ここまでで星を1つ追いかけさせることはできるようになりましたが、あまりおもしろくありませんし、まったくリアクティブ感がありません。そこで少し工夫してみます。

StalkerオブジェクトはtargetPositionを目指して一定速度で移動します。この移動中のStalkerオブジェクト自身の位置をEventStreamとして取り扱えるようにしてみます。

bacon.jsのBusというオブジェクトを使うと自分で値をpushできるようなEventStreamを作る事ができます。Stalkerが星の位置を更新する箇所でBusとして作ったEventStreamに値をpushします。pushされた値が最後にpushされた値と同じ場合は無視したいので、skipDuplicatesメソッドによって作られた新しいEventStreamStalkerオブジェクトのpositionStreamフィールドにセットしておきます。

// Stalker のコンストラクタ内にて
// animationFrameごとにStalkerのpositionを更新する
  var ps = new Bacon.Bus();
  this.positionStream = ps.skipDuplicates(); // Busに同じ値がpushされても無視する

  animationFrame.onValue(function() {
    position = next();
    ps.push(position); // 位置の変化をStreamにpushする
    elem.style.left = position.x + 'px';
    elem.style.top = position.y + 'px';
  });

これにより、移動中のStalkerの位置もmouseCursorStreamと同じ形式のEventStreamとして取り扱えるようになりました。つまり、Stalkerはマウスカーソルだけではなく別のStalkerも追いかけられるようになりました。

Stalker をつなげる

お膳立ては済んだのでStalkerオブジェクトをたくさん作ってもう少しおもしろいマウスストーカーを作れます。

例えば、1つ目のStalkerがマウスカーソルを追いかけるようにし、3つ目のStalkerが1つ目のStalkerを、3つ目のStalkerが2つ目のStalkerを追いかけるようにしてみましょう。

  var one = new Stalker(mouseCursorStream);
  var two = new Stalker(one.positionStream.delay(100));
  var three = new Stalker(two.positionStream.delay(100));

f:id:hakobe932:20150309003632g:plain:w300

うまくいきました。positionStreamで発生したイベントを100msほどdelayしているのがポイントです。positionStreamの更新は頻繁に行っているため、delayしないと3つの星がほぼ同じ位置に表示されて面白みがありません。

はじめに紹介したマウスストーカーでは以下のように30個の星を鎖のようにつなげて、自分より前にならんだ星を追いかけるように設定しています。

  var cur = new Stalker(mouseCursorStream);
  for (var i = 0; i < 30; i++) {
    cur = new Stalker(cur.positionStream.delay(100));
  }

感想

リアクティブプログラミングの技術を活用したマウスストーカーを実装してみました。刻々と変化する位置の変化をEventStreamのオブジェクトとみなすことで、Stalkerを刻々と変わる目的地( = targetStream)を目指して動くオブジェクトである、というすなおでわかりやすいモデルにすることができました。

例えば、EventStreamに頼らずにmousemoveイベントのハンドラで目的の位置を更新するコードをStalkerの外に実装することもできるでしょう。

var s = new Stalker(mouseCursorStream);
document.addEventListener('mousemove', function(e) {
  s.updateCurrentTargetPosition({x: e.pageX, y: e:pageY});
});

ですが、目的の位置が変化した時にどのような反応をするかはStalkerである限りはそれほど変わりがない(現在の目的位置を更新する)と考えられるので、コードの重複や情報隠蔽の観点からStalker内に実装されているのが良さそうに思います。かといって、mousemoveのハンドラの登録を直接Stalker内に実装すれば、マウスカーソルではない別のStalkerの位置からイベントを受け取って星を連ねる、といった柔軟性を実現できなかったでしょう。

EventStreamという抽象化は大変便利です。EventStreamを使うことでskipDuplicatesdelayのような便利なメソッドも利用出来ました。

マウスストーカーがリアクティブプログラミングを学ぶ最適な課題というわけではないようには思いますが、今回は変化するイベントをオブジェクトとして扱い組み合わせられることの便利さを少しは感じられたと思います。

おまけ: http://mouse-stalkers.github.io/への寄稿を募集しています

マウスストーカーの実装を集める取り組みを始めました。みなさん何かしらのマウスストーカーを実装されたことがあるかと思います。おもしろいマウスストーカーが埋もれてしまうのは残念なので、ぜひmouse-stalkers.github.ioにPullRequestしてください。

*1:マウスカーソルの後ろに星がくっついてきたりするヤツ

*2:そしてアニメーションしているところのコードは雑です

関西2015年冬アニメ 放送時間まとめ

今期も関西における今期のアニメの放送状況を表にまとめました。いつもどおりしょぼいカレンダーのデータを利用させていただいています。ありがとうございます。予約設定時の確認などにお役立てください。

今季の関西最速は二作品となりました。なかなかの苦戦ですね。

蒼穹のファフナーEXODUSは2004年に初めて放送された蒼穹のファフナーシリーズの最新作です。もう10年前なんですね...。今季に放送される作品は、2004年のTVシリーズの2年後を描いた劇場版の後の時間軸の物語になっています。初見の人にも配慮されたストーリになっているそう。僕は2004年のテレビシリーズを途中までみたのですが、ストーリーが辛くなってきて見続けられなかった記憶があるので、今季視聴しようか悩んでいます。

ローリング☆ガールズは原作なしのオリジナル作品です。都道府県がそれぞれ独立した国家になった日本を舞台に主人公四人組が旅をするというストーリーとのことです。トレーラーをみるとなかなかポップな絵作りで楽しく見れそうな予感がします。キャラデザの原案がTARITARIと同じtaruさんなのが個人的な気になりポイントです。どういった作品になのか、まずは放送が楽しみですね。

実は、艦隊これくしょん -艦これ-DOG DAYS″は関東と同時刻の放送になります。完全勝利とはいきませんが、最速には違いありませんから、要チェックです。

お正月もあけたばかりですが、もう新番組の放送ははじまりつつあります。今季も気を抜かずにがんばっていきましょう。

関西2015年冬アニメまとめ