Hatena Blog Tags

はてなフォトライフAtomAPI

(はてな)
はてなふぉとらいふあとむえーぴー


このページは古い情報を掲載しています

このページの情報は更新されていません。新しい情報は「はてなフォトライフAtomAPI - Hatena Developer Center」に移転しました。

本ドキュメントに関する注意事項

本ドキュメントははてなフォトライフにおける AtomAPI 実装を解説するものです。主にはてなスタッフがその作成と更新を行っています。

Atomプロジェクトが定めるAtomAPI仕様 http://www.ietf.org/html.charters/atompub-charter.html (英語)は現時点でドラフト段階です。それに伴い本ドキュメントおよびはてなフォトライフの AtomAPI 実装は変更される可能性があります。

変更履歴

AtomAPI とは

AtomAPI はウェブリソースを出版、編集するためのアプリケーション・プロトコル仕様です。はてなフォトライフのAtomAPIを利用することで、開発者ははてなフォトライフに写真を参照、投稿、編集、削除したりを行うオリジナルのアプリケーションを作成することができます。

AtomAPIについて詳しくは http://www.ietf.org/html.charters/atompub-charter.html (英語)などを参照してください。

はてなフォトライフAtomAPI はオリジナルのアプリケーションからはてなフォトライフを操作するためのインターフェースです。はてなフォトライフAtomAPIを利用することで、HTMLを解析してパラメーターを組み立てPOSTするといった、いわゆるHTMLスクレイピングのような手法を行うことなしに、専用のAPIインタフェースを使ってアプリケーションを実装することができます。

はてなフォトライフにおけるAtomAPI実装の概要

はてなフォトライフAtomAPIはRESTをサポートしています。現時点でSOAPはサポートしていません。

HTTP の GET/POST/PUT/DELETE を特定のURIに対して行い、そのリクエストに規定のXML文書を加えて送信することでインタフェースが用意している操作を行うことができます。また、一部の操作はそのレスポンスとして規定のXML文書を返却します。

現時点でAPIがサポートしている操作は以下です。

  • 新規写真の投稿 (PostURI への POST)
  • 投稿した写真のタイトルの変更 (EditURI への PUT)
  • 投稿した写真の削除 (EditURI への DELETE)
  • 投稿した写真の参照 (EditURI への GET)
  • 最近投稿した写真の一覧の取得 (FeedURI への GET)

以下、はてなフォトライフAtomAPIの詳細を解説します。

WSSE認証

AtomAPIの認証にはWSSE認証が利用されます。はてなフォトライフAtomAPIの利用にはWSSE認証が必須です。WSSE認証の詳細に関しては http://www-128.ibm.com/developerworks/webservices/library/ws-secure/ (英語) を参照してください。ここではWSSE認証についての必要事項を簡単に解説します。

WSSE認証はHTTPのX-WSSEヘッダを用いて認証用文字列を送信する認証手段です。WSSE認証用文字列にはユーザー名とパスワードが含まれます。このとき、パスワードはSHA1アルゴリズムによって暗号化されたダイジェストとして送信されるため、HTTP基本認証などに比べてセキュアな認証が可能です。

送信するX-WSSEヘッダのサンプルは以下のようになります。

X-WSSE: UsernameToken Username="hatena", PasswordDigest="ZCNaK2jrXr4+zsCaYK/YLUxImZU=", Nonce="Uh95NQlviNpJQR1MmML+zq6pFxE=", Created="2005-01-18T03:20:15Z"
Username
ユーザー名。(はてなフォトライフAPIでははてなアカウントのid)
Nonce
HTTPリクエスト毎に生成したセキュリティ・トークン*1
Created
Nonceが作成された日時をISO-8601表記で記述したもの
PasswordDigest
Nonce, Created, パスワード(はてなアカウントのパスワード)を文字列連結しSHA1アルゴリズムでダイジェスト化して生成された文字列を、Base64エンコードした文字列

はてなフォトライフのすべてのAtomAPIエンドポイントURIにはWSSE認証が設定されています。

ルートAtomエンドポイント

はてなフォトライフAtomAPIのルートAtomエンドポイントは以下になります。ルートAtomエンドポイントに対しGETリクエストを行うことで、PostURIとFeedURIを取得することができます。

http://f.hatena.ne.jp/atom

リクエスト

GET /atom

レスポンス

HTTP/1.1 200 OK
Content-Type: application/x.atom+xml

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://purl.org/atom/ns#">
  <link type="application/x.atom+xml" rel="service.post"
        href="http://f.hatena.ne.jp/atom/post" title="fotolife sample">
  <link type="application/x.atom+xml" rel="service.feed"
        href="http://f.hatena.ne.jp/atom/feed" title="fotolife sample">
</feed>

PostURI

PostURIははてなフォトライフへ写真を新規投稿するためのエンドポイントです。POSTメソッドのみをサポートしています。PostURIに対し規定のリクエスト用XML文書をPOSTすることで写真の投稿が可能です。写真データBase64エンコードしてリクエスト用XML文書に記述します。また、Dublin Coreモジュールのdc:subject要素を追加することにより、ファルダ名を指定してアップロードすることができます。

リクエスト用XML文書に記述することができるパラメータは以下です。

  • 写真のタイトルをtitle要素のテキストに
  • 写真データをcontent要素に
    • type属性に画像のContent-Type(例: image/jpeg)
    • mode属性はbase64
    • テキストにBase64エンコードされた画像データ文字列
  • アップロード先のフォルダ名をdc:subject要素に
    • 指定されたフォルダが存在しない場合は、自動的に作成されます。
  • アップロードツール名をgenerator要素に
    • フォトライフの設定画面で、アップロードツール毎のフォルダ振り分けの設定ができます。

操作が何かしらの理由によって失敗した場合は、正常レスポンスとは異なるステータスコードと、それに合わせたエラーメッセージをHTTPヘッダとして返却します。

リクエスト

POST /atom/post

<entry xmlns="http://purl.org/atom/ns#">
  <title>Sample</title>
  <content mode="base64" type="image/jpeg">/9j/2wCEAAQDAwQDAw.../9n/AA==</content>
</entry>

レスポンス

  • レスポンスは正常終了時としてHTTPステータス201を返します。
  • レスポンスXML文書はhatena名前空間(http://www.hatena.ne.jp/info/xmlns#)によって拡張されています。
  • サンプルのXXXXXXXXXXXXXXは画像のURLにおける末尾の数値部に置き換えてください。
  • サンプルのYYYYYYは画像をアップロードした写真があるフォルダ名に置き換えてください。
201 Created
Content-Type: application/x.atom+xml
Location: http://f.hatena.ne.jp/atom/edit/XXXXXXXXXXXXXX

<?xml version="1.0" encoding="utf-8"?>

<entry xmlns="http://purl.org/atom/ns#" xmlns:hatena="http://www.hatena.ne.jp/info/xmlns#">
  <title>Sample</title>
  <link rel="alternate" type="text/html" href="http://f.hatena.ne.jp/naoya/XXXXXXXXXXXXXX"/>
  <link rel="service.edit" type="application/x.atom+xml" href="http://f.hatena.ne.jp/atom/edit/XXXXXXXXXXXXXX" title="Sample"/>
  <issued>2005-01-14T17:01:29+09:00</issued>
  <author>
    <name>naoya</name>
  </author>
  <generator url="http://f.hatena.ne.jp/" version="1.0">Hatena::Fotolife</generator>
  <dc:subject xmlns:dc="http://purl.org/dc/elements/1.1/">YYYYYY</dc:subjetct>
  <id>tag:hatena.ne.jp,2005:fotolife-naoya-XXXXXXXXXXXXXX</id>
  <hatena:imageurl>http://f.hatena.ne.jp/images/fotolife/n/naoya/XXXXXXXX/XXXXXXXXXXXXXX.jpg</hatena:imageurl>
  <hatena:imageurlsmall>http://f.hatena.ne.jp/images/fotolife/n/naoya/XXXXXXXX/XXXXXXXXXXXXXX_m.gif</hatena:imageurlsmall>
  <hatena:syntax>f:id:naoya:XXXXXXXXXXXXXX:image</hatena:syntax>
</entry>

EditURI

EditURIははてなフォトライフへ投稿した

  • 特定の写真エントリのフィードを参照 (GET)
  • 写真の編集 (PUT)
  • 写真の削除 (DELETE)

を行うためのエンドポイントです。操作が何かしらの理由によって失敗した場合は、正常レスポンスとは異なるステータスコードと、それに合わせたエラーメッセージをHTTPヘッダとして返却します。

リクエスト

GET /atom/edit/XXXXXXXXXXXXXX

レスポンス

200 OK
Content-Type: application/x.atom+xml

<?xml version="1.0" encoding="utf-8"?>

<entry xmlns="http://purl.org/atom/ns#" xmlns:hatena="http://www.hatena.ne.jp/info/xmlns#">
  <title>Sample</title>
  <link rel="alternate" type="text/html" href="http://f.hatena.ne.jp/naoya/XXXXXXXXXXXXXX"/>
  <link rel="service.edit" type="application/x.atom+xml" href="http://f.hatena.ne.jp/atom/edit/XXXXXXXXXXXXXX" title="Sample"/>
  <issued>2005-01-14T17:01:29+09:00</issued>
  <author>
    <name>naoya</name>
  </author>
  <id>tag:hatena.ne.jp,2005:fotolife-naoya-XXXXXXXXXXXXXX</id>
  <hatena:imageurl>http://f.hatena.ne.jp/images/fotolife/n/naoya/XXXXXXXX/XXXXXXXXXXXXXX.jpg</hatena:imageurl>
  <hatena:imageurlsmall>http://f.hatena.ne.jp/images/fotolife/n/naoya/XXXXXXXX/XXXXXXXXXXXXXX_m.gif</hatena:imageurlsmall>
  <hatena:syntax>f:id:naoya:XXXXXXXXXXXXXX:image</hatena:syntax>
</entry>

リクエスト

PUT /atom/edit/XXXXXXXXXXXXXX

<entry xmlns="http://purl.org/atom/ns#">
  <title>My Photo</title>
</entry>

※特定の画像エントリの画像データの置換はEditURIへのPUTではサポートしていません。該当のエントリの削除+新規投稿で対応してください。

レスポンス

200 OK

リクエスト

DELETE /atom/edit/XXXXXXXXXXXXXX

レスポンス

200 OK

FeedURI

FeedURIは、投稿された写真のうち最近のエントリをAtomフィードで取得するためのエンドポイントです。GETメソッドのみをサポートしています。

フィードに含まれるエントリの件数は、はてなフォトライフでのユーザー設定によって決定されます。

リクエスト

GET /atom/feed

レスポンス

はてなフォトライフがフィードしているAtomフィードと同様の結果を返します。ここでは省略します。

Perl によるWSSE認証の実装

WSSE認証をPerlで実装する場合は、例えば以下のようになります。

#!/usr/local/bin/perl
use strict;
use warnings;

use DateTime;
use Digest::SHA1 qw (sha1);
use HTTP::Request;
use MIME::Base64 qw (encode_base64);
use LWP::UserAgent;

my $username = shift or die "need username\n";
my $password = shift;

my $nonce = sha1(sha1(time() . {} . rand() . $$));
my $now = DateTime->now->iso8601 . 'Z';
my $digest = encode_base64(sha1($nonce . $now . $password || ''), '');
my $credentials =
    sprintf(qq(UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"),
            $username, $digest,  encode_base64($nonce, ''), $now);

my $req = HTTP::Request->new(GET => 'http://f.hatena.ne.jp/atom');
$req->header( Accept => 'application/x.atom+xml, application/xml, text/xml, */*');
$req->header( 'X-WSSE' => $credentials );

print LWP::UserAgent->new->request($req)->as_string;

X-WSSE ヘッダを作成し、はてなフォトライフAtomAPIエンドポイントの認証を通過して、ルートエンドポイントにGETすることで PostURI、EditURI を取得しています。

また、CPANモジュールのLWP::Authen::Wsse を利用すると、X-WSSEヘッダを生成するロジックを書かなくても、

my $ua = LWP::UserAgent->new;
$ua->credentials('f.hatena.ne.jp:80', '', 'username', 'password');

と LWP::UserAgent に命令するだけで、認証ヘッダを追加したリクエストを送信することができます。

CPANモジュール XML::Atom::Client を利用した投稿

CPANモジュールのXML::Atom::ClientはAtomAPIクライアントを実装するための、WSSE認証やリクエスト、レスポンスに必要なXML文書の組み立てなどを抽象化したモジュールです。

XML::Atom::Clientを用いて、はてなフォトライフに任意の画像をアップロードするサンプルコードは以下のようになります。

#!/usr/local/bin/perl
use strict;
use warnings;

use FileHandle;
use XML::Atom::Entry;
use XML::Atom::Client;

my $PostURI = 'http://f.hatena.ne.jp/atom/post';
my $username = shift or die "need username";
my $password = shift;

my $api = XML::Atom::Client->new;
$api->username($username);
$api->password($password);

my $file = shift;
local $/; # slurp mode
my $fh = FileHandle->new($file) 
	or die "cannnot open $file: $!";
my $image = $fh->getline;

my $entry = XML::Atom::Entry->new;
$entry->content($image);
$entry->content->type('image/jpeg');
$entry->title('Sample image for AtomAPI');
my $EditURI = $api->createEntry($PostURI, $entry) or
	die $api->errstr;

print $EditURI;

XML::Atom::Client はWSSE認証を抽象化しているため、username/passwordメソッドでそれぞれをセットするだけで認証を通過できます。また、XML文書の組み立てはXML::Atom::Entryインスタンスを生成して行い、それを最後にXML::Atom::Clientインスタンスに渡せば完了です。

このスクリプトはコマンドラインから実行し、

$ perl atompost.pl hatena hatena ./sample.jpg

として第3引数に画像ファイルを指定します。画像データのBase64エンコードもXML::Atom::Entryが抽象化しているので、プログラマは特に気にする必要はありません。

*1:ヘッダに含める際にbase64エンコーディングする必要があります

このタグの解説についてこの解説文は、すでに終了したサービス「はてなキーワード」内で有志のユーザーが作成・編集した内容に基づいています。その正確性や網羅性をはてなが保証するものではありません。問題のある記述を発見した場合には、お問い合わせフォームよりご連絡ください。

関連ブログ