綾小路龍之介の素人思考

[perl] WebService::Google::Readerでsubscription/edit出来ない

WebService::Google::Readerの0.1に有った問題。subscribeとかedit_tagとか出来ない。問題はtokenを取得していなかったから。モジュールに含めてくれよ。

まずはテストコードとこれを動かした結果。リクエストにエラーがあるといわれるけど、どこがまずいのかはわからない。

$ cat googlereader_test.pl
#!/usr/bin/perl
use strict;
use warnings;
use WebService::Google::Reader;
my $reader = WebService::Google::Reader->new(
                username => '*******',
                password => '*******',
                );
$reader->unsubscribe('http://search.cpan.org/uploads.rdf');
print $reader->error;
exit;
$ perl googlereader_test.pl
400 Bad Request - <html><head><title>400 Client Error</title>
<style type="text/css">
      body {font-family: arial,sans-serif}
      div.nav {margin-top: 1ex}
      div.nav A {font-size: 10pt; font-family: arial,sans-serif}
      span.nav {font-size: 10pt; font-family: arial,sans-serif; font-weight: bold}
      div.nav A,span.big {font-size: 12pt; color: #0000cc}
      div.nav A {font-size: 10pt; color: black}
      A.l:link {color: #6f6f6f}
      </style></head>
<body text="#000000" bgcolor="#ffffff"><table border="0" cellpadding="2" cellspacing="0" width="100%"></table>
<table><tr><td rowspan="3" width="1%"><b><font face="times" color="#0039b6" size="10">G</font><font face="times" color="#c41200" size="10">o</font><font face="times" color="#f3c518" size="10">o</font><font face="times" color="#0039b6" size="10">g</font><font face="times" color="#30a72f" size="10">l</font><font face="times" color="#c41200" size="10">e</font>  </b></td>
<td> </td></tr>
<tr><td bgcolor="#3366cc"><font face="arial,sans-serif" color="#ffffff"><b>Error</b></font></td></tr>
<tr><td> </td></tr></table>
<blockquote><h1>Client Error</h1>
There was an error in your request.
<p></p></blockquote>
<table width="100%" cellpadding="0" cellspacing="0"><tr><td bgcolor="#3366cc"><img alt="" width="1" height="4"></td></tr></table></body></html>

ngrepを仕込んでパケットキャプチャした結果が以下。GoogleReaderAPIの非公式文書を当たると、subscription/edit系のAPIはtokenが必要とのこと。本家WebService::Google::Readerを使うとtokenが送られていない。

# ngrep -d ppp0 -W byline WebService
interface: ppp0 (***************/255.255.255.255)
match: WebService
T ***************:58605 -> 66.249.89.104:80 [AP]
POST /reader/api/0/subscription/edit?ck=1277968999000&client=WebService%3A%3AGoogle%3A%3AReader%2F0.1+(gzip) HTTP/1.1.
TE: deflate,gzip;q=0.3.
Connection: TE, close.
Accept-Encoding: gzip,deflate.
Authorization: GoogleLogin auth=***********************************************************************************************************************************************************************************************************.
Host: www.google.com.
User-Agent: WebService::Google::Reader/0.1 (gzip).
Content-Length: 272.
Content-Type: application/x-www-form-urlencoded.
.
ac=unsubscribe&s=feed%2Fhttp%3A%2F%2Fsearch.cpan.org%2Fuploads.rdf&T=***********************************************************************************************************************************************************************************************************
118 received, 0 dropped

tokenとは何かを非公式文書から調べる。tokenとはhttp://www.google.com/reader/api/0/tokenにアクセスして得られる57文字の文字列のことらしい。

To edit anything in the Google Reader database, you need a token (see glossary). To get a token, just go to http://www.google.com/reader/api/0/token . This url will return a string containing 57 chars. It's the token.

まずはtokenを得るためのコード。tokenを得るためには最初にログインをする必要がある。得られた文字列は57文字ではない(22文字)けど、これで問題ない。

$ cat googlereader_test.pl
#!/usr/bin/perl
use strict;
use warnings;
use HTTP::Request;
use WebService::Google::Reader;
my $reader = WebService::Google::Reader->new(
                username => '*******',
                password => '*******',
                );
$reader->_login;
my $req_token = HTTP::Request->new(GET => 'http://www.google.com/reader/api/0/token');
my $res_token = $reader->_request($req_token);
print $res_token->content, "\n";
exit;
$ perl googlereader_test.pl
**********************

ngrepでパケットキャプチャしたときの記録。

# ngrep -d ppp0 -W byline WebService
interface: ppp0 (***************/255.255.255.255)
match: WebService
T ***************:49241 -> 66.249.89.99:80 [AP]
GET /reader/api/0/token?ck=1277970643000&client=WebService%3A%3AGoogle%3A%3AReader%2F0.1+(gzip) HTTP/1.1.
TE: deflate,gzip;q=0.3.
Connection: TE, close.
Accept-Encoding: gzip,deflate.
Authorization: GoogleLogin auth=***********************************************************************************************************************************************************************************************************.
Host: www.google.com.
User-Agent: WebService::Google::Reader/0.1 (gzip).
.

得られたtokenを使ってsubscribeしてみる。エラーなしで終了する。確かにフィードが購読されていることがブラウザからログインして確かめられる。

$ cat googlereader_test.pl
#!/usr/bin/perl
use strict;
use warnings;
use HTTP::Request::Common qw(POST);
use Data::Dumper;
use WebService::Google::Reader;
my $reader = WebService::Google::Reader->new(
                username => '*******',
                password => '*******',
                );

$reader->_login;
my $req_token = HTTP::Request->new(GET => 'http://www.google.com/reader/api/0/token');
my $res_token = $reader->_request($req_token);

my $uri = 'http://www.google.com/reader/api/0/subscription/edit';
my $req = HTTP::Request->new();
$req = POST($uri,[
        ac => 'subscribe',
        s  => 'feed/http://search.cpan.org/uploads.rdf',
        T  => $res_token->content,
]);
$reader->_request($req);
$reader->error;
exit;
$ perl googlereader_test.pl

ngrepの記録。tokenを持ってきて、これを使ってsubscribeしていることがわかる。

# ngrep -d ppp0 -W byline WebService
interface: ppp0 (***************/255.255.255.255)
match: WebService
T ***************:45131 -> 66.249.89.99:80 [AP]
GET /reader/api/0/token?ck=1277970978000&client=WebService%3A%3AGoogle%3A%3AReader%2F0.1+(gzip) HTTP/1.1.
TE: deflate,gzip;q=0.3.
Connection: TE, close.
Accept-Encoding: gzip,deflate.
Authorization: GoogleLogin auth=***********************************************************************************************************************************************************************************************************.
Host: www.google.com.
User-Agent: WebService::Google::Reader/0.1 (gzip).
.

###############
T ***************:45132 -> 66.249.89.99:80 [AP]
POST /reader/api/0/subscription/edit?ck=1277970978000&client=WebService%3A%3AGoogle%3A%3AReader%2F0.1+(gzip) HTTP/1.1.
TE: deflate,gzip;q=0.3.
Connection: TE, close.
Accept-Encoding: gzip,deflate.
Authorization: GoogleLogin auth=***********************************************************************************************************************************************************************************************************.
Host: www.google.com.
User-Agent: WebService::Google::Reader/0.1 (gzip).
Content-Length: 89.
Content-Type: application/x-www-form-urlencoded.
.
ac=subscribe&s=feed%2Fhttp%3A%2F%2Fsearch.cpan.org%2Fuploads.rdf&T=**********************
54 received, 0 dropped

つまり、subscription/editする場合はtokenを持ってきて、これを含めてPOSTすればいいということになる。subscription/edit系ののメソッドで全てこれをやるのは煩雑なのでモジュール化して欲しい。

リファレンス

  1. GoogleReaderAPI - pyrfeed - Project Hosting on Google Code
  2. WebService::Google::Reader - search.cpan.org
  3. 未公開の Google Reader API を探る - WebOS Goodies
  4. http://www.google.com/reader/api/0/token - Google 検索

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2009-06-10T17:04:58+09:00
  2. Modified: 2009-06-10T17:04:58+09:00
  3. Generated: 2017-07-13T23:09:41+09:00