Google Data API クライアントのデバッグ: プログラム内のトラフィックを確認する

Google Data API チーム Jeffrey Scudder
2007 年 6 月

はじめに

ケーブルで何を確認するかは、見当たらないこともあります。これは、Google Data API のようなウェブサービスを使用するソフトウェアを記述する場合に特に当てはまります。こうしたオペレーションでは、多くのオペレーションで HTTP リクエストが行われます。他のいずれの方法でも検証できない場合は、実際の送受信バイト数を確認すると、プログラムが想定どおりに動作するかどうかを確認できます。Google Data API のクライアント ライブラリの多くは、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 オブジェクトによって生成されたすべてのイベントを表示することを選択しました。

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

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

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

これらのログは非常に大きくなる可能性があるため、Loggers のレベルの設定には厳密な制限を設けることをおすすめします。また、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 に設定できます。

debug を 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 は増え続けており、今後も Google Data API の導入を進めていく予定です。Google はグループを積極的にモニタリングしています。

ご質問やご提案がありましたら、ぜひお問い合わせください。ディスカッション グループにアクセスして投稿を開始します。