Gỡ lỗi Ứng dụng Google Data API: Khám phá lưu lượng truy cập trong chương trình của bạn

Jeffrey Scudder, Nhóm API dữ liệu của Google
Tháng 6 năm 2007

Giới thiệu

Đôi khi, không có gì thay thế được việc xem những gì diễn ra trên mạng. Điều này đặc biệt đúng khi viết phần mềm sử dụng các dịch vụ web như Google Data API, trong đó nhiều thao tác liên quan đến việc đưa ra các yêu cầu HTTP. Nếu không được, bạn có thể xác minh rằng chương trình của mình đang thực hiện những gì bạn mong đợi bằng cách xem các byte thực tế đã truyền và nhận. Nhiều thư viện ứng dụng cho Google Data API có chế độ gỡ lỗi giúp hiển thị lưu lượng truy cập HTTP. Điều này đặc biệt hữu ích khi bạn không có quyền truy cập vào một trình theo dõi gói như WireShark hoặc Fiddler.

Tôi không thể đếm được số lần tôi có thể thề rằng chương trình của mình là chính xác, chỉ để thấy rằng khi kiểm tra dấu vết gói, có một ký tự dòng mới thừa hoặc một tiêu đề HTTP bị đặt tên sai. Lập trình dựa trên một dịch vụ web mà không xem xét lưu lượng truy cập HTTP có thể giống như việc cố gắng xâu kim khi mắt bạn nhắm nghiền.

Tuy nhiên, bạn có thể gặp phải tình huống không có sẵn trình theo dõi gói hoặc trình theo dõi gói không đủ khả năng xử lý các gói được mã hoá. Đừng lo lắng, bạn có thể khắc phục hạn chế này bằng cách tận dụng một số cơ chế ghi nhật ký trong chương trình. Bằng cách sử dụng các cơ sở ghi nhật ký này, bạn có thể thấy một số (nếu không phải tất cả) dữ liệu đã trao đổi, ngay cả đối với dữ liệu HTTPS được mã hoá hoặc mã đang chạy từ xa.

Trong bài viết này, tôi đã viết mã chẩn đoán mẫu bằng 3 ngôn ngữ bằng cách sử dụng thư viện ứng dụng Google Data API cho Java, .NETPython. Trong mỗi ví dụ, tôi bật tính năng ghi nhật ký hoặc gỡ lỗi, xác thực bằng cách đăng nhập bằng ứng dụng và sau đó lấy danh sách các Google Trang tính của tôi rồi in tiêu đề của chúng.

Java

Bạn có thể dùng các lớp java.util.logging để đặt cấp độ ghi nhật ký (và do đó hiển thị dữ liệu lưu lượng truy cập) cho một số đối tượng chính trong thư viện ứng dụng khách. Trong ví dụ dưới đây, tôi chọn xem tiêu đề HTTP và các hoạt động của trình phân tích cú pháp XML để có được cái nhìn hoàn chỉnh về những gì đang truyền qua mạng.

Thư viện ứng dụng Google Data Java có các lớp riêng biệt để xử lý các yêu cầu HTTP và phân tích cú pháp XML; do đó, tôi cần tạo hai đối tượng Trình ghi nhật ký, một cho mỗi lớp: com.google.gdata.client.http.HttpGDataRequest xử lý lưu lượng truy cập HTTP trong khi com.google.gdata.util.XmlParser chịu trách nhiệm phân tích cú pháp XML.

Các thực thể trình ghi nhật ký sẽ ghi lại hoạt động cho HttpGDataRequestXmlParser, đồng thời bạn có thể kiểm soát mức độ chi tiết của đầu ra của từng trình ghi nhật ký. Trong bản minh hoạ này, tôi đã chọn xem tất cả các sự kiện do các đối tượng HttpGDataRequestXmlParser tạo ra.

Sau khi tạo và định cấu hình Trình ghi nhật ký, tôi cần cho chúng biết phải làm gì khi nhận được một sự kiện từ các lớp của chúng. Hiện tại, tôi muốn ghi tất cả thông tin ghi nhật ký ra bảng điều khiển, vì vậy, tôi tạo một ConsoleHandler và thêm nó vào cả hai Logger.

Sau đây là mã mẫu của tôi:

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

Khi chạy chương trình này, bạn sẽ thấy nội dung như sau trên bảng điều khiển (tôi đã cắt bỏ một số phần ít thú vị):

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

Các nhật ký này có thể khá lớn, vì vậy, bạn nên chọn lọc hơn khi đặt cấp độ của Trình ghi nhật ký. Bạn cũng có thể tạo một FileHandler thay vì ConsoleHandler để cho phép bạn lưu trữ dữ liệu nhật ký để sử dụng sau.

Tất nhiên, nếu không thích Java, bạn có thể thử .NET.

.NET

Để ghi lại lưu lượng truy cập HTTP trong thư viện ứng dụng .NET, bạn có thể thay thế nhà máy yêu cầu mặc định trong ứng dụng bằng một GDataLoggingRequestFactory.

Các yêu cầu HTTP trong thư viện .NET được tạo bởi GDataRequestFactory nằm trong mỗi đối tượng Dịch vụ. Các nhà máy yêu cầu thông thường không thực hiện bất kỳ hoạt động ghi nhật ký nào nhưng GDataLoggingRequestFactory (một lớp con của GDataRequestFactory) có sẵn tính năng ghi nhật ký. Bạn có thể chỉ định đường dẫn đầy đủ của tệp nhật ký bằng cách đặt CombinedFileName.

Sau khi thiết lập nhà máy yêu cầu, bạn cần thay thế nhà máy yêu cầu trong đối tượng Dịch vụ bằng cách đặt RequestFactory của đối tượng dịch vụ. Mã của bạn có thể có dạng như sau:

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

Tệp nhật ký kết quả chứa các yêu cầu và phản hồi XML. Sau đây là một ví dụ rút gọn mà tôi đã định dạng bằng cách sử dụng 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>

Nhưng có lẽ bạn thực sự thích ngôn ngữ kịch bản và bạn muốn sử dụng Python.

Python

Để ghi lại lưu lượng truy cập HTTP trong thư viện ứng dụng Python, bạn có thể lặp lại lưu lượng truy cập tiêu đề HTTP vào bảng điều khiển bằng cách bật chế độ gỡ lỗi trong ứng dụng HTTP. Đối tượng dịch vụ có một thành phần gỡ lỗi mà bạn có thể đặt thành True.

Việc đặt giá trị gỡ lỗi thành true sẽ đặt cờ gỡ lỗi trong đối tượng HTTPRequest cơ bản có trong đối tượng dịch vụ.

Sau đây là một ví dụ minh hoạ việc phản hồi các tiêu đề HTTP được gửi từ máy chủ bảng tính khi bạn yêu cầu danh sách bảng tính của mình.

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

Bạn sẽ thấy nội dung như sau trên bảng điều khiển:

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

Khi thực hiện các thao tác bổ sung, chẳng hạn như chèn hoặc cập nhật, bạn sẽ thấy dữ liệu yêu cầu tương ứng được phản hồi vào bảng điều khiển.

Kết luận

Hướng dẫn ngắn này minh hoạ cách bạn có thể thêm chức năng ghi nhật ký cơ bản vào chương trình Java, .NET hoặc Python sử dụng thư viện ứng dụng Google Data API. Những kỹ thuật này có thể hữu ích nếu bạn cần gỡ lỗi các hoạt động trao đổi HTTP nhưng không có quyền truy cập vào một trình theo dõi gói. Tôi chỉ mới đề cập đến một số ví dụ. Nhiều cơ chế ghi nhật ký có trong các ngôn ngữ này mạnh hơn nhiều so với những gì được trình bày ở đây. Nếu bạn muốn biết thêm thông tin về việc ghi nhật ký hoặc Google Data API, hãy xem danh sách tài nguyên bên dưới.

Bạn có thể tìm thấy các thư viện ứng dụng được đề cập trong bài viết này trên những trang sau:

Các mục liên quan trong cơ sở kiến thức:

Nhóm thảo luận: Chúng tôi có khá nhiều nhóm và sẽ có thêm nhiều nhóm nữa khi các API dữ liệu của Google được triển khai. Chúng tôi chủ động giám sát các nhóm.

Nếu bạn có câu hỏi hoặc đề xuất, tôi rất mong nhận được ý kiến của bạn. Tham gia nhóm thảo luận và bắt đầu đăng bài.