JSXコンパイラのオプション詳説(もしくは --executable の機能)

※この記事はJSX Advent Calendar 2013の一部です。

アドベントカレンダーの目的は、関連情報を増やすこと。だったら公式ドキュメントを増やせばいいじゃん!!!!! もしかしてオレ天才ちゃう?

ということで今日はCompiler Reference - Documents - JSXを書きました。おなかすいた

Test::Mocha::PhantomJSを書いた

Test::Mocha::PhantomJSというPerlモジュールをリリースしました。

一言でいうと、Perlで書いたサーバサイドロジックを、PhantomJS上で動くMochaのテストコードで検証するためのモジュールです。

具体的な手順としては、

  1. t/ 以下に次のようなテストコードを書いて
  2. Mochaのテストが含まれるHTMLを返すようにする

の2点さえやってしまえば、あとはmake testするだけで、PhantomJSのヘッドレスウェブブラウザ上でテストが動いて集計されます。

use Test::Mocha::PhantomJS;

test_mocha_phantomjs(
    server => sub {
        my $port = shift;
        # サーバを localhost:$port で起動
        ...
    }
);

はい。End-to-end テストを書く際に便利ですね。

実際のテストコードをどういう感じで書けばいいかは、GitHubのレポジトリのt/以下をご覧ください。

JSXでプログラムを書く上で参考になるドキュメント

※この記事はJSX Advent Calendar 2013の一部です。

JSXでプログラムを書く上で参考になるドキュメントといえば、なんといっても公式ドキュメントです。

量は少ないですが、チュートリアルや型に関するリファレンスはhttp://jsx.github.io/doc.htmlにあります。プロファイラの説明等もあります。

また、見落としがちですが、組み込みAPIの公式ドキュメントが、上記サイト内のhttp://jsx.github.io/doc/stdlibref.htmlにあります。組み込みオブジェクトについて「どんなメソッドがあるのかわからない」と思った際は、こちらを見るといいでしょう。

これらを見ても解決しない場合は、Twitter等で聞くと開発者が巡回して回答しますって @__gfx__ が言ってました。かっこいいですね。

コンストラクタから他のコンストラクタを呼び出す方法

※この記事はJSX Advent Calendar 2013の一部です。

JSXでは「this(...)」と書くことで、あるコンストラクタから別のコンストラクタを呼び出すことができます。下の例はJSXのコンパイラからの抜粋。

class NodePlatform extends Platform {

    function constructor () {
         this(node.path.dirname(node.__dirname));    // <----- ココ
    }

    function constructor (root : string) {
        this._root = Util.resolvePath(root);
    }

また、親クラス(あるいは Interface あるいは Mixin)のコンストラクタを呼び出す際には、「super(...)」あるいは「親クラス名(...)」とします。

Javaと一緒ですね!

JavaScriptバインディングの書き方

※この記事はJSX Advent Calendar 2013の一部です。

JSXでは、JavaScriptで定義されているオブジェクトをJSXのクラスとして簡単に取り込めるようになっています。やりかたは簡単。「native」属性を付与してクラス定義を書くだけです。たとえばJavaScriptの組み込みオブジェクトであるRegExpバインディングは、以下のように定義されています。

native final class RegExp {

        function constructor(pattern :string, flags :string);
        function constructor(pattern :string);
        function constructor(pattern :RegExp);

        function exec(str :string) :string[];

        function test(str :string) :boolean;

        override function toString() :string;

        __readonly__ var source :string;
        __readonly__ var global :boolean;
        __readonly__ var ignoreCase :boolean;
        __readonly__ var multiline :boolean;
        __readonly__ var lastIndex :int;

}

native属性以外に注目すべきところとして、プロパティに__readonly__属性を付与して読み込みのみ可能としている点*1があげられるかと思います。

また、node.js等でrequireを使ってロードするオブジェクトについては、以下のようにすることで、対応する表現を定義することができます*2

native class url {
        static function parse(urlStr : string) : Url;
        static function format(url : Url) : string;
        static function format(urlStr : string) : string;

        static function resolve(source : Url,    relative : Url)    : string;
        static function resolve(source : Url,    relative : string) : string;
        static function resolve(source : string, relative : Url)    : string;
        static function resolve(source : string, relative : string) : string;
} = "require('url')";

*1:これはnativeクラス専用の拡張です

*2:GitHub - jsx/nodejs.jsx: (to be) the node.js binding for JSXより抜粋

オレオレ認証局の適切な運用とName Constraints

オレオレ認証局が忌避されるべきものとされてきた理由は、X.509 PKIが保証する安全性は、最も信頼性が低い認証局(trusted root)のそれに等しいからです。

しかし、X.509 v3以降ではName Constraintsが導入され、「特定のドメインに対してのみ証明書を発行可能な認証局」を定義できるようになっており、同constraintをcritical key usage extension*1として宣言したルート証明書を安全な経路で配布、インストールすることができれば、上記のようなX.509 PKIの系全体に対する影響は発生しないことになります*2

ここで問題になるのは、どの程度のウェブブラウザがName Constraintsに対応しているのか、という点になりますがhttps://news.ycombinator.com/item?id=5194103によると、Chrome, IE*3, Firefoxは対応済だがSafariは未対応*4とのことです。

以上です。誰か実際に試験してくれるといいんじゃないかなと思いました。

*1:実装にとって拡張が未知である場合は証明書を信頼しないと宣言する機能

*2:本稿では、ドメイン内へのhttpsアクセスの信頼性を規定するのは、そのドメインの管理者の裁量である、という前提をおいています

*3:実際はVista以降なら対応とかじゃないかな

*4:つまり、上記ルート証明書を使うサーバとは交信できない

個人サーバのファイアウォールを活かしつつ、どこからでもログインする方法 (CGI編)

以前、

いつでもどこからでもサーバにログインしたくなるときってありますよね。かといって、サーバの sshd への接続を全世界から可能にしておくというのは、たとえパスワード認証を無効化していても避けたいところ

Dynamic DNS を使って SSH アクセスを制限する方法 - kazuhoのメモ置き場

ということでDynamic DNSを使う方法でやってきてたんだけど、いろいろ不便があったので、HTTPベースに変えた。具体的に言うと、

#! /usr/bin/perl

use strict;
use warnings;

my $TARGET_FILE = '/etc/hosts.allow.d/www/update_addr_cgi';

print "Content-Type: text/plain\r\n\r\n";

my $remote_addr = $ENV{REMOTE_ADDR}
    or die "no remote addr\n";

open my $fh, '>', $TARGET_FILE
    or die "failed to open $TARGET_FILE:$!";
print $fh "$remote_addr\n";
close $fh;

print "address updated to:$remote_addr\n";

のような CGI を個人サーバの秘密の場所*1に設置して、/etc/hosts.allowに

ssh: /etc/hosts.allow.d/www/update_addr_cgi

と書いた感じ*2(実際は他のサービスもマッピングしてる)。

サーバプロセスをファイアウォール(というかtcpwrapper)で保護することでインターネットから攻撃される可能性を下げつつ、CGIを一発たたいたらどこからでも作業できるようになるので、わりと便利。

*1:Basic認証等をセットしてもいいが、このCGIの目的はssh等による認証の前のノッキングだと考えるならば必ずしも必須ではない

*2:/etc/hosts.allow.d/wwwはCGIの実行権限で書き込み可能にしておく