對 Google Data API 用戶端進行偵錯:瞭解程式內部流量

Jeffrey Scudder,Google Data API 團隊
2007 年 6 月

簡介

有時候,沒有取代電線的選擇。在使用使用 Google Data API 等網路服務的軟體編寫這類軟體時,更是如此,因為有許多作業涉及發出 HTTP 要求。 當所有其他條件都失敗時,您可以查看實際傳輸和接收的位元組,驗證程式是否如預期運作。Google Data API 的許多用戶端程式庫都設有顯示 HTTP 流量的偵錯模式。如果您無法存取 SreSharkFiddler 這類封包剪接程式,這項功能就特別實用。

我無法計算我的程式不正確的出現次數,只會在檢查封包追蹤記錄中發現多餘的換行字元或名稱有誤的 HTTP 標頭。您在不查看 HTTP 流量的情況下,針對網路服務進行程式設計,就如同嘗試讓眼睛閉合的針線一樣。

但是,您可能會在自己遇到封包加密工具無法使用或不足以處理加密封包的情況下遇到自己。只要運用程式化的紀錄機制,您就能克服這項限制。只要運用這些記錄設備,您就能看到部分交換資料 (但不是全部的資料),即使是加密的 HTTPS 資料或遠端執行的程式碼也一樣。

在本文中,我已使用適用於 Java.NETPython 的 Google Data API 用戶端程式庫,以 3 種語言編寫範例診斷程式碼。在每個範例中,我開啟記錄或偵錯功能,使用用戶端登入資訊進行驗證,然後取得 Google 試算表的清單並列印這些標題。

Java

您可以使用 java.util.logging 類別,為用戶端程式庫中的幾個重要物件設定記錄層級 (並因此公開流量資料)。在以下範例中,我選擇查看 HTTP 標頭和 XML 剖析器的活動,以完整掌握線路的運作情形。

Google Data Java 用戶端程式庫有獨立的類別來處理 HTTP 要求和 XML 剖析;因此,我必須建立兩個記錄器物件,每個類別各一個:com.google.gdata.client.http.HttpGDataRequest 會處理 HTTP 流量,而 com.google.gdata.util.XmlParser 則負責處理 XML 剖析。

記錄器執行個體會記錄 HttpGDataRequestXmlParser 的活動,而您可以控制每個記錄器輸出內容的細節層級。本示範選擇的是 HttpGDataRequestXmlParser 物件產生的「所有」事件。

建立並設定記錄器後,我需要告知他們收到班級收到事件時該怎麼做。目前,我想將所有記錄資訊寫入主控台,所以建立 ConsoleHandler 並將其加入兩個記錄器。

以下是我的程式碼範例:

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

這些記錄可能會變得相當龐大,因此建議您設定記錄器層級的選項。您也可以建立 FileHandler 而非 ConsoleHandler,以便儲存記錄資料以供日後使用。

當然,如果 Java 不是您的行李,您可以試試 .NET。

.NET

如要擷取 .NET 用戶端程式庫中的 HTTP 流量,您可以將用戶端的預設要求工廠替換為 GDataLoggingRequestFactory

.NET 程式庫中的 HTTP 要求是由每個 Service 物件內的 GDataRequestFactory 建立。一般要求工廠不會執行任何記錄,但 GDataLoggingRequestFactoryGDataRequestFactory 的子類別,並內建記錄功能。您可以設定 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。我們會主動監控這些群組。

如有任何問題或建議,我們十分樂意聽取您的建議。加入討論群組,開始張貼文章。