AtomPubって何だ

参考資料

AtomPubに興味が出てきました.ってことで,色々調べてみてるんですがどうも要領を得ません.RFCになったばかりでI-D時代の説明や実装が多いからなのかな,と思ってるんですが実際のところは調査不足かと.とりあえず,読んでおかないといけなさそうな資料をまとめました.

で,これらをもとにちょっと試してみて,うまく行ったところをメモしてみました.

APP Test Siteを試してみる

Atom Publishing Protoclを試す cURLを読んで,cURLを使えばAtomPubを試せるとわかったので,APP Test Site Specificationで試してみました.まず,記事通りにサービスドキュメントを取得しました.

curl -s "http://bitworking.org/projects/apptestsite/app.cgi/service/;service_document"

そうすると次のデータが返ってきます.

<?xml version="1.0" encoding="utf-8"?>
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
  <workspace>
    <atom:title>AtomPub Test Site</atom:title>
      ...
      <collection href="media/">
           <atom:title>media</atom:title>
        <accept>*/*</accept>
         <categories fixed="yes" />
      </collection>
      ...
  </workspace>
</service>

これからわかるのはworkspace titleが"AtomPub Test Site"で,"media collection URI"が"http://bitworking.org/projects/apptestsite/app.cgi/service/media/"ということです.次に,curlを実行するディレクトリに"catalyst_logo.png"を用意してからmedia collectionに画像をuploadしました.

curl -s -H Content-Type:image/png --data-binary @catalyst_logo.png \
  -X POST "http://bitworking.org/projects/apptestsite/app.cgi/service/media/"

このコマンドを実行した結果返ってくるのが次のxml

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app">
     <title />
     <link href="http://bitworking.org/news/460/" />
     <id>http://bitworking.org/news/460/</id>
     <author>
        <name>Joe Gregorio</name>
     </author>
     <updated>2008-02-10T23:39:12.614612-04:00</updated>
     <app:edited>2008-02-10T23:39:12.614612-04:00</app:edited>
     <summary type="xhtml">
          <div xmlns="http://www.w3.org/1999/xhtml" />
     </summary>
     <link href="." rel="edit" />
     <link href=";media" rel="edit-media" />
     <content src="http://bitworking.org/images/dev/460-.png" type="image/png" />
</entry>

これからわかるのが,

ということです.でもこれはなんだか変です.よく見ると,

     <link href="." rel="edit" />
     <link href=";media" rel="edit-media" />

となっていますが,元の記事から類推すると,

     <link href="460/" rel="edit" />
     <link href="460/;media" rel="edit-media" />

のようになるはずです.この場合,entry resourceとmedia resourceは以下のようになるはずです.

もう一回GETしてみたら

curl -s "http://bitworking.org/projects/apptestsite/app.cgi/service/media"

確かにそうなっているみたいです.何が起こっているんでしょうか.追記:たけまるさんに,APP Test Siteのバグだと教えてもらいました.バグ報告も上がってるんだけど,スルーされてるらしい

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app">
   <title type="text">BitWorking | Joe Gregorio</title>
   <link href="http://bitworking.org/projects/apptestsite/app.cgi/service/media" rel="self" />
   <link href="http://bitworking.org/" rel="alternate" />
   <link href="?page=1" rel="next" />
   <icon>http://bitworking.org/favicon.ico</icon>
   <updated>2008-02-10T23:39:12.614612-04:00</updated>
   <author>
      <name>Joe Gregorio</name>
   </author>
   <id>http://bitworking.org/</id>
   <entry>
     <title />
     <link href="http://bitworking.org/news/460/" />
     <link href="460/" rel="edit" />
     <link href="460/;media" rel="edit-media" />
     <id>http://bitworking.org/news/460/</id>
     <updated>2008-02-10T23:39:12.614612-04:00</updated>
     <app:edited>2008-02-10T23:39:12.614612-04:00</app:edited>
     <summary type="xhtml">
          <div xmlns="http://www.w3.org/1999/xhtml" />
     </summary>
         <link href="460/;media" rel="edit-media" />
         <content src="460/;media" type="image/png" />
   </entry>
   ...
</feed>

資料によると,Atomエントリを更新するには"entry resource"に"PUT"を実行,uploadした画像を変更するには"media resource"に"PUT"を実行,Atomエントリを削除するには"DELETE"を実行して,削除できたかどうかを確認するには"collection uri"をGETすることになります.というわけで,画像を変更してみました.

curl -s -H Content-Type:image/png --data-binary @ape_logo.png \
  -X PUT "http://bitworking.org/projects/apptestsite/app.cgi/service/media/460/;media"

何の出力もなく,"http://bitworking.org/images/dev/460-.png"の画像が変わっていました.If-Match ヘッダを付ける必要があるのかと思ったんだけど,そこら辺がちょっと謎な点です.で,実際に削除するにはどうすればいいのかと思ってやってみました.

curl -s -X DELETE "http://bitworking.org/projects/apptestsite/app.cgi/service/media/460/;media"

画像だけ消せるかどうかをまず試してみると,

<h1>That action is not allowed on this resource.</h1>

ということで失敗.ということで,エントリ全部を削除してみると,

curl -s -X DELETE "http://bitworking.org/projects/apptestsite/app.cgi/service/media/460/"

成功です."http://bitworking.org/images/dev/460-.png"へのアクセスもできなくなりました.

Catalyst::Controller::Atompubで試してみる

たけまる / Catalyst::Controller::Atompub リリースを読んで,Catalyst::Controller::Atompubを使って作ったMyAtomをテーゲットにしてcURLを使ってみました.

curl -s "http://localhost:3000/myservice"

ここでもサービスドキュメントを取得しています.これで返ってくるのはこんなデータ.

<?xml vrsion="1.0" encoding="utf-8"?>
<service xmlns="http://www.w3.org/2007/app">
  <workspace>
    <atom:title xmlns:atom="http://www.w3.org/2005/Atom">MyAtom</atom:title>
    <collection href="http://localhost:3000/mycollection">
      <atom:title xmlns:atom="http://www.w3.org/2005/Atom">MyCollection</atom:title>
    </collection>
  </workspace>
</service>

これから"collection url"が"http://localhost:3000/mycollection"だと言う事がわかりました.

curl -s -H Content-Type:image/png --data-binary @catalyst_logo.png \
  -X POST "http://localhost:3000/mycollection"

で,こちらも同様に画像をuploadしようとしてみると,

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
<link rel="related" href="http://localhost:3000/mycollection"/>
<updated>2008-02-11T17:47:42+09:00</updated>
<title>415 Unsupported media type: image/png</title>
<content type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">415 Unsupported media type: image/png</div>
</content>
</entry>

失敗しました.どうやらxmlしかuploadできないようです.たけまる / Perl - Atompub 0.0.1 リリースを見るとXML::Atom::Entryモジュールを使えば必要なxmlを用意できるようです.

perl -MXML::Atom::Entry -le '$e = XML::Atom::Entry->new; \
  $e->title("New Entry"); $e->content("Content of my entry"); print $e->as_xml'

これを実行してみてできるxmlファイルはこんな感じ.

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://purl.org/atom/ns#">
  <title>New Entry</title>
  <content mode="xml">
    <div xmlns="http://www.w3.org/1999/xhtml">Content of my entry</div>
  </content>
</entry>

ここで注意しないといけないのは"Content-Type".curlがデフォルトで使っている"Content-Type"ではuploadできないので,明示的に"application/atom+xml"と指定する必要があります.元々フォームデータをuploadするためのツールでしょうからね.

curl -s -H Content-Type:application/atom+xml \
  --data-binary @-  -X POST "http://localhost:3000/mycollection"

ちなみに,"--data-binary @-"となっているのはvim上で実行しているからです.上のxmlファイルを"visual mode"で指定(vで開始位置指定,hjklで移動,:で確定)して外部コマンド呼び出しをしています.

:'<,'>! curl -s -H ...

こんな感じ.で,返ってきたxmlはこうなります.

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://purl.org/atom/ns#">
  <title>New Entry</title>
  <content mode="xml">
    <div xmlns="http://www.w3.org/1999/xhtml">Content of my entry</div>
  </content>
  <app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-11T19:10:36+09:00</app:edited>
  <modified>2008-02-11T19:10:36+09:00</modified>
  <id>http://localhost:3000/mycollection/20080211-191036-985610.atom</id>
  <link xmlns="http://www.w3.org/2005/Atom" rel="edit"
    href="http://localhost:3000/mycollection/20080211-191036-985610.atom"/>
</entry>

この場合の"entry resource"はサーバが任意に指定しています(mycollection/20080211-191036-985610.atom)が,Slugを使うと作成するエントリのURIを指定することができます.

curl -s -H Content-Type:application/atom+xml -H Slug:new-entry \
  --data-binary @-  -X POST "http://localhost:3000/mycollection"

Slugはヘッダで指定します.ここで指定したデータを実際に使うかどうかはサーバ実装に依存します.これに対して返ってくるxmlは以下のようになります.

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://purl.org/atom/ns#">
  <title>New Entry</title>
  <content mode="xml">
    <div xmlns="http://www.w3.org/1999/xhtml">Content of my entry</div>
  </content>
  <app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-11T20:00:12+09:00</app:edited>
  <modified>2008-02-11T20:00:12+09:00</modified>
  <id>http://localhost:3000/mycollection/new-entry.atom</id>
  <link xmlns="http://www.w3.org/2005/Atom" rel="edit"
    href="http://localhost:3000/mycollection/new-entry.atom"/>
</entry>

この場合の"entry resource"はサーバに指定できています(mycollection/new-entry.atom).で今回の日記の最後がuploadしたデータの編集.うまく行っていません.たぶんやり方としては,

curl -s -H Content-Type:application/atom+xml --data-binary @- \
  -X PUT "http://localhost:3000/mycollection/new-entry.atom"

というコマンドを使って

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <content type="xhtml">
    <div xmlns="http://www.w3.org/1999/xhtml">Content of my entry.</div>
  </content>
  <app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-11T22:26:40+09:00</app:edited>
  <updated>2008-02-11T22:26:40+09:00</updated>
  <id>http://localhost:3000/mycollection/new-entry.atom</id>
  <link rel="edit" href="http://localhost:3000/mycollection/new-entry.atom"/>
  <title>New Entry ver.2</title>
</entry>

というxmlを送ればいいようなんですが,なんでこのxmlを送ればいいのかがわかりません.追記:変更する箇所,この場合だとtitleタグの中身かcontentタグの中身を書き換えて送ればいいってことに,この日記を書いた後気がつきました.edited, updatedの中身はサーバが設定しているから,クライアント側で考えて時間を設定しなくてもよいみたい.

続く

たぶん…