Июнь 2007 г.
Введение
Иногда нет альтернативы наблюдению за тем, что проходит по сети. Это особенно актуально при написании программного обеспечения, использующего веб-сервисы, такие как API Google Data, где множество операций связано с HTTP-запросами. Если же всё остальное не помогает, вы можете убедиться, что ваша программа работает так, как и ожидалось, посмотрев фактические переданные и полученные байты. Многие клиентские библиотеки для API Google Data имеют режим отладки, отображающий HTTP-трафик. Это особенно полезно, когда у вас нет доступа к анализатору пакетов, такому как WireShark или Fiddler .
Не могу сосчитать, сколько раз я мог поклясться, что моя программа верна, но при проверке трассировки пакета обнаруживал лишний символ перевода строки или неправильно названный HTTP-заголовок. Программирование веб-сервиса без анализа HTTP-трафика похоже на попытку вдеть нитку в иголку с заклеенными глазами.
Однако вы можете оказаться в ситуации, когда анализатор пакетов недоступен или не справляется с обработкой зашифрованных пакетов. Не волнуйтесь — это ограничение можно обойти, используя встроенные механизмы журналирования. Используя эти механизмы, вы можете увидеть часть, если не все, передаваемые данные, даже зашифрованные HTTPS-данные или удалённо запущенный код.
Для этой статьи я написал пример диагностического кода на трёх языках, используя клиентские библиотеки Google Data API для Java , .NET и Python . В каждом примере я включаю ведение журнала или отладку, прохожу аутентификацию, используя клиентский логин, а затем получаю список своих Google Таблиц и вывожу их заголовки.
Ява
Вы можете использовать классы java.util.logging
для настройки уровней логирования (и, следовательно, предоставления данных о трафике) для нескольких ключевых объектов клиентской библиотеки. В примере ниже я решил анализировать HTTP-заголовки и активность XML-парсера, чтобы получить полное представление о том, что передается по сети.
Клиентская библиотека Google Data Java имеет отдельные классы для обработки HTTP-запросов и анализа XML. Таким образом, мне нужно создать два объекта Logger, по одному для каждого класса: com.google.gdata.client.http.HttpGDataRequest
обрабатывает HTTP-трафик, а com.google.gdata.util.XmlParser
отвечает за анализ XML.
Экземпляры логгера будут регистрировать действия HttpGDataRequest
и XmlParser
, и вы можете управлять уровнем детализации выходных данных каждого логгера. Для этой демонстрации я решил просмотреть все события, создаваемые объектами HttpGDataRequest
и XmlParser
.
После создания и настройки логгеров мне нужно указать им, что делать при получении события от своих классов. Сейчас я хочу выводить всю информацию журнала в консоль, поэтому я создаю 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
Эти журналы могут быть довольно большими, поэтому вам может потребоваться более избирательная настройка уровней Loggers. Вы также можете создать FileHandler
вместо ConsoleHandler
, чтобы хранить данные журнала для последующего использования.
Конечно, если Java вам не по душе, вы можете попробовать .NET.
.СЕТЬ
Чтобы захватить HTTP-трафик в клиентской библиотеке .NET, можно заменить фабрику запросов по умолчанию в клиенте на GDataLoggingRequestFactory
.
HTTP-запросы в библиотеке .NET создаются фабрикой GDataRequestFactory
, которая находится внутри каждого объекта Service. Обычные фабрики запросов не ведут журналирование, но GDataLoggingRequestFactory
, подкласс GDataRequestFactory
, имеет встроенную функцию журналирования. Вы можете указать полный путь к файлу журнала, установив параметр CombinedFileName
.
После настройки фабрики запросов вам необходимо заменить фабрику запросов в объекте Service, установив свойство RequestFactory
объекта Service. Код может выглядеть примерно так:
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.
Питон
Чтобы перехватить HTTP-трафик в клиентской библиотеке Python, можно вывести HTTP-заголовок в консоль, включив режим отладки в HTTP-клиенте. У объекта службы есть элемент debug, которому можно присвоить значение True .
Установка значения debug в 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-обмен, но у вас нет доступа к анализатору пакетов. Я лишь поверхностно рассмотрел эти примеры. Многие механизмы журналирования, представленные в этих языках, гораздо мощнее, чем представленные здесь. Если вам нужна дополнительная информация о журналировании или Google Data API, ознакомьтесь со списком ресурсов ниже.
Клиентские библиотеки, рассматриваемые в этой статье, можно найти на следующих страницах:
Сопутствующие элементы базы знаний:
- Как получить информацию журнала HTTP в клиентской библиотеке Java?
- Как получить информацию журнала HTTP в клиентской библиотеке .NET?
- Какие есть хорошие инструменты для отладки HTTP?
- Что такое API Google Таблиц?
Группы для обсуждения: у нас их довольно много, и их будет становиться всё больше по мере внедрения новых API Google Data. Мы активно следим за группами.
Если у вас есть вопросы или предложения, буду рад их услышать. Заходите в группу для обсуждения и пишите.