Google Data API クライアントのデバッグ: プログラム内からのトラフィックの調査

Google Data APIs チーム、Jeffrey Scudder
2007 年 6 月

はじめに

ワイヤを通過するものを確認する以外に方法がない場合もあります。これは、Google Data APIs などのウェブサービスを使用するソフトウェアを作成する場合に特に当てはまります。この場合、多くのオペレーションで HTTP リクエストの作成が必要になります。他の方法で確認できない場合は、実際に送受信されたバイト数を確認することで、プログラムが想定どおりに動作していることを確認できます。Google Data APIs のクライアント ライブラリの多くには、HTTP トラフィックを表示するデバッグモードがあります。これは、WireSharkFiddler などのパケット スニファにアクセスできない場合に特に便利です。

プログラムが正しいと確信していたのに、パケット トレースを調べると、余分な改行文字があったり、HTTP ヘッダーの名前が間違っていたりしたことが何度あったか数え切れません。HTTP トラフィックを確認せずにウェブ サービスに対してプログラミングを行うのは、目をつぶって針に糸を通そうとするようなものです。

ただし、パケット スニファが使用できない場合や、暗号化されたパケットを処理するのに十分でない場合があります。ただし、プログラム内のロギング メカニズムを活用することで、この制限を回避できます。これらのロギング機能を利用すると、暗号化された HTTPS データやリモートで実行されているコードであっても、交換されたデータの一部またはすべてを確認できます。

この記事では、Java.NETPython 用の Google Data API クライアント ライブラリを使用して、3 つの言語でサンプル診断コードを作成しました。各例では、ロギングまたはデバッグをオンにし、クライアント ログインを使用して認証してから、Google スプレッドシートのリストを取得してタイトルを出力します。

Java

java.util.logging クラスを使用すると、クライアント ライブラリ内のいくつかのキー オブジェクトのロギングレベルを設定できます(結果としてトラフィック データが公開されます)。次の例では、HTTP ヘッダーと XML パーサーのアクティビティを調べて、ネットワークを通過するものを完全に把握しています。

Google Data Java クライアント ライブラリには、HTTP リクエストと XML 解析を処理する個別のクラスがあります。そのため、クラスごとに 1 つずつ、2 つの Logger オブジェクトを作成する必要があります。com.google.gdata.client.http.HttpGDataRequest は HTTP トラフィックを処理し、com.google.gdata.util.XmlParser は XML 解析を担当します。

ロガー インスタンスは HttpGDataRequestXmlParser のアクティビティを記録します。各ロガーの出力の詳細レベルを制御できます。このデモでは、HttpGDataRequest オブジェクトと XmlParser オブジェクトによって生成されたすべてのイベントを表示するように選択しました。

Logger を作成して構成したら、クラスからイベントを受信したときに何を行うかを Logger に伝える必要があります。ここでは、すべてのロギング情報をコンソールに出力したいので、ConsoleHandler を作成して両方の Logger に追加します。

サンプルコードは次のとおりです。

import com.google.gdata.client.spreadsheet.*;
import com.google.gdata.data.spreadsheet.*;
import com.google.gdata.util.*;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.logging.*;

public class PrintSpreadsheetsWithLogging {
   
   
public static void main(String [] args) throws AuthenticationException,
                                                   
ServiceException, IOException {
       
// Configure the logging mechanisms.
       
Logger httpLogger = Logger.getLogger("com.google.gdata.client.http.HttpGDataRequest");
        httpLogger
.setLevel(Level.ALL);
       
Logger xmlLogger = Logger.getLogger("com.google.gdata.util.XmlParser");
        xmlLogger
.setLevel(Level.ALL);
       
// Create a log handler which prints all log events to the console.
       
ConsoleHandler logHandler = new ConsoleHandler();
        logHandler
.setLevel(Level.ALL);
        httpLogger
.addHandler(logHandler);
        xmlLogger
.addHandler (logHandler);
       
       
SpreadsheetService service = new SpreadsheetService("testing-loggingExampleApp-1");
        service
.setUserCredentials(email, password);
     
       
// Get a list of your spreadsheets.
        URL metafeedUrl
= new URL("http://spreadsheets.google.com/feeds/spreadsheets/private/full ");
       
SpreadsheetFeed feed = service.getFeed(metafeedUrl, SpreadsheetFeed.class);
     
       
// Print the title of each spreadsheet.
       
List spreadsheets = feed.getEntries();
       
for (int i = 0; i < spreadsheets.size(); i++) {
         
SpreadsheetEntry entry = (SpreadsheetEntry)spreadsheets.get(i);
         
System.out.println("\t" + entry.getTitle().getPlainText());
       
}
   
}
}

このプログラムを実行すると、コンソールに次のような内容が表示されます(興味のない部分は省略しています)。

Jun 7, 2007 10:24:50 AM ...HttpGDataRequest setPrivateHeader
FINER: Authorization: <Not Logged>
Jun 7, 2007 10:24:50 AM ...HttpGDataRequest setHeader
FINER: User-Agent: ...
...
Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute
FINE: 200 OK
Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute
FINER: Date: Thu, 07 Jun 2007 17:25:24 GMT
Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute
FINER: null: HTTP/1.1 200 OK
Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute
FINER: Content-Type: application/atom+xml; charset=UTF-8
Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute
FINER: Last-Modified: Thu, 07 Jun 2007 17:25:22 GMT
...
Jun 7, 2007 10:25:20 AM ...XmlParser startElement
FINE: Start element id
Jun 7, 2007 10:25:20 AM ...XmlParser endElement
FINE: End element id
...
Jun 7, 2007 10:25:20 AM ...XmlParser startElement
FINE: Start element title
Jun 7, 2007 10:25:20 AM ...XmlParser startElement
FINER: Attribute type='text'
Jun 7, 2007 10:25:20 AM ...XmlParser endElement
FINE: End element title
...
Jun 7, 2007 10:25:20 AM ...XmlParser endElement
FINE: End element entry
...
Jun 7, 2007 10:25:20 AM ...XmlParser endElement
FINE: End element feed

これらのログは非常に大きくなる可能性があるため、ロガーのレベルを設定する際は、より選択的に行うことをおすすめします。ConsoleHandler の代わりに FileHandler を作成して、ログデータを保存し、後で使用できるようにすることもできます。

もちろん、Java が得意でない場合は、.NET を試してみることもできます。

.NET

.NET クライアント ライブラリで HTTP トラフィックをキャプチャするには、クライアントのデフォルトのリクエスト ファクトリを GDataLoggingRequestFactory に置き換えます。

.NET ライブラリの HTTP リクエストは、各 Service オブジェクト内にある GDataRequestFactory によって作成されます。通常のリクエスト ファクトリはロギングを行いませんが、GDataRequestFactory のサブクラスである GDataLoggingRequestFactory にはロギングが組み込まれています。CombinedFileName を設定すると、ログファイルのフルパスを指定できます。

リクエスト ファクトリを設定したら、サービス オブジェクトの RequestFactory を設定して、サービス オブジェクトのリクエスト ファクトリを置き換える必要があります。コードは次のようになります。

using System;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Spreadsheets;

namespace LogginTest
{
   
class Program
   
{
       
static void Main(string[] args)
       
{
           
SpreadsheetsService service = new SpreadsheetsService("-exampleApp-1");
            service
.setUserCredentials(email, password);

           
Google.GData.Client.GDataLoggingRequestFactory factory = new GDataLoggingRequestFactory("wise", "SpreadsheetsLoggingTest");
            factory
.MethodOverride = true;
            factory
.CombinedLogFileName = "c:\\temp\\xmllog.log";
           
Console.WriteLine("Log file name:" + factory.CombinedLogFileName);
           
            service
.RequestFactory = factory;

           
SpreadsheetQuery query = new SpreadsheetQuery();
           
SpreadsheetFeed feed = service.Query(query);

           
Console.WriteLine("Your spreadsheets:");
           
foreach (SpreadsheetEntry entry in feed.Entries)
           
{
               
Console.WriteLine(entry.Title.Text);
           
}

           
Console.ReadKey();
       
}
   
}
}

生成されたログファイルには、XML リクエストとレスポンスが含まれています。以下に、tidy を使用してフォーマットした例を簡略化して示します。

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

<feed xmlns='http://www.w3.org/2005/Atom'
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
  <id>
  http://spreadsheets.google.com/feeds/spreadsheets/private/full</id>
  <updated>2007-06-07T22:05: 02.674Z</updated>
  <link rel='self' type='application/atom+xml'
  href='http://spreadsheets.google.com/feeds/spreadsheets/private/full'>

  </link>
  ...
  <entry>
    <updated>2007-03-28T17:28:57.250Z</updated>
    <category scheme=' http://schemas.google.com/spreadsheets/2006'
    term='http://schemas.google.com/spreadsheets/2006#spreadsheet'>
    <title type='text'>events</title>

    <content type='text'>events</content>
    ...
  </entry>
  <entry>
    <updated>2007-05-25T22:11:08.200Z</updated>

    <category scheme=' http://schemas.google.com/spreadsheets/2006'
    term='http://schemas.google.com/spreadsheets/2006#spreadsheet'>
    </category>
    <title type='text'>UnitTest</title>
    <content type='text'>UnitTest</content>
    ...
  </entry>

  ...
</feed>

スクリプト言語に精通していて、Python を使用したい場合もあるでしょう。

Python

Python クライアント ライブラリで HTTP トラフィックをキャプチャするには、HTTP クライアントでデバッグモードをオンにして、HTTP ヘッダー トラフィックをコンソールにエコーします。サービス オブジェクトには、True に設定できるデバッグ メンバーがあります。

デバッグを true に設定すると、サービス オブジェクトに含まれる基盤となる HTTPRequest オブジェクトのデバッグ フラグが設定されます。

次の例では、スプレッドシートのリストをリクエストしたときに、スプレッドシート サーバーから送信された HTTP ヘッダーをエコーします。

#!/usr/bin/python

import gdata.spreadsheet.service

client
= gdata.spreadsheet.service.SpreadsheetsService()
client
.debug = True

client
.ClientLogin(email, password)

feed
= client.GetSpreadsheetsFeed()

for entry in feed.entry:
 
print entry.title.text

コンソールに次のような出力が表示されます。

reply: 'HTTP/1.1 200 OK\r\n'
header: Content-Type: application/atom+xml; charset=UTF-8
header: Last-Modified: Thu, 07 Jun 2007 18:22:35 GMT
header: Cache-Control: max-age=0, must-revalidate, private
header: Transfer-Encoding: chunked
...
header: Date: Thu, 07 Jun 2007 18:22:35 GMT
header: Server: GFE/1.3

挿入や更新などのオペレーションを追加すると、対応するリクエスト データがコンソールにエコーバックされます。

まとめ

この簡単なチュートリアルでは、Google Data API クライアント ライブラリを使用する Java、.NET、Python プログラムに基本的なロギング機能を追加する方法について説明しました。これらの手法は、HTTP 交換をデバッグする必要があるが、パケット スニファにアクセスできない場合に役立ちます。これらの例は、ほんの一部にすぎません。これらの言語に存在するロギング メカニズムの多くは、ここで説明するよりもはるかに強力です。ロギングまたは Google Data API の詳細については、以下のリソースをご覧ください。

この記事で説明するクライアント ライブラリについては、次のページをご覧ください。

関連するナレッジベース アイテム:

ディスカッション グループ: 多数のグループがあり、Google Data API のロールアウトが進むにつれてさらに増える予定です。グループは常に監視されています。

ご質問やご提案がございましたら、お気軽にお問い合わせください。ディスカッション グループに参加して、投稿を開始します。