2009年2月15日

portable contactsから情報取得をしてみた。

portable contactsから情報取得をしてみた。



とりあえず提案元のPlaxoから取得。
discoveryはopenidライブラリに含まれているyadisモジュールを使用。



認証はOAuthかBasic認証のサポートが必須となっているが、今回はBasic認証を使っている。



openid.yadis.services.getServiceEndpointsで、XRDSからサービスエンドポイントを取得する。このとき、portableContactsのエンドポイントだけを取得するようにフィルタを使う。
フィルタはIFilterというインターフェイスも定義されているが、Pythonだと関数を渡すだけでもOK。きっと、JavaやC#の時に使うのでしょう。



エンドポイントが取得できたら、そのURLに対してGETリクエストしますが、認証がかかってるので、WWW-AUTHENTICATEヘッダで認証方法を確認します。
前述のとおり、今回はBasic認証だけ対応。



取得できたら、レスポンスボディをjsonに変換して、エントリを取り出します。



import sys
import httplib2
import re
import json
from openid.yadis import services


PORTABLECONTACTS='http://portablecontacts.net/spec/1.0'
def portableContactsFilter(endpoint):
return endpoint if PORTABLECONTACTS in endpoint.type_uris else None

authpattern = re.compile(
r'''(?:\s*www-authenticate\s*:)?\s*
(?P<scheme>\w*)\s+realm=['"]
(?P<realm>[^'"]+)['"]''',
re.IGNORECASE | re.VERBOSE)


def show_entries(content):

contacts = json.loads(content)
for entry in contacts['entry']:
print entry['id'], entry['displayName']


url = 'http://www.plaxo.com'

url, endpoints = services.getServiceEndpoints(url, portableContactsFilter)
if len(endpoints) == 0:
print 'endpoints not found'
sys.exit(0)


e = endpoints[0]
h = httplib2.Http()
res, content = h.request(e.uri, "GET")
if res.status == 200:
show_entries(content)

if res.status == 401:
auth = [m.groupdict()['scheme']
for m in authpattern.finditer(res.get('www-authenticate', ''))]
if 'Basic' in auth:
import getpass
user = raw_input('username: ')
password = getpass.getpass('password: ')
h.add_credentials(user, password)
res, content = h.request(e.uri, "GET")
if res.status == 200:
show_entries(content)
else:
print 'Request is failed.'
else:
print 'Basic auth is not supported.'</realm></scheme>


Webアプリで使う場合はOAuthを使うことが多くなりそうですが、yadisリクエストを何度も行うことになりそうです。
openid.consumerのソースをみると、yadis.managerというものがキャッシュをしてくれるようです。