Gỡ lỗi ứng dụng API dữ liệu của Google: Khám phá lưu lượng truy cập từ 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ế cho việc xem nội dung nào sẽ xuất hiện. Đ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 thực hiện các yêu cầu HTTP. Khi tất cả những cách khác đều không thành công, bạn có thể xác minh rằng chương trình của bạn đang làm điều bạn mong đợi bằng cách xem các byte đã truyền và đã nhận thực tế. Nhiều thư viện ứng dụng cho API Dữ liệu của Google có chế độ gỡ lỗi để 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 khám phá gói như WireShark hoặc Fiddler.

Tôi không thể đếm được số lần mà tôi có thể tuyên bố chương trình của mình là chính xác, chỉ để kiểm tra một dấu vết gói phát hiện có thêm một ký tự dòng mới hoặc tiêu đề HTTP bị đặt tên sai. Việc 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 chèn một cây kim vào mắt của bạn.

Tuy nhiên, bạn có thể thấy mình trong tình huống không có sẵn tiện ích đọc gói. Đừng bao giờ sợ hãi – bạn có thể vượt qua giới hạn 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ố dữ liệu đã trao đổi (nếu không phải tất cả) ngay cả cho dữ liệu HTTPS đã mã hóa hoặc mã chạy từ xa.

Đối với 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 API dữ liệu của Google 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 thông tin đăng nhập ứng dụng, sau đó lấy danh sách Bảng tính Google và in tiêu đề của chúng.

Java

Bạn có thể sử 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 vài đối tượng chính trong thư viện ứng dụng. Trong ví dụ bên dưới, 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ái nhìn đầy đủ về nội dung di chuyển qua dây.

Thư viện ứng dụng Google Data Java có các lớp riêng để 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 Logger, mỗi đối tượng cho một 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 phiên bản trình ghi nhật ký sẽ ghi lại các hoạt động cho HttpGDataRequestXmlParser, đồng thời bạn có thể kiểm soát mức độ chi tiết của dữ liệu đầu ra của mỗi trình ghi nhật ký. Đối với 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 họ biết việc cần làm khi họ nhận được một sự kiện từ các lớp của họ. Hiện tại, tôi muốn ghi tất cả thông tin ghi nhật ký vào bảng điều khiển, vì vậy, tôi tạo một ConsoleHandler rồi thêm thông tin đó vào cả hai trình ghi nhật ký của mình.

Đâ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ớt một số phần không 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 có thể chọn nhiều hơn trong việc đặt các cấp độ của Trình ghi nhật ký. Bạn cũng có thể tạo FileHandler thay vì ConsoleHandler để cho phép bạn lưu trữ dữ liệu nhật ký để sử dụng sau này.

Tất nhiên, nếu Java không phải là túi của bạn, bạn có thể thử .NET.

.NET

Để nắm bắt 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 bên 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, là một lớp con của GDataRequestFactory, được tích hợp 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ý thu được chứa các yêu cầu và phản hồi XML. Sau đây là một ví dụ viết tắt mà tôi đã định dạng bằ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 thích sử dụng Python.

Python

Để chụp 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 cho 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 viên gỡ lỗi mà bạn có thể đặt thành True.

Việc đặt 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ụ sẽ lặp lại tiêu đề HTTP gửi từ máy chủ bảng tính khi bạn yêu cầu danh sách các bảng tí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 khác, 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 nhắc lại trong 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. Các kỹ thuật này có thể hữu ích nếu bạn cần gỡ lỗi các lượt trao đổi HTTP, nhưng không có quyền truy cập vào một tiện ích gói. Tôi mới chỉ mới bắt đầu với những ví dụ này. Nhiều cơ chế ghi nhật ký ở những ngôn ngữ này có hiệu quả hơn rất nhiều so với những gì được thể hiện ở đây. Nếu bạn muốn biết thêm thông tin về cách ghi nhật ký hoặc API Google Data, hãy xem danh sách tài nguyên dưới đây.

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 cơ bản liên quan đến kiến thức:

Nhóm thảo luận: Chúng tôi có khá nhiều nhóm thảo luận, và sẽ có nhiều nhóm thảo luận hơn khi cho ra mắt nhiều API Dữ liệu của Google hơn. Chúng tôi chủ động theo dõi các nhóm.

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