HaskellでTwitterクライアント開発blog(仮)

今すぐに挫折するかもしれない程度のモチベーションによるTwitterクライアント開発記

Haskell で OAuth API利用Tweetしてみた

いよいよOAuth APIを使ってtweetしてみました。
が、そのまえに前記事・前々記事には気づかなかった署名アルゴリズムに関する私の誤解について。

署名対象文字列生成の際、パラメータ部分を接合する時

パラメータを' & ' , ' = 'で接合→URLエンコード

という変換だと思っていましたが、これは誤解で

パラメータを' & ' , ' = 'で接合してURLエンコード→URLエンコード

でした。

この問題は、URLエンコードによって変更される文字がパラメータ・パラメータ名には無かったので、今まで表面化しなかったようです。
ここで随分ハマってしまいました。

さて本題です。tweetしてみた話。
status="ツイート内容"という、APIに渡す引数が加わっただけですが、コレのせいでいろいろなバグを踏みました。

(1)署名にはstatus="ツイート内容"を含めて、Authorizationヘッダのパラメタには含めない
→statusはAuthorizationヘッダの内容ではないが、署名対象にはなるということ。

(2)POSTリクエストボディにstatus="ツイート内容"を込めて送信する場合、Content-Lengthヘッダを付ける。
→これは単に私がHTTP通信に慣れてなかったせいで見落としました(たぶん)。ただ、この場合も返ってくるエラーは"401 Unauthorized"なんですよね……

とりあえずこれで無事自作クライアントでtweetすることができました。

コードも載せますが、一応ツイートが成功するHTTPリクエストの内容を載せます。
自分が作っていて一番欲しい情報だったので……

POST http://api.twitter.com/1/statuses/update.json HTTP/1.1
Authorization: OAuth oauth_token="********************", oauth_consumer_key="***************", oauth_nonce="804621766734007680", oauth_timestamp="1332346240", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="*********************"
Content-Length: 11


Request Body:

"status=TEST"

リクエストボディにstatus="ツイート内容"を入れ、Content-Lengthヘッダに「status=」も含めた長さを指定。

このときの署名は

POST&「"http://api.twitter.com/1/statuses/update.json"をURLエンコード」&(「上のAuthorizationヘッダのパラメタ+status="ツイート内容"」を'&', '='で接合してURLエンコード

全体をさらにURLエンコードした文字列です。

ちなみに、日本語ツイートをする場合、ツイート内容はUTF8エンコードしておく必要があります。

コードはこちら → http://ideone.com/tJe1I

gistが文字数多すぎて使えないんですよね……早めにgithubでコード公開するようにしたいです。