ようこそゲストさん

mitc - 日記

2008/02/21(木) Remember The Milk APIの使い方調査

はてブ 2008/02/20 25:38 調査miff

はじめに

Remember The Milkとは

Remember The Milkとは,いわゆるTODO管理ツールです.
やるべきことを忘れないように書きとめておいて,実行状態を確認できるようにしておくような感じです.
このRemember The Milkは,TwitterやGMailと連携する機能などを用意していて最近人気があるような気もする感じです.
その辺の界隈のことはよくわからないですが,私も数ヶ月前から使っていてそれなりにいい感じです.
使っている風景を次のスクリーンショットに示します.

RtMUsing.png

Remember The Milk APIとは

Remember The Milk APIとは,いわゆる「WebAPI」と呼ばれるようなものです.
具体的には,Remember The Milkの機能を自作のアプリケーションから呼び出すための規約です.
○○という手順でデータを送ると○○という処理をしますといったようなルールの集合です.
Remember The Milk APIでは,HTTPリクエストで文字列をやり取りすることで50種類の処理が行えるようになっています.
また,ユーザ認証の手順も提供されていて,アプリケーション側でユーザのアカウント情報を触る必要が無いようになっています.

詳しくは次節以降で説明しますが,簡単に書くと次のようなURLを作ってそこにアクセスすると処理が実行されるようなイメージです.
http://api.rememberthemilk.com/services/rest/?method=rtm.test.echo&api_key=foobar

Remember The Milk APIの仕組み

メソッド呼び出しと戻り値

メソッド呼び出し
Remember The Milk - Services / API / Request Formats / REST

メソッドの呼び出しには,RESTを用います*1
Remember The Milk APIでメソッドを呼び出す具体的な方法を示します.

例えば,次のような条件を考えます.
API_URL
http://api.rememberthemilk.com/services/rest/
ParameterValue
methodrtm.test.echo
api_keyfoobar
これに対して,次の二つの文字列を準備します.

・呼び出しURL
http://api.rememberthemilk.com/services/rest/
・パラメータ
method=rtm.test.echo&api_key=foobar
呼び出しURLはそのままAPIのURL.
パラメータは,パラメータ名とその値を「=」で接続したものを「&」で接続します.

実際に呼び出すにはHTTPの「GET」か「POST」のどちらかを使います.
GETならURLの後ろに「?」を付けてパラメータを接続します.
ここでは,簡単のためにGETのみを解説します.
http://api.rememberthemilk.com/services/rest/?method=rtm.test.echo&api_key=foobar
こうして作成したURLにアクセスすることで,要求をWebAPIに伝えます.
処理結果は,その接続での応答に記されます.
戻り値
戻り値は,何も指定しない時はXML,
呼び出し時にformat=jsonを指定することでJSON形式で返ってきます.

例えば,メソッド呼び出しの項目で例に挙げたリクエストだと次のようになります.
<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="ok">
	<api_key>foobar</api_key>
	<method>rtm.test.echo</method>
</rsp>
このXML形式の文書を解析することで処理結果を得ます.,

エラー

Remember The Milk API側でリクエストに対するエラーが発生した場合,
戻り値が次のようになります.
<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="fail">
	<err code="100" msg="Invalid API Key"/>
</rsp>
ルートノードルート要素*2「rsp」の属性「stat」が"ok"でないことを確認すれば良いでしょう.

認証の仕組み

Remember The Milk - Services / API / User Authentication

Remember The Milk APIの認証機構の概要を次図に示します.

AuthenticationSystem.png
図 Remember The Milk APIの認証機構*3

この認証機構では,frob,認証URLとtokenの3つの要素が登場します.
frobはtokenの引換券,認証URLはユーザにfrobを承認して貰うためのURL,
そしてtokenはユーザの認証に使う文字列です.
このようにアプリケーションがユーザのパスワードに全く触れなくても良い認証機構となっています.
これは,写真共有サイトFlickrのAPIを参考にしたらしいです.
Flickrの認証APIについては,次のサイトの解説がわかりやすいです.
Remember The Milkも流れは同じなので参考になります.
認証の流れを図中の番号を参照して簡単に説明します.

1. frobを取得する

rtm.auth.getFrobメソッドでfrobを取得します.
frobとは,tokenを取得するための引換券です.

2. ユーザに認証URLにアクセスしてfrobを承認してもらう

認証URLは,Remember The Milkの認証APIのURLに次のパラメータを追加することで作成します.
パラメータ名
permsアプリケーションがユーザのデータに対してどの程度の権限を持つか.(read/write/delete)のいずれか.
api_keyRemember The Milkから発行されるアプリケーションを一意に識別する文字列.認証はこのapi_keyに対して行われる.
frobtokenを得るための文字列.ユーザは,このfrobに対して承認を行う.
api_sig次項で説明する,確かにapi_keyの持ち主がこのパラメータを作成したということを証明するための署名
これらの値をパラメータとして持たせたRemember The Milkの認証URLにユーザにブラウザでアクセスしてもらいます.
アクセスすると,次のスクリーンショットのようなページが表示されます.
(ただし,ユーザがRemember The Milkにログインしていない状態でアクセスすると,
まずRemember The Milkのログイン画面が表示されます)
AuthUrl.png

ここで,ユーザが「OK, I'll allow it」ボタンをクリックしてアプリケーションのユーザのデータへのアクセスを承認すると,
次のスクリーンショットのようなページが表示されます.
AuthUrlAuthed.png

これで,認証URLに渡したfrob値が有効になり,tokenと交換することができるようになります.

また,frobは省略可能ですが,frobを省略して作成した認証URLにアクセスすると,
frobを省略しなかった場合と同様にユーザに対して対象APIへの権限付与を行うかどうかを確認するページが表示され,
ユーザが承認すると次のスクリーンショットのように,frob値が提示されます.
つまり,frobを省略した場合は,ユーザにそのfrob値をアプリケーションに入力してもらい,
そのfrob値を追加した認証URLを再度作成する必要があります.

AuthUrlWithoutFrob.png

ところで,このページには,
No callback URL specified for this API key. Your frob value is foobar
と書いてあるようにcallback URLがあれば,
次のようにそのURLのパラメータにfrob値を付けてリダイレクトしてくれるようです.
http://www.callbackurl.com/callback?frob=foobar
これは,Webブラウザベースのアプリケーションでの認証に利用するもののようです.

3. frobとtokenを引き替え

rtm.auth.getTokenメソッドでユーザから承認を得たfrobをtokenと交換します.
よくあるWebサービスのユーザ認証機構では,ユーザ名とパスワードをAPIに渡して認証を行ったりしますが,
Remember The Milk APIが採用している認証機構では,このtokenがユーザ認証のためのキーになります.
実際,ユーザ認証が必要なAPIを呼び出す時には,このtokenを必ずパラメータに含めます.

また,「frobをtokenと交換」と表現しましたが,
実際に一度tokenの取得に使用したfrobは効果を失い,tokenとの交換に使えなくなります.

api_sigとは?

Remember The Milk APIへのリクエストには,「なりすましリクエスト」を防ぐために
api_sigという名前の署名パラメータを付与する必要があります.
これは,リファレンスには載っていませんが次のメソッド以外を呼び出す時には必ずメソッドに含める必要があります.
  • rtm.auth.checkToken
  • rtm.reflection.getMethodInfo
  • rtm.reflection.getMethods
  • rtm.test.echo
  • rtm.time.parse
(この表は,rtm.reflectioni.getMethodInfoで得られる情報から作成しました.
 試したわけではないので間違っている場合はご指摘お願いします)

このapi_sigとは,アプリケーション開発者があらかじめRemember The Milkから受け取っている共通鍵(Shared Secret)とapi_sig以外のパラメータから作成する文字列です.
具体的には,全パラメータをパラメータ名の昇順で並べ,順番にパラメータ名とパラメータ値を結合していった文字列の先頭に共通鍵を結合し,
その文字列のMD5値を算出して求めます.
かなりわかりにくいと思うので,例を挙げて説明します.

例えば,次のようなパラメータをAPIに送る場合を考えます.
auth_token=USERAUTHEDTOKEN
name=テスト
timeline=19983421
method=rtm.lists.add
api_key=USERAPIKEY
まず,パラメータ名の昇順に並べ替えます.
api_key=USERAPIKEY
auth_token=USERAUTHEDTOKEN
method=rtm.lists.add
name=テスト
timeline=19983421
次に,パラメータ名とパラメータ値を結合します.
api_keyUSERAPIKEY
auth_tokenUSERAUTHEDTOKEN
methodrtm.lists.add
nameテスト
timeline19983421
次に,これらを順番に結合して一つの文字列にします.
api_keyUSERAPIKEYauth_tokenUSERAUTHEDTOKENmethodrtm.lists.addnameテストtimeline19983421
次に,共通鍵を文字列の先頭に結合します.
今回は,共通鍵の文字列が「SHAREDSECRET」であると仮定します.
SHAREDSECRETapi_keyUSERAPIKEYauth_tokenUSERAUTHEDTOKENmethodrtm.lists.addnameテストtimeline19983421
最後に,この文字列のMD5値を算出します.
a03ff53a439f51932462864e16aff309
これでapi_sigの計算が完了します.
最終的に,これをAPIに送るパラメータに追加します.
上で例示したパラメータリストの場合,APIに送るパラメータ文字列は次のようになります.
api_key=USERAPIKEY&api_sig=a03ff53a439f51932462864e16aff309&auth_token=USERAUTHEDTOKEN&method=rtm.lists.add&name=テスト&timeline=19983421
注意点として,MD5値の算出時に文字列をUTF-8として扱う必要があります.
例えば,次のようなC#のコードでは,api_sigが不正だというエラーが返ってきてしまいます.
// MD5計算用オブジェクト
System.Security.Cryptography.MD5 md5Calculator = System.Security.Cryptography.MD5.Create();

// 文字列をUTF-8のバイト列に変換
byte[] data = md5Calculator.ComputeHash(Encoding.Default.GetBytes(sourceString));

// バイト列を文字列に変換して返す
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
	sBuilder.Append(data[i].ToString("x2"));
}
return sBuilder.ToString();
この部分で入力文字列からMD5算出用のバイト列を取得しているのですが,
Encoding.Default.GetBytes(sourceString)
Windows環境*4では通常,Encoding.DefaultがShift_JISになっているので,
正しいapi_sigが算出できません.
これは,api_sig算出時に限らないのですが,Remember The Milk APIとやり取りする文字列は,
全てUTF-8であることを意識しておく必要があります.

timelineとUndo

Remember The Milk - Services / API / Timelines

timelineとは,Remember The Milk APIを使って行った処理を巻き戻すために必要な数値列です.
rtm.timelines.createメソッドを呼び出すことで,例えば「18921543」のような数値列を得られます.
タスクを追加する,リストを削除するといったデータに変更を加えるAPIを呼び出す時のパラメータには,必ずこのtimelineを含ませる必要があります.

timelineを何かに例えるなら,一番近いのは「記憶」です.
timelineは,メソッドに渡されることでそのメソッドが何をしたかを記憶します.
記憶には,メソッド実行後に返ってくるそのメソッド実行のtransaction idでアクセスできます.
timelineとtransaction idを渡してrtm.transactions.undoメソッドを呼び出すことで,
そのtransaction idが指すメソッド実行を無かったことにできます.

timeline.png

ここで,transactionやundoといった単語がでてきていますが,
よく使われるundoは一つ前の処理をキャンセルすることであり,
transactionは複数の処理をまとめて扱うための機構です.
しかし,ここでのtransactionは一つ一つのメソッド実行であり,
undoは各transactionをキャンセルすることです.
似ている部分もありますが,同じものでは無いことに注意する必要があります.
Undoできるメソッドできないメソッド
メソッドには,Undoできるメソッドとできないメソッドがあります.
公式リファレンスやメソッドの情報を得るためのメソッド「rtm.reflection.getMethodInfo」からは,
これらを区別する情報を得られません.
では,どうやってそれを判断するのかといいますと,基本的に二つの条件が考えられます.
一つは,「メソッド呼び出しにtimelineを必要とするか否か」です.
当然,timelineを渡さないで実行するメソッドはUndoできません.
しかし,timelineを渡して実行するメソッドにもUndoできないものがあります.
これを判断するためには,メソッド呼び出しの戻り値をチェックします.

例えば,rtm.lists.deleteの戻り値は次のようになります.
<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="ok">
	<transaction id="1689341907" undoable="1" />
	<list id="2630412" name="transaction1" deleted="1" locked="0" archived="0" position="0" smart="0" sort_order="0" />
</rsp>
ここで注目すべきは,「/rsp/transaction/@undoable」です.
上記コード中で色を変えているのでわかると思いますが,transactionノードのundoable属性が1であれば,Undo可能です.

ちなみに,Undoできない例としてrtm.lists.addの戻り値を掲載しておきます.
<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="ok">
	<transaction id="1690041908" undoable="0"/>
	<list id="2630768" name="transaction'" deleted="0" locked="0" archived="0" position="0" smart="0" sort_order="0"/>
</rsp>

日時の扱い

Remember The Milk - Services / API / Dates

日時の扱いは,ISO8601形式でタイムゾーンはUTC(協定世界時:Coordinated Universal Time*5)です.
Remember The Milk APIに日時を入力する時は,ローカルの日時からUTCへ,
逆に日時を含むデータを取得する時は,UTCからローカルの日時に変換します.
日本の標準時はJST(日本標準時:Japan Standard Time)なのでUTCとJSTの相互変換になります.
JSTとUTCの関係は,(JST=(UTC+9:00))になります.

例えば,2008/2/19 16:51:37に更新したタスクがあったとして,
Remember The Milk APIから取A得した時に書いてあるのは,次のようになります.
2008-02-19T07:51:37Z
.NETなら,DateTimeクラスのToLocalTimeメソッドとToUniversalTimeメソッドで相互変換できます.

*1 : JSONでの呼び出しがcoming soon...になっているので,そのうちJavaScriptを使ったアプリが作りやすくなるかもしれません.

*2 : 2008/08/22修正

*3 : シーケンス図もどきです.字が小さくて読みにくいです.

*4 : Windows Vistaにおいても

*5 : CUTなのにUTC?と疑問に思った方はWikipedia辺りで調べて下さい

おわりに

本文書の最後に,Remember The Milk APIの使用に関する簡単なまとめを掲載します.
  • 認証には,認証URLを作成してユーザにそのURLにアクセスしてもらう必要がある
    • frobとtokenと呼ばれる文字列のやり取りで認証を行う少し特殊なやり方なので注意が必要
  • 公式リファレンスのメソッド情報に載っていない必須パラメータとして「api_sig」がある
    • api_sigは,メソッドの呼び出しパラメータに共通鍵とMD5値を使って行う署名である
    • ただし,api_sigは必要無い場合もある
  • timelineとtransaction idをrtm.transactions.undoメソッドに渡すことでtransaction idが示す処理を無かったことにできる
    • ただし,undoが可能なメソッドと可能でないメソッドがある
  • 時間はUTCに変換してやり取りする必要がある


名前:  非公開コメント   

E-Mail(任意/非公開):
URL(任意):
  • TB-URL  http://mitc.s279.xrea.com/diary/073/tb/
  • TO DOの管理ツール「Remember The Milk」 アタシのアシタはココにあるっ!
    私は結構忘れっぽいです。 先月の末くらいから今月の頭のほうまではすごく忙しくて、...