Google Veri API'si İstemcilerinde Hata Ayıklama: Programınızdaki Trafiği Keşfetme

Jeffrey Scudder, Google Veri API'leri Ekibi
Haziran 2007

Giriş

Bazen neyin işe yaradığını görmek için başka bir yol yoktur. Bu durum, özellikle Google Data API'leri gibi web hizmetlerini kullanan yazılımlar yazarken geçerlidir. Bu tür yazılımlarda birçok işlem HTTP istekleri göndermeyi içerir. Diğer tüm yöntemler başarısız olduğunda, gerçek iletilen ve alınan baytları görerek programınızın beklediğiniz şekilde çalıştığını doğrulayabilirsiniz. Google Veri API'leri için istemci kitaplıklarının birçoğunda HTTP trafiğini gösteren bir hata ayıklama modu bulunur. Bu özellik, özellikle WireShark veya Fiddler gibi bir paket yakalayıcıya erişiminiz olmadığında kullanışlıdır.

Programımın doğru olduğuna yemin edebileceğim ancak bir paket izini incelediğimde fazladan bir yeni satır karakteri veya yanlış adlandırılmış bir HTTP başlığı olduğunu gördüğüm zamanların sayısını hatırlamıyorum. HTTP trafiğine bakmadan bir web hizmetine karşı programlama yapmak, gözleriniz kapalıyken iğneye iplik geçirmeye çalışmaya benzer.

Ancak paket koklayıcının kullanılamadığı veya şifrelenmiş paketlerle başa çıkmak için yetersiz olduğu bir durumla karşılaşabilirsiniz. Endişelenmeyin. Program içi bazı günlük kaydı mekanizmalarından yararlanarak bu sınırlamayı aşabilirsiniz. Bu günlük kaydı olanaklarını kullanarak, şifrelenmiş HTTPS verileri veya uzaktan çalışan kodlar için bile, değiştirilen verilerin bir kısmını (tümü olmasa da) görebilirsiniz.

Bu makale için, Java, .NET ve Python için Google Veri API'si istemci kitaplıklarını kullanarak 3 dilde örnek teşhis kodu yazdım. Her örnekte, günlük kaydını veya hata ayıklamayı etkinleştiriyorum, istemci girişiyle kimlik doğruluyorum, ardından Google E-Tablolarımın listesini alıp başlıklarını yazdırıyorum.

Java

İstemci kitaplığındaki birkaç önemli nesne için günlük kaydı düzeylerini ayarlamak (ve dolayısıyla trafik verilerini kullanıma sunmak) üzere java.util.logging sınıflarını kullanabilirsiniz. Aşağıdaki örnekte, kablo üzerinden iletilenleri tam olarak görmek için HTTP üstbilgilerine ve XML ayrıştırıcının etkinliklerine bakmayı tercih ettim.

Google Data Java istemci kitaplığında HTTP isteklerini ve XML ayrıştırmayı işlemek için ayrı sınıflar bulunur. Bu nedenle, her sınıf için bir tane olmak üzere iki Logger nesnesi oluşturmam gerekir: com.google.gdata.client.http.HttpGDataRequest HTTP trafiğini işlerken com.google.gdata.util.XmlParser XML ayrıştırmadan sorumludur.

Günlükçü örnekleri, HttpGDataRequest ve XmlParser için etkinlikleri kaydeder. Ayrıca, her günlükçünün çıkışının ayrıntı düzeyini kontrol edebilirsiniz. Bu gösterimde, HttpGDataRequest ve XmlParser nesneleri tarafından oluşturulan tüm etkinlikleri görüntülemeyi seçtim.

Günlükçülerimi oluşturup yapılandırdıktan sonra, sınıflarından bir etkinlik aldıklarında ne yapmaları gerektiğini söylemem gerekir. Şimdilik tüm günlük bilgilerini konsola yazmak istiyorum. Bu nedenle bir ConsoleHandler oluşturup her iki Logger'ıma da ekliyorum.

Örnek kodum:

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());
       
}
   
}
}

Bu programı çalıştırdığınızda konsolda şuna benzer bir şey görürsünüz (daha az ilginç olan bazı bölümleri kestim):

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

Bu günlükler oldukça büyük olabilir. Bu nedenle, günlükçülerin düzeylerini ayarlarken daha seçici olmanız gerekebilir. Günlük verilerini daha sonra kullanmak üzere saklamanıza olanak tanımak için ConsoleHandler yerine FileHandler da oluşturabilirsiniz.

Java'yı tercih etmiyorsanız .NET'i deneyebilirsiniz.

.NET

.NET istemci kitaplığındaki HTTP trafiğini yakalamak için istemcideki varsayılan istek fabrikasını GDataLoggingRequestFactory ile değiştirebilirsiniz.

.NET kitaplığındaki HTTP istekleri, her Hizmet nesnesinin içinde bulunan GDataRequestFactory tarafından oluşturulur. Normal istek fabrikaları herhangi bir günlük kaydı oluşturmaz ancak GDataLoggingRequestFactory, GDataRequestFactory sınıfının bir alt sınıfı olduğundan günlük kaydı oluşturma özelliği yerleşiktir. CombinedFileName değerini ayarlayarak günlük dosyasının tam yolunu belirtebilirsiniz.

İstek fabrikanızı ayarladıktan sonra hizmet nesnesinin RequestFactory özelliğini ayarlayarak hizmet nesnenizdeki istek fabrikasını değiştirmeniz gerekir. Kodunuz aşağıdaki gibi görünebilir:

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();
       
}
   
}
}

Sonuçta elde edilen günlük dosyası, XML isteklerini ve yanıtlarını içerir. Aşağıda, tidy kullanılarak biçimlendirilmiş kısaltılmış bir örnek verilmiştir.

<?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>

Ancak belki de komut dosyası dillerine çok meraklısınız ve Python'ı kullanmayı tercih ediyorsunuz.

Python

Python istemci kitaplığındaki HTTP trafiğini yakalamak için HTTP istemcisinde hata ayıklama modunu etkinleştirerek HTTP başlığı trafiğini konsola yansıtabilirsiniz. Hizmet nesnesinde, True olarak ayarlayabileceğiniz bir hata ayıklama üyesi bulunur.

Hata ayıklamayı doğru olarak ayarlamak, hizmet nesnesinde bulunan temel HTTPRequest nesnesindeki hata ayıklama işaretini ayarlar.

Aşağıda, e-tablolarınızın listesini istediğinizde e-tablolar sunucusundan gönderilen HTTP üstbilgilerini yansıtacak bir örnek verilmiştir.

#!/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

Konsolunuzda şuna benzer bir çıkış görürsünüz:

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

Ekleme veya güncelleme gibi ek işlemler gerçekleştirdikçe, ilgili istek verilerinin konsolunuza yansıtıldığını görürsünüz.

Sonuç

Bu kısa eğitimde, Google Data API istemci kitaplıklarını kullanan bir Java, .NET veya Python programına temel günlük işlevini nasıl ekleyebileceğiniz gösterilmiştir. Bu teknikler, HTTP değişimlerinde hata ayıklamanız gerektiğinde ancak paket yakalayıcıya erişiminiz olmadığında yararlı olabilir. Bu örneklerle yalnızca konunun yüzeyini çizdim. Bu dillerde bulunan birçok günlük kaydı mekanizması, burada gösterilenlerden çok daha güçlüdür. Günlüğe kaydetme veya Google Veri API'leri hakkında daha fazla bilgi edinmek isterseniz aşağıdaki kaynak listesini inceleyin.

Bu makalede ele alınan istemci kitaplıklarını şu sayfalarda bulabilirsiniz:

İlgili bilgi bankası öğeleri:

Tartışma grupları: Birkaç tane var ve daha fazla Google Veri API'si kullanıma sunuldukça yenileri ekleniyor. Grupları aktif olarak izliyoruz.

Sorularınız veya önerileriniz varsa lütfen bize bildirin. Tartışma grubuna katılarak yayın yapmaya başlayın.