junho de 2007
Introdução
Às vezes, não há substituto para ver o que acontece na rede. Isso ocorre principalmente ao escrever softwares que usam serviços da Web como as APIs de dados do Google, em que muitas operações envolvem a realização de solicitações HTTP. Quando todo o restante falha, é possível verificar se o programa está fazendo o que é esperado ver os bytes reais transmitidos e recebidos. Muitas das bibliotecas de cliente das APIs de dados do Google têm um modo de depuração que exibe o tráfego HTTP. Isso é especialmente útil quando você não tem acesso a um pacote MapReduce, como WireShark ou GoDaddy.
Não consigo contar o número de vezes que posso dizer que meu programa estava correto, apenas para descobrir ao inspecionar um trace de pacote que houve um caractere de nova linha extra ou um cabeçalho HTTP com nome incorreto. Programar um serviço da Web sem analisar o tráfego HTTP pode ser uma tentativa de criar uma linha de execução com os olhos fechados.
No entanto, você pode se deparar com uma situação em que um detector de pacotes não está disponível ou é inadequado para lidar com pacotes criptografados. Não se preocupe, você pode contornar essa limitação aproveitando alguns mecanismos de geração de registros no programa. Ao utilizar esses recursos de geração de registros, é possível ver alguns ou todos os dados trocados, mesmo para dados HTTPS criptografados ou código de execução remota.
Neste artigo, escrevi um código de diagnóstico de exemplo em três linguagens usando as bibliotecas de cliente da API Google Data para Java, .NET e Python. Em cada exemplo, ativo a geração de registros ou a depuração, autentico usando o login de cliente e, em seguida, recebo uma lista das minhas planilhas do Google e imprimi os títulos delas.
Java
É possível usar as classes java.util.logging
para definir os níveis
de geração de registros (e, consequentemente, expor dados de tráfego) a alguns objetos-chave
na biblioteca de cliente. No exemplo abaixo, escolhi analisar os cabeçalhos HTTP
e as atividades do analisador XML para ter uma visão completa do que
está sendo transmitido pela rede.
A biblioteca de cliente Java dos dados do Google tem classes separadas para lidar com solicitações HTTP e análise XML. Assim, precisamos criar dois objetos logger, um para cada classe: com.google.gdata.client.http.HttpGDataRequest
gerencia o tráfego HTTP enquanto com.google.gdata.util.XmlParser
é responsável pela análise XML.
As instâncias do logger vão gravar atividades para
HttpGDataRequest
e XmlParser
, e você pode controlar
o nível de detalhes da saída de cada um. Para
essa demonstração, escolhi visualizar todos os eventos produzidos pelos objetos HttpGDataRequest
e XmlParser
.
Depois de criar
e configurar meus loggers, preciso dizer o que eles devem fazer quando receberem um evento das classes deles. Por enquanto, quero gravar todas as informações de registro
no console. Portanto, crio um ConsoleHandler
e o adiciono aos dois loggers.
Veja um exemplo de código:
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());
}
}
}
Ao executar o programa, você verá algo parecido com isto no console: Cortei algumas das partes menos interessantes:
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
Como esses registros podem ficar muito grandes, é possível ser mais seletivo em relação aos níveis dos registradores. Também é possível criar um FileHandler
em vez de um ConsoleHandler
para permitir que você armazene os dados de registro para uso posterior.
É claro que se Java não for sua bolsa, tente .NET.
.NET
Para capturar o tráfego HTTP na biblioteca de cliente .NET, é possível substituir a fábrica de solicitação padrão no cliente por um GDataLoggingRequestFactory
.
As solicitações HTTP na biblioteca .NET são criadas pelo GDataRequestFactory
que está dentro de cada objeto Service. As fábricas de solicitações normais não realizam
nenhuma geração de registros, mas a GDataLoggingRequestFactory
, que é uma subclasse de GDataRequestFactory
, tem geração de registros integrada. É possível especificar o caminho completo do
arquivo de registros definindo CombinedFileName
.
Depois de configurar a fábrica de solicitações, substitua a fábrica de objetos no objeto Service definindo o RequestFactory
do objeto de serviço.
O código vai ficar assim:
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();
}
}
}
O arquivo de registro resultante contém as solicitações e respostas XML. Veja um exemplo abreviado que formatei usando 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>
Mas talvez você goste muito de linguagens de script e prefira usar o Python.
Python
Para capturar o tráfego HTTP na biblioteca de cliente Python, você pode ecoar o tráfego de cabeçalho HTTP para o console ativando o modo de depuração no cliente HTTP. O objeto de serviço tem um membro de depuração que pode ser definido como True.
Definir a depuração como verdadeira definirá a sinalização de depuração no objeto HTTPRequest
subjacente contido no objeto de serviço.
Veja um exemplo que reproduzirá os cabeçalhos HTTP enviados do servidor de planilhas ao solicitar uma lista das planilhas.
#!/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
Você verá algo parecido com isto no seu console:
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
Ao executar outras operações, como inserir ou atualizar, você verá os dados de solicitações correspondentes ecoados no console.
Conclusão
Neste breve tutorial, ilustramos como adicionar a funcionalidade básica de geração de registros a um programa Java, .NET ou Python que usa as bibliotecas de cliente da API Google Data. Essas técnicas podem ser úteis se você precisar depurar trocas HTTP, mas não tiver acesso a um identificador de pacotes. Abordamos apenas alguns exemplos. Muitos dos mecanismos de geração de registros presentes nessas linguagens são muito mais poderosos do que o mostrado aqui. Se você quiser mais informações sobre a geração de registros ou as APIs de dados do Google, confira a lista de recursos abaixo.
As bibliotecas de cliente abordadas neste artigo podem ser encontradas nestas páginas:
Itens relacionados da base de conhecimento:
- Como faço para ter informações da geração de registros HTTP na biblioteca de cliente Java?
- Como faço para ter informações da geração de registros HTTP na biblioteca de cliente .NET?
- Quais são as ferramentas adequadas para depuração HTTP?
- O que é a API Google Sheets?
Grupos de discussão: temos alguns, e mais serão disponibilizados à medida que mais APIs de dados do Google forem lançadas. Monitoramos os grupos ativamente.
Se tiver dúvidas ou sugestões, entre em contato. Entre no grupo de discussão e comece a postar.