การแก้ไขข้อบกพร่องของไคลเอ็นต์ Google Data API: การสํารวจการเข้าชมจากภายในโปรแกรม

Jeffrey Scudder, ทีม Google Data API
มิถุนายน 2007

บทนำ

บางครั้งก็ไม่มีอะไรมาแทนที่การดูสิ่งที่ส่งผ่านสายได้ โดยเฉพาะอย่างยิ่งเมื่อเขียนซอฟต์แวร์ที่ใช้บริการบนเว็บ เช่น Google Data APIs ซึ่งการดำเนินการจำนวนมากเกี่ยวข้องกับการส่งคำขอ HTTP หากวิธีอื่นๆ ไม่ได้ผล คุณสามารถยืนยันว่าโปรแกรมทำงานตามที่คาดไว้ได้โดยดูไบต์ที่ส่งและรับจริง ไลบรารีของไคลเอ็นต์จำนวนมากสำหรับ Google Data API มีโหมดการแก้ไขข้อบกพร่องซึ่งแสดงการรับส่งข้อมูล HTTP ซึ่งจะเป็นประโยชน์อย่างยิ่งเมื่อคุณไม่มีสิทธิ์เข้าถึงเครื่องดมแพ็กเก็ต เช่น WireShark หรือ Fiddler

ฉันนับครั้งที่ฉันสาบานได้ว่าโปรแกรมของฉันถูกต้องไม่ได้ แต่เมื่อตรวจสอบการติดตามแพ็กเก็ตก็พบว่ามีอักขระขึ้นบรรทัดใหม่เพิ่มเติมหรือส่วนหัว HTTP ที่ตั้งชื่อผิด การเขียนโปรแกรมกับเว็บเซอร์วิสโดยไม่ดูการรับส่งข้อมูล HTTP ก็เหมือนกับการพยายามร้อยเข็มโดยที่หลับตา

อย่างไรก็ตาม คุณอาจพบว่าตัวเองอยู่ในสถานการณ์ที่ไม่มีเครื่องดมแพ็กเก็ต หรือเครื่องดมแพ็กเก็ตไม่เพียงพอที่จะจัดการกับแพ็กเก็ตที่เข้ารหัส ไม่ต้องกังวล คุณสามารถหลีกเลี่ยงข้อจำกัดนี้ได้โดยใช้ประโยชน์จากกลไกการบันทึกในโปรแกรมบางอย่าง การใช้เครื่องมือบันทึกเหล่านี้จะช่วยให้คุณเห็นข้อมูลที่แลกเปลี่ยนบางส่วนหรือทั้งหมด แม้จะเป็นข้อมูล HTTPS ที่เข้ารหัสหรือโค้ดที่เรียกใช้จากระยะไกลก็ตาม

ในบทความนี้ ฉันได้เขียนโค้ดการวินิจฉัยตัวอย่างใน 3 ภาษาโดยใช้ไลบรารีของไคลเอ็นต์ Google Data API สำหรับ Java .NET และ Python ในแต่ละตัวอย่าง ฉันจะเปิดการบันทึกหรือการแก้ไขข้อบกพร่อง ทำการตรวจสอบสิทธิ์โดยใช้การเข้าสู่ระบบของไคลเอ็นต์ แล้วรับ รายการสเปรดชีตใน Google และพิมพ์ชื่อของสเปรดชีตเหล่านั้น

Java

คุณสามารถใช้java.util.loggingคลาสเพื่อตั้งค่าระดับการบันทึก (และแสดงข้อมูลการเข้าชม) สำหรับออบเจ็กต์หลัก 2-3 รายการใน ไลบรารีของไคลเอ็นต์ ในตัวอย่างด้านล่าง ฉันเลือกดูส่วนหัว HTTP และกิจกรรมของตัวแยกวิเคราะห์ XML เพื่อให้เห็นภาพรวมทั้งหมดของสิ่งที่ ส่งผ่านสาย

ไลบรารีไคลเอ็นต์ Java ของ Google Data มีคลาสแยกต่างหากสำหรับ จัดการคำขอ HTTP และการแยกวิเคราะห์ XML ดังนั้นฉันจึงต้องสร้างออบเจ็กต์ Logger 2 รายการ รายการหนึ่งสำหรับแต่ละคลาส com.google.gdata.client.http.HttpGDataRequest จัดการการรับส่งข้อมูล HTTP ขณะที่ com.google.gdata.util.XmlParser มีหน้าที่ แยกวิเคราะห์ XML

อินสแตนซ์ของเครื่องบันทึกจะบันทึกกิจกรรมสำหรับ HttpGDataRequest และ XmlParser และคุณสามารถควบคุม ระดับรายละเอียดของเอาต์พุตของเครื่องบันทึกแต่ละรายการได้ สำหรับการสาธิตนี้ ฉันเลือกที่จะดูเหตุการณ์ทั้งหมดที่สร้างโดยออบเจ็กต์ HttpGDataRequest และ XmlParser

เมื่อสร้างและกำหนดค่าเครื่องบันทึกแล้ว ฉันต้องบอกให้เครื่องบันทึกทำอะไรเมื่อได้รับเหตุการณ์จากคลาส ตอนนี้ฉันต้องการเขียนข้อมูลการบันทึกทั้งหมด ไปยังคอนโซล จึงสร้าง ConsoleHandler และเพิ่มลงใน Logger ทั้ง 2 รายการ

โค้ดตัวอย่างของฉันมีดังนี้

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

หากต้องการบันทึกการรับส่งข้อมูล HTTP ในไลบรารีของไคลเอ็นต์ .NET คุณสามารถแทนที่โรงงานคำขอเริ่มต้นในไคลเอ็นต์ด้วย GDataLoggingRequestFactory

คำขอ HTTP ในไลบรารี .NET สร้างขึ้นโดย GDataRequestFactory ซึ่งอยู่ภายในออบเจ็กต์บริการแต่ละรายการ โรงงานคำขอปกติไม่ได้ทำการบันทึกใดๆ แต่ GDataLoggingRequestFactory ซึ่งเป็นคลาสย่อยของ GDataRequestFactory มีการบันทึกในตัว คุณระบุเส้นทางแบบเต็มของ ไฟล์บันทึกได้โดยตั้งค่า CombinedFileName

หลังจากตั้งค่า Request Factory แล้ว คุณต้องแทนที่ Request Factory ในออบเจ็กต์บริการโดยตั้งค่า 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

หากต้องการบันทึกการรับส่งข้อมูล HTTP ในไลบรารีของไคลเอ็นต์ Python คุณสามารถแสดงการรับส่งข้อมูลส่วนหัว HTTP ในคอนโซลได้โดยเปิดโหมดแก้ไขข้อบกพร่องในไคลเอ็นต์ HTTP ออบเจ็กต์บริการ มีสมาชิกการแก้ไขข้อบกพร่องซึ่งคุณตั้งค่าเป็น 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

เมื่อคุณดำเนินการเพิ่มเติม เช่น การแทรกหรือการอัปเดต คุณจะเห็นข้อมูลคำขอที่เกี่ยวข้องแสดงในคอนโซล

บทสรุป

บทแนะนำสั้นๆ นี้ได้แสดงให้เห็นวิธีเพิ่มฟังก์ชันการบันทึกพื้นฐานลงในโปรแกรม Java, .NET หรือ Python ที่ใช้ไลบรารีของไคลเอ็นต์ Google Data API เทคนิคเหล่านี้มีประโยชน์ในกรณีที่คุณต้องแก้ไขข้อบกพร่องของ HTTP Exchange แต่ไม่มีสิทธิ์เข้าถึงเครื่องดมแพ็กเก็ต ตัวอย่างเหล่านี้เป็นเพียงส่วนหนึ่งเท่านั้น กลไกการบันทึก ที่มีอยู่ในภาษาเหล่านี้ มีประสิทธิภาพมากกว่าที่แสดงที่นี่มาก หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกหรือ Google Data APIs โปรดดู รายการแหล่งข้อมูลด้านล่าง

คุณดูไลบรารีของไคลเอ็นต์ที่กล่าวถึงในบทความนี้ได้ในหน้าเว็บต่อไปนี้

รายการฐานความรู้ที่เกี่ยวข้อง

กลุ่มสนทนา: เรามีกลุ่มสนทนาอยู่หลายกลุ่ม และจะมีเพิ่มขึ้นเรื่อยๆ เมื่อเราเปิดตัว Google Data API เพิ่มเติม เราตรวจสอบกลุ่มอย่างสม่ำเสมอ

หากคุณมีคำถามหรือข้อเสนอแนะ เรายินดีรับฟัง เข้าร่วมกลุ่มสนทนา แล้วเริ่มโพสต์