ブログ  前の記事  次の記事  2007-09-27 

たけまる / Catalyst::Controller::Atompub - Media Resource


2007-09-27

_ Catalyst::Controller::Atompub - Media Resource [perl][atompub]

Atompub モジュールの使い方シリーズです.

Catalyst::Controller::Atompub は Catalyst の拡張モジュールで,
Atompub (Atom Publishing Protocol) サーバを簡単に実装することがで
きます.

# クライアントは Atompub モジュール [2007-08-12-1] にあります.

さて,Entry Resource (いわゆる Atom XML のこと) を扱うサーバについ
ては [2007-09-13-1] で説明しました.今回は,Media Resource (バイナ
リデータ) のについて説明します.ブログシステムで例えるなら,Entry
Resource はブログのテキストであり,Media Resource は写真や動画にな
ります.

# Media Resource とは? という方は,こちら↓をどうぞ
# "Atom Publishing Protocol を勉強するには" [2007-09-20-1]

Media Resource の扱いは少しややこしいです.というのは,リソース本
体だけではなく,リソースのメタ情報を記述する Media Link Entry も同
時に扱わなければならないからです.

Media Resource を扱うサンプルコードは,Catalyst::Controller::Atompub
の samples/MyBlog にあります.今回の説明も,このサンプルをベースに
しています.

まず,Media Resource を扱う Controller を作成します.
$ ./script/myblog_create.pl controller MediaCollection Atompub::Collection

すると,lib/MyBlog/Controller/MediaCollection.pm が作成されるので,
このファイルにリソースを CRUD するコードを実装していきます.ここで
は,作成 (Create) と取得 (Read) をみていきます.

まず,リソースを作成するコードです.
sub create_resource :Atompub(create) {
    my ( $self, $c ) = @_;

    # 新たなリソースの URI (親クラスで自動生成)
    my $entry_uri = $self->media_link_entry->uri;
    my $media_uri = $self->media_resource->uri;

    # Entry の作成時刻 (app:edited, 親クラスで自動生成)
    # SQLite では UNIX time 形式に変換する
    my $edited = $self->edited->epoch;

    # POST された Media Resource (バイナリ)
    my $media = $self->media_resource->body;

    # Media Resource のメディアタイプ (ex. image/jpeg)
    my $media_type = $self->media_resource->type;

    # Media Link Entry (XML::Atom::Entry, 親クラスで自動生成)
    my $entry = $self->entry_resource->body;

    # 必要に応じて,$media, $entry を修正...

    # Media Resource と Media Link Entry を DB に格納
    $c->model( $MODEL )->create( {
	edited     => $edited,
	entry_uri  => $entry_uri,
	entry_body => $entry->as_xml,
	media_uri  => $media_uri,
	media_body => MIME::Base64::encode( $media ), # ASCII 変換
	media_type => $media_type,
    } );

    # 成功したら true を返す
    return 1;
}

基本的には,親クラスで前処理されたリソースを,DB に格納するだけで
OK です.Media Resource を格納するときは,メディアタイプを忘れない
ようにしてください (リソースを返すときに必要になります).

ここでは,簡単のために Media Resource を Base64 で ASCII に変換し
ましたが,実際にはファイルとして保存したほうがよいかもしれません.
キャッシュとして素早く返せるからです.

リソースを取得するコードです.
sub get_resource :Atompub(read) {
    my ( $self, $c ) = @_;

    my $uri = $c->req->uri;

    # DB からリソースを取得
    my $cond = { '-or' => [ { entry_uri => $uri },
			    { media_uri => $uri } ] };

    my $rs = $c->model( $MODEL )->search( $cond )->first;

    # Media Link Entry であれば,
    if ( $rs->entry_uri eq $uri ) {
        # アクセサを使って Entry を設定
	$self->media_link_entry->body( XML::Atom::Entry->new( \$rs->entry_body ) );
    }
    # Media Resource であれば,
    else {
        # アクセサを使って Media Resource を設定 (メディアタイプを忘れないこと)
	$self->media_resource->body( MIME::Base64::decode( $rs->media_body ) );
	$self->media_resource->type( $rs->media_type );
    }

    # 成功したら true を返す
    return 1;
}

URI の指すリソースが Media Resource なのか Media Link Entry なのか
によって,処理が異なります.URI からリソース種を判定してもよいので
すが,ここでは OR を使って区別せずに検索しています.そして,検索後
に URI を比較してリソース種を判定しています.

最後に,取得したリソースをアクセサに設定してください.あとの処理は
親クラスがやってくれます.なお,Media Resource のときは,メディア
タイプを忘れないでください.


このあと,リソースの更新 (Update) と削除 (Delete) を実装する必要が
あります.また,列挙 (Feed の取得) も実装します.Feed には Media
Link Entry のみを含めてください.これらの処理については,
C::C::Atompub のソースコードに含まれるサンプルコード (samples/MyBlog)
を参考にすれば難しくないと思います.


以上,リソースの作成と取得についてみてきました.このように,Media
Resource を扱うときには,Media Link Entry の存在に気をつけて実装し
てください.


コレクションは,デフォルトでは Entry Resource しか受け付けません.
Media Resource (画像) を受け付けるように,myblog.yaml でコレクショ
ンを設定します.accept: 以下に,受け付けるデータのメディアタイプを
列挙してください.

myblog.yaml
Controller::MediaCollection:
    collection:
        title: Photo
        accept:
          - image/png
          - image/jpeg
          - image/gif


以上で,Media Resource を扱う AtomPub サーバが完成します.

一言メッセージをこっそり送信できます (非公開)
 今年の西暦→
Referrer (Inside): [2007-10-22-1]