2010-12-28

[facebook] プロフィールのメールアドレスを非公開にする

アカウント保護のため(と称するおせっかい機能に促されて)Facebookに複数のメールアドレスを登録した場合、デフォルトのではコンタクト情報を共有する相手に全てのメールアドレスが表示されます。

友だちにも見せたくないメールアドレスがある場合、自分のプロフィールを編集し、メールアドレスのプライバシー設定を「自分のみ」とします。

耳寄り情報
Facebookのプロフィールに追加したメールアドレスは必ず(なんと非公開設定でも!)メールアドレスから検索可能になり、アドレス帳インポート機能などにより一括検索できます。また、検索窓により個別に発見することもできます。この機能を無効化する設定はなく、メールアドレスを登録しないでおくしかありません。ご注意ください。

2012/3/15 追記
プライバシー設定 > つながりの設定 よりメールアドレスから検索する機能を制限できるようになったようです。
Who can look you up using your email address or phone number?
この項目を [友達のみ] に設定すれば実質的に機能しなくなるようです。

2010-12-19

[facebook] コメントが追加されましたメール通知を止める

Facebook の作りこみは正直にすごいと思いますが、ついうっかりどこかにコメントしただけで、延々とコメントが追加されました通知がメールで届くのがうざったい所でした。

設定画面は、アカウント → アカウント設定 → お知らせ
設定項目が大量で読む気になれないけれど、結局のところ以下の項目のチェックボックスを外せば良いです。
写真にコメントが追加されたとき
アルバムにコメントが追加されたとき
ノートにコメントが追加されたとき
リンクにコメントが追加されたとき
動画にコメントが追加されたとき
ウォールの記事にコメントが追加されたとき
この設定は設定を変更した後に行ったコメントから有効になるようです。また、メールが来なくなるだけで、通知自体が消滅するわけではないので、Facebook 内の地球印のお知らせには影響がありません。

自分の投稿にコメントが付いた場合のメール通知にはまた別の設定項目があり、個別に設定できます。他にも Tips として、「投稿のフォローをやめる」を押しておくことで、投稿主には知られることなく、個別の投稿に関するコメント追加通知を全く来ないようにできます。

現在 (2012.2) うちでは Chrome の拡張 Facebook Notifications を入れたことでメール通知は不要となったので、ほとんど全てのメール通知を無効化して快適に使っています。

2010-12-14

[gae] 静的ファイルの配信でcharsetを指定するには

クラウド時代を実感させてくれる Google の素晴らしいサービス Google App Engine でアプリを作る際の設定について。

app.yaml で static_files を指定してファイルを配信する際に、レスポンスヘッダ Content-Type で charset を明示したい場合は、mime_type プロパティに 'text/html; charset=utf-8' という感じの値を入れると良いようです。

allow-any-origin.appspot.com で使っている app.yaml の断片:

handlers:
- url: /
  static_files: static/index.html
  mime_type: text/html; charset=utf-8
  upload: static/index\.html

2010-11-21

[Node.js] /dev/urandom を延々と出力する HTTP サーバー

Node.js の本体の API にある、http.createServer を使って、ファイルの内容 (Readable Stream) を Class: http.ServerResponse (Writable Stream) に対して随時書き込んで、/dev/urandom から湧き出てくるランダムバイナリをストリーミング出力するとても有意義なサーバーを作ってみました。

以下のコードを node hogehoge.js という感じで実行して、適当に http://localhost:10001/ みたいなアドレスに対して HTTP でアクセスすると、バイナリデータを延々と返してくれます。

ポイント
  • /dev/urandom を、ファイルの内容を Readable Stream で取れるように、fs.createReadStream で開く。
  • HTTP レスポンスオブジェクト: resに対して、res.write で書き込みしていって、送信バッファがいっぱいになった場合、書き込めるようになると発生するイベント: drain まで書き込まずに待つ。

var fs = require('fs'),
    http = require('http'),
    util = require('util'),
    PORT = 10001;

http.createServer(function (req, res) {
    res.writeHead(200, {
        'Content-Type': 'application/octed-stream',
    });

    var stream = fs.createReadStream('/dev/urandom');

    stream.on('data', function (data) {
        console.log('on data: ' + data.length);
        var flushed = res.write(data);

        if (!flushed) {
            console.log("send buffer looks full");
            stream.pause();
        }
    });

    res.on('drain', function () {
        console.log("on drain");
        stream.resume();
    });
}).listen(PORT);

続編に続く
hidekiy blog: [node.js] 続 /dev/urandom を延々と出力する HTTP サーバー

関連記事
urandom streaming on twiggy - tokuhirom's blog.

2010-11-09

[perl] PayPal の ExpressCheckout を使ってみる

PerlからPayPalのExpressCheckoutを使う方法についての記事です。これからはPayPalの時代が来るという記事を読んで自分でもやってみたくなったので、Sandboxアカウントで実際にやってみました。まだ実際にお金を動かしたりはしていないので、至らない点が多々あると思います。

ExpressCheckoutとは、決済手続きの途中でPayPalにリダイレクトして、その後こちら側のサイトに戻ってから最終決断のボタンを押してもらう方式で、決済完了の情報がきちんと伝わらないみたいな中途半端な状態にはならない方式です。

モジュールの選定
PayPal APIは二種類の形式で使うことができて、NVP(Name Value Pair)とSOAPです。

このうち、SOAPを使う、Business::PayPal::API はPayPal APIの更新に追従できていないので良くないです。SOAPを直接いじろうとして、SOAP::Lite を検討しましたが、面倒な感じなのでやめました。

a=b&c=d..のような形式でフォーマットされている素朴極まりないNVPを利用するライブラリ、Business::PayPal::NVP がAPIが更新されても利用できるので良いと思います。

Sandboxアカウントの取得
こちら PayPal Sandbox で誰でも取得できます。Sandboxの中ではお金が使い放題です。

実際のコード

use Business::PayPal::NVP;

# branchでsandbox, 本番サーバーを切り替える
my $paypal = Business::PayPal::NVP->new(
    test => {
        user    => 'info_1287414775_biz_api1.hidekiy.com',
        pwd => 'xxxxxxxxxxx',
        sig => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
        version => 65, # 新しいのをたのむ
    },
    branch => 'test',
);

# 請求金額が確定していて、PayPalでの支払いを希望しているとする。
my %res = $paypal->SetExpressCheckout(
    PAYMENTREQUEST_0_PAYMENTACTION => 'Sale',
    PAYMENTREQUEST_0_AMT => '1000.00',
    PAYMENTREQUEST_0_CURRENCYCODE => 'JPY',
    LOCALECODE => 'JP',             # Sandboxでは効いてないけど、本番ではたぶんOK
    LANDINGPAGE => 'Billing', # ログインだけのページになると寂しいのでBilling
    SOLUTIONTYPE => 'Sole',     # PayPalアカウントを作る必要はなしとする
    RETURNURL => 'http://example.com/return',
    CANCELURL => 'http://example.com/cancel',
);

# $res{ACK}を確認後、
# https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=$res{TOKEN}
# にリダイレクトして、支払い手続きをしてもらう。

# http://example.com/returnにPayerIDとtokenを付けて戻ってくる
# 最終決断をしてもらったあと、以下を実行する
my %res = $paypal->DoExpressCheckoutPayment(
    PAYMENTREQUEST_0_PAYMENTACTION => 'Sale',
    PAYMENTREQUEST_0_AMT => '1000.00',
    PAYMENTREQUEST_0_CURRENCYCODE => 'JPY',
    TOKEN => scalar $req->param('token'),
    PAYERID => scalar $req->param('PayerID'),
);
# $res{ACK}を確認して完了

参考資料
Introducing Express Checkout
SetExpressCheckout API Operation
DoExpressCheckoutPayment API Operation

2010-11-08

[linux] SSH経由でrootでrsyncしてサーバーの引っ越し

結論
rootでrsyncしようとsudo rsyncすると、SSHのAgent Forwardingに必要な環境変数をsudoがセキュリティ対策で削除して困ったが、sudo -E rsync とすると上手くいく。

蛇足
2HOSTの方針で、St.Louisのデータセンターが閉鎖されて、そのついでにセキュリティ問題発覚以後開発元がおかしなことになっている HyperVM から SolusVM への移行をすすめるので、新しいVPSノードを再設定できる人は、SolusVM管理下の新しいVPSノードを作るから各自移行してね、というメールが来たので、提案された通りにすることにしました。

そこで、古いサーバーのファイルを持っていくのに、scpでちまちまコピーするのも良いけどファイル数が多いと遅いので、rootでrsyncしてコピーすると良いのではないかと思って、やってみました。

しかし普通にsudo rsyncとすると、エージェントフォワーディングによる公開鍵認証にならないので、なぜなのか悩みましたが、sudoのセキュリティ対策によるものと分かりました。

CentOSでyumで入るsudoの/etc/sudoersはとても安全側に振ってあるみたいで、環境変数は指定されたものは全部削除されてしまい、SSH_AUTH_SOCKが削除されてAgent Forwardingが働きません。参考:sudo env と叩く

sudoのmanページを読むと、その環境変数を削除する機能を一時的に無効にするオプション -E (preserve environment) を追加したら、無事公開鍵により認証され、root権限でのrsyncができました。

実際に使ったコマンドは、
sudo -E rsync --archive --verbose example.com:/etc/ ./example.com-etc
のような感じで、example.com の /etc がローカルの ./example.com-etc に保存されます。

2010-11-06

[perl] Coro::Specific の使いどころについて

Coro とは、AnyEventJSON::XS で有名な Marc Lehmann 作の、Perlにおいて、協調型スレッド(簡単な方のスレッド) を実現して、背後で AnyEvent が仕事をしながら、プログラマ側からは今までのブロッキング方式と思って書けるようにするためのモジュールです。

本体に同梱されている Coro::Specific というモジュールを使うと、今まで fork システムコールで多重化していた Net::Server のような、サーバーのインスタンスが1つで、それぞれのクライアントがプロパティをちょこっと書き換える型のサーバーを Coro 化するのに役に立ちます。

実際に、Coro における PSGI サーバー実装である Corona で使っている、Net::Server::Coro では、以下のようにして特定のプロパティをコルーチンごとに別々に設定できるようにしています。

# Net::Server::Coro::post_bind_hook 付近より抜粋
# $self はサーバーのインスタンス

foreach my $key (qw(client sockaddr sockport peeraddr peerport peerhost)) {
    tie $self->{server}{$key}, Coro::Specific::;
}

2010-10-30

[perl] AnyEvent::Twitter::Stream で自動再接続処理

Perl関係のツイートをリツイートするうざいボット @AE_PerlIsm を動かして得られた知見についての記事です。

キーワードを含んだツイートは、Twitter Streaming API を AnyEvent からいい感じで取得できる AnyEvent::Twitter::Stream で取得しているのですが、この接続が12~24時間に1回くらい切られるようなので、再接続処理が必要だと思います。

そのコードは以下のような感じでやっています。

注意点は、
接続状態から切れた時は wait なしで再接続する。
接続成功は、30秒おきに届く on_keepalive で判明する場合もある。
リトライウエイトで sleep を使うとイベントループが止まって良くないので、AE::timer を使う。

use AnyEvent::Twitter::Stream;

while (1) {
    my $done_cv = AE::cv;
    my $connected;
    my $streamer = AnyEvent::Twitter::Stream->new(
        method => 'filter',
        track => 'perl',
        # 認証は適当にやっとく

        timeout => 45,
        on_tweet => sub {
            $connected = 1 unless $connected;
            # 新しいツイートを受信したときの処理
        },
        on_keepalive => sub {
            $connected = 1 unless $connected;
        },
        on_error => sub {
            $done_cv->send;
        },
    );
    $done_cv->recv;
    undef $streamer;

    my $wait = $connected ? 0 : 2; #とりあえず2秒まってやる

    my $wait_cv = AE::cv;
    my $wait_t = AE::timer $wait, 0, $wait_cv;
    $wait_cv->recv;
}

2012/1/3 追記
現在の AE_PerlIsm は DotCloud にて、supervisord に依存して、接続が切れたら die で異常終了することで再接続するようにしてみました。再接続回数などの情報を保存して受け継ぐ必要がありますが、この方が簡単に書けると思います。

2010-10-29

[perl] Image::Imlib2 でファイルハンドルに書き込む

mixi で採用されている らしい Image::Imlib2 ですが、出力の方法がファイルに対する書き込みしかなかったので、hidekiy.com の背景画像を動的に生成するのに便利な方法を考えてみました。

IO::File->new_tmpfileで一時ファイル (tmpfile, tempfile) を作って、そのハンドル $fh のファイルディスクリプタに対して save で保存します。$fh のカーソルは先頭のままなので、$fh をそのまま PSGI レスポンスの body とかに使えばよいです。さらに変数に入れたいなら Perl6::Slurp みたいな方法で $fh を読めば OK です。

use Image::Imlib2;
use IO::File;

my $img = Image::Imlib2->new(100, 100);
$img->set_color(128, 128, 128, 256);
$img->fill_rectangle(0, 0, $img->width, $img->height);

$img->image_set_format('png');
my $fh = IO::File->new_tmpfile;
$img->save('/dev/fd/' . $fh->fileno);

$fh;

2010-10-28

[perl] Devel::REPL を使う

CPAN モジュール Devel::REPL をインストールすると Perl の対話環境 (インタラクティブシェル, Read-Eval-Print Loop) が re.pl というコマンドで入ります。公式ドキュメントでは、いまいちカスタマイズの仕方が分からないのですが、起動スクリプトで便利なプラグインを読み込むと良いです。

起動時にデフォルトで読み込まれるスクリプトは、こちらを参照 して、$HOME/.re.pl/repl.rc なので、これを作成します。以下は今使ってるものですが、もっと活用できそうです。便利な機能を発見したらまた更新します。

use strict;
no strict 'vars';
use utf8;
use warnings;
use diagnostics;
use Data::Dumper;
binmode STDOUT, ':utf8';

$_REPL->load_plugin($_) for qw(
    Colors
    Completion
    CompletionDriver::Globals
    CompletionDriver::INC
    CompletionDriver::Keywords
    CompletionDriver::LexEnv
    CompletionDriver::Methods
    DDS
    History
    LexEnv
    MultiLine::PPI
    Packages
    ReadLineHistory
);

2010-10-16

XMLHttpRequest Level 2 時代のクロスドメインリクエスト Proxy

XMLHttpRequest Level 2では、XMLHttpRequest が Same Origin Policy を満たさなくても通信できるようにするための仕組みが追加されています。

その仕組みとは、通信相手のサーバーが HTTP レスポンスヘッダ中でクロスドメインアクセスを許可することを示す、Access-Control-Allow-Origin というヘッダを出力するというものです。このヘッダだけ出力した場合は GET リクエストによるクロスドメインアクセスが対象になります。

この拡張された XMLHttpRequest の機能をもっと活用するために、Google App Engine 上で動く GET で取れる範囲でレスポンスヘッダに Access-Control-Allow-Origin: * (すべて許可) をことごとく追加して返す Proxy を開発してみました。

使い方は http://allow-any-origin.appspot.com/http://www.google.co.jp/ のように後ろにくっつけてリクエストするだけです。

デモ

function xhrdemo() {
    var url = document.getElementById("xhrdemo-url").value;
    var req = window.XDomainRequest ? new XDomainRequest() : new XMLHttpRequest();
    req.open("GET", "http://allow-any-origin.appspot.com/" + url, true);
    req.onload = function (event) {
        alert(req.responseText);
        req = null;
    }
    req.send(null);
}



リンク
allow-any-origin.appspot.com
404 Blog Not Found:Ajax - Goodbye, JSONP. Hello, Access-Control-Allow-Origin
NetAgent Official Blog : IE8+jQueryによるクロスドメイン通信とXDomainRequestラッパーの作成 - この Proxy をご紹介いただきました

2010-08-27

[windows] Chrome を Program Files にインストールする

Google Pack で Chrome をインストールすると C:\Program Files に入る。さらに、beta, dev channel を御希望の方は レジストリを変更する方式 でOK

2012/10/30 追記
Google Pack は終了しましたが以下の方法で引き続き全ユーザー用にインストールできます。
Google Chrome を複数のユーザー アカウントにインストールする

2010-04-19

[perl] File::Path::mkpath() に複数のパスを与える

File::Path の mkpath で、複数のディレクトリパスを一気に作ってもらおうとすると困りそうなことについてです。make_path と mkpath はディレクトリパスが複数の場合の扱いに違いがあります。

make_path($dir1, $dir2, $dir3);      # OK
make_path($dir1, $dir2, $dir3, {});  # OK
mkpath($dir1, $dir2, $dir3);         # NG 【なんと!】
mkpath($dir1, $dir2, $dir3, {});     # OK
mkpath([$dir1, $dir2, $dir3]);       # OK

そもそも、複数のパスを指定することを止めれば安心して使えます。

mkpath($_) for ($dir1, $dir2, $dir3);

2010-04-03

[Perl] [CPAN] 球面三角法

地球を球体と仮定した時の、二地点間の方位角や距離を求める場合などに役立つかもしれない、球面三角法についての関数は Math::Trig のGREAT CIRCLE DISTANCES AND DIRECTIONSの辺りにあります。

2010-03-09

[plack] response body を変更する Middleware の試作

Web アプリケーションが見事にコードリファレンス一つに抽象化されている PSGI では、あるアプリケーションに前処理・後処理を追加して、動作をちょっと変更する Middleware という仕組みがあって、それで色々と面白いことができそうなので、試しにくだらないものを作ってみました。

今回作ったのは、実用性皆無ですが、後処理を追加することで、出力をすべて大文字にしてくれる Middleware です。

必要なモジュール: Plack, Twiggy

使い方: plackup -s Twiggy app.psgi で動かして、http://localhost:5000/stream などを見てみる。

package Plack::Middleware::UpperCase;
use strict;
use warnings;
use parent qw(Plack::Middleware);

sub call {
    my ($self, $env) = @_;

    my $res = $self->app->($env);

    return $self->response_cb($res, sub {
        my $res = shift;

        return sub {
            my $body_chunk = shift;

            if (defined $body_chunk) {
                return uc $body_chunk;
            } else {
                return;
            }
        };
    });
}

package main;
use strict;
use warnings;
use AnyEvent;
use Plack::Builder;
use Plack::Response;

builder {
#    enable 'Plack::Middleware::UpperCase';
    enable sub { Plack::Middleware::UpperCase->wrap(@_) };

    mount '/static' => sub {
        my $env = shift;

        my $res = Plack::Response->new(200);
        $res->content_type('text/plain');
        $res->body("static response");

        return $res->finalize;
    };

    mount '/handle' => sub {
        my $env = shift;

        my $res = Plack::Response->new(200);
        $res->content_type('text/plain');

        open my $io, '<', \'body handle';
        $res->body($io);

        return $res->finalize;
    };

    mount '/stream' => sub {
        my $env = shift;

        return sub {
            my ($write) = @_;

            my $writer = $write->([
                200,
                [
                    'Content-Type' => 'text/plain',
                ],
            ]);

            my $count = 0;
            my $t; $t = AE::timer 0, 0.5, sub {
                $writer->write("date:@{[ scalar localtime ]}, count:@{[ $count++ ]}\n");

                if ($count > 10) {
                    undef $t;
                    $writer->close;
                }
            };
        };
    };
};

hiratara さんの記事 PSGI 1.03のMiddlewareを書いてみる を参考にしながら作ってみたのですが、Plack::Component::response_cb の定義をよく見ると、body_filter として返すコードリファレンスの内容は、return undef をすると $res->[2] に無駄な undef が入るので、return () の方を使うこのコードの方がよいと思います。

2010-03-01

[javascript] call と apply のサンプル

JavaScript の関数オブジェクトについている不思議なメソッド、call と apply についての記事です。これを使うと使いたいメソッドを実行時に文字列で指定するような感じの動的メソッド呼び出しが実現できます。

call, apply の第一引数は、呼ばれた先でのthisを指定します。

callとapplyの違いは、引数の与え方です。例: fn.call(context, arg1, arg2, ...); fn.apply(context, [arg1, arg2, ...])

var list = [];
list.push("hoge0");
list["push"].call(list, "hoge1");

var m = "push";
list[m].apply(list, ["hoge2"]);

console.log(list); // output: ["hoge0", "hoge1", "hoge2"]

2010-02-23

貼り付けたコードを実行してくれるペーストビン ideone

このタイプのペーストビンでは、codepad の方が有名ですが、現時点では対応言語が少ないので、JavaScript, Scala, Pascal, Prolog, Erlang, Go など盛り沢山の言語を実行してくれる ideone というのも知ってたら役に立つと思います。

ideone の codepad にない機能として、標準入力をとってそれをいじったりできます。
例: http://ideone.com/sxZN8JM1

2010-01-24

風呂桶一杯の水道水の脱塩素に必要なビタミンCの量

適当に検索すると、お風呂の脱塩素にはビタミンC粉末を1グラムでOKとあるけど、とりあえず自分でも計算してみました。

計算
日本国の法律で決まっている最低限の塩素濃度すなわち次亜塩素酸ナトリウム濃度は、0.1ppmとあり、200Lの水で考えると、次亜塩素酸ナトリウムの比重を気にしないで計算すれば、0.02g また、次亜塩素酸ナトリウムの式量は77.44

ビタミンCすなわちL-アスコルビン酸ナトリウムの式量は、198.11で、1分子で電子3個分還元できるとのことなので、必要なビタミンCの質量は、(0.02 / 77.44) / 3 * 198.11 = 0.017g

考察
高度浄水処理施設のない給水地域は夏場には結構塩素濃度を上げるみたいですが、ビタミンC粉末は意外と安いので、水200LあたりビタミンCを1グラムほど入れておけば、6ppmくらいまで対応出来るようで一安心です。比重が水に近い普通の粉末1グラムは、小さじ1/5杯です。

備考
ビタミンC粉末はあまり地上のお店ではお手頃な価格で売られていない様ですが、楽天市場などで探したら売っています。
また、お湯を張る前に湯船の底にまいておいた方が、湯張中に蒸気になって鼻がつんとするのを防げます。

2010-01-22

Twitter の Streaming API における日時表現の解析について

目的

DateTime が便利なので、DateTime::Format::* で、Streaming API で流れてくる、こういう表記 "Fri Jan 22 13:52:17 +0000 2010" を上手くパースしたい。
この表記方法は、古き良き時代を感じさせるC言語の ctime() に由来するものであるとのこと。日付の表記に関するノート

現状

DateTime::Format::HTTP, DateTime::Format::Mail は失敗。
ただし、+0000をUTCとかGMTに置換すればDateTime::Format::HTTPでOK
DateTime::Format::DateParse は成功。これを使うべき。
DateTime::Format::Strptime で自作しても可 (DIY派専用)

コード


use DateTime::Format::DateParse;
my $dt = DateTime::Format::DateParse->parse_datetime('Fri Jan 22 13:52:17 +0000 2010');

use DateTime::Format::Strptime;
my $formatter = DateTime::Format::Strptime->new(
    pattern => '%a %b %d %T %z %Y',
    locale => 'en_US',
);
my $dt = $formatter->parse_datetime('Fri Jan 22 13:52:17 +0000 2010');

2010-01-16

[php] 1年後まで有効とする Expires ヘッダを出力する

説明

コピペで世の中に出回っているコードはあまり格好良くないので、改良してみました。パフォーマンス的にはイマイチでも、見た目重視ということにしました。

このようなヘッダは、クライアントにコンテンツを積極的にキャッシュさせるため、期限切れまで全く確認のリクエストなしで使われます。サーバーからコンテンツが更新されたことを通知する方法はないのでアドレスを変化させましょう。

コード


header('Expires: ' . gmdate('D, d M Y H:i:s T', strtotime('+1 year')));

出力例

Expires: Sat, 15 Jan 2011 15:02:20 GMT

2010-01-15

jQuery 1.4 の互換性について

この記事について


jQueryチームのみなさん、リリースおめでとうございます。毎日とても役に立っています。

公式サイトを見に行くと、パフォーマンス改善が素晴らしいとありますが、あまりパフォーマンスで困っている人はいないと思うので、一番欲しい情報はversion 1.3から乗り換える際の互換性についてではないでしょうか。

後方互換性を失う変更の一部


$.ajaxで、複数の値を持つパラメータ(data:{a:[1,2,3]} など)のシリアライズ方法の変更。
$() (引数なし) を$(document)と解釈するのを止めた。
addは単なるaddではなく、同じものが複数入らないように、mergeするようになった。
$.ajaxで、dataType無指定の時の自動判断に、Content-Typeを尊重するコードが追加された。

自分が困ったこと


jQuery.ajaxで、dataType無指定の自動判断のまま1.3.2までなんとか動いていたところが、Content-Type: text/javascriptのJSONを受け取っていたため、1.4からIE8でセミコロンがありませんという変なエラーが出るようになった。

対策:dataType: "json"とする。また、Content-Type: application/jsonで吐き出すようにする。詳しくは、ソースコードを"httpData:"で検索

リンク


Backwards-Incompatible Changes
Version 1.4 - jQuery API 新機能と変更点についての公式ドキュメント
14 Days of jQuery リリース記念ブログ。

[perl] AnyEvent::Handle を使ってみて気づいたこと

AnyEvent::Handle を使って困ったことや気づいたことについて。

on_read や push_read していない場合など、read watcher が止まっている時は、クライアント切断時に on_error や on_eof が即座には呼ばれず、push_write した時になる。さらに、push_write しなければ、ずっとエラーを検出できない。対策: あらかじめ手動で start_read しておく。

AnyEvent::Handle 内に独自の wbuf (write buffer), rbuf (read buffer) を持っているので、いったん使い始めたら、途中で使うのをやめる時には注意が必要。

push_shutdown は on_drain を黙って上書きする。on_read と push_read は別々に存在できて、push_read したキューがなくなったら on_read になるのにちょっと困る。内部に read queue のような write queue が存在しないことを理解すれば仕方ないと分かる。

2010-01-10

[windows] 付属の nslookup をもっと活用してみる

現状
Windowsに付属している唯一のDNSトラブルシューティングツールnslookup.exeは、ドキュメントが不足しているせいで、本来あるべき姿に比べてあまりにも活用されていない状況です。

この記事では、いちいちうざったい対話的インターフェースじゃなくて、コマンドラインインターフェイスの方について使用例を書きます。

基本編
8.8.8.8はGoogleの提供するDNSサーバーなので、必要に応じてISPのDNSサーバーや、DNSコンテンツサーバー(権威サーバー)などに読み替えてください。
nslookup example.com
サーバーを指定しなければ、既定のDNSサーバーに問い合わせをする。
nslookup example.com 8.8.8.8
DNSサーバーをGoogle Public DNS: 8.8.8.8に指定する。デフォルトではAレコードを取得。
nslookup -type=ns example.com 8.8.8.8
必要に応じて-typeで指定する。
nslookup -type=mx example.com 8.8.8.8
MXレコードを確認してメールの配信先を確認する。
nslookup -type=soa example.com 8.8.8.8
SOAシリアルできちんと最新版になっているかを確認する。
nslookup -type=txt example.com 8.8.8.8
TXTレコードを引いて迷惑メール対策用のSPF認証レコードなどを調べる。

応用編
nslookup -debug example.com 8.8.8.8
-debugを付けると詳細情報を表示。TTLなどが分かる。一つ目のGot answerは関係のない逆引きクエリについてなので注意。
nslookup -timeout=10 -type=txt porttest.dns-oarc.net
DNS-OARCのソースポートのランダム性チェックは標準のタイムアウト2秒だと間に合わないので少し延長する。
nslookup -type=ns example.com a.root-servers.net
nslookup -type=ns example.com a.gtld-servers.net
Rootサーバーから手動で再帰的問い合わせをして、委譲状況を確認する。
nslookup -type=txt twitter.wp.dg.cx
WikipediaのDNSインターフェース(笑)で、"twitter" について調べる。

備考
-typeは-qでもOK