Junio de 2007
Introducción
A veces, no hay sustituto para ver lo que se transmite por el cable. Esto es especialmente cierto cuando se escribe software que usa servicios web, como las APIs de Google Data, en las que muchas operaciones implican realizar solicitudes HTTP. Cuando todo lo demás falla, puedes verificar que tu programa haga lo que esperas viendo los bytes reales transmitidos y recibidos. Muchas de las bibliotecas cliente de las APIs de Google Data tienen un modo de depuración que muestra el tráfico HTTP. Esto es especialmente útil cuando no tienes acceso a un analizador de paquetes como WireShark o Fiddler.
No puedo contar la cantidad de veces que podría haber jurado que mi programa era correcto, solo para descubrir, al inspeccionar un registro de paquetes, que había un carácter de nueva línea adicional o un encabezado HTTP con un nombre incorrecto. Programar en función de un servicio web sin observar el tráfico HTTP puede ser como intentar enhebrar una aguja con los ojos cerrados.
Sin embargo, es posible que te encuentres en una situación en la que un analizador de paquetes no esté disponible o no sea adecuado para tratar con paquetes encriptados. No te preocupes, puedes evitar esta limitación aprovechando algunos mecanismos de registro en el programa. Si utilizas estas funciones de registro, puedes ver algunos de los datos intercambiados, si no todos, incluso los datos HTTPS encriptados o el código que se ejecuta de forma remota.
Para este artículo, escribí código de diagnóstico de muestra en 3 lenguajes con las bibliotecas cliente de la API de Google Data para Java, .NET y Python. En cada ejemplo, activo el registro o la depuración, realizo la autenticación con el acceso del cliente y, luego, obtengo una lista de mis hojas de cálculo de Google y sus títulos.
Java
Puedes usar las clases java.util.logging
para establecer los niveles de registro (y, en consecuencia, exponer los datos de tráfico) para algunos objetos clave en la biblioteca cliente. En el siguiente ejemplo, elegí observar los encabezados HTTP y las actividades del analizador de XML para obtener una vista completa de lo que se transmite por cable.
La biblioteca cliente de Google Data para Java tiene clases separadas para controlar las solicitudes HTTP y el análisis de XML. Por lo tanto, necesito crear dos objetos Logger, uno para cada clase: com.google.gdata.client.http.HttpGDataRequest
controla el tráfico HTTP, mientras que com.google.gdata.util.XmlParser
es responsable del análisis de XML.
Las instancias de Logger registrarán actividades para HttpGDataRequest
y XmlParser
, y podrás controlar el nivel de detalle del resultado de cada Logger. Para esta demostración, elegí ver todos los eventos producidos por los objetos HttpGDataRequest
y XmlParser
.
Una vez que haya creado y configurado mis objetos Logger, debo indicarles qué hacer cuando reciban un evento de sus clases. Por ahora, quiero escribir toda la información de registro en la consola, por lo que creo un ConsoleHandler
y lo agrego a mis dos registradores.
Este es mi código de muestra:
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());
}
}
}
Cuando ejecutes este programa, verás algo como lo siguiente en la consola (corté algunas de las partes menos interesantes):
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
Estos registros pueden ser bastante extensos, por lo que te recomendamos que seas más selectivo a la hora de establecer los niveles de los registradores. También puedes crear un FileHandler
en lugar de un ConsoleHandler
para almacenar los datos de registro y usarlos más adelante.
Por supuesto, si Java no es lo tuyo, puedes probar .NET.
.NET
Para capturar el tráfico HTTP en la biblioteca cliente de .NET, puedes reemplazar la fábrica de solicitudes predeterminada en el cliente por un GDataLoggingRequestFactory
.
Las solicitudes HTTP en la biblioteca de .NET se crean con el objeto GDataRequestFactory
que se encuentra dentro de cada objeto Service. Las fábricas de solicitudes normales no realizan ningún registro, pero GDataLoggingRequestFactory
, que es una subclase de GDataRequestFactory
, tiene el registro integrado. Puedes especificar la ruta de acceso completa del archivo de registro configurando CombinedFileName
.
Después de configurar la fábrica de solicitudes, debes reemplazarla en tu objeto Service configurando el RequestFactory
del objeto de servicio.
Tu código podría verse de la siguiente manera:
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();
}
}
}
El archivo de registro resultante contiene las solicitudes y respuestas en XML. Este es un ejemplo abreviado que formateé con 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>
Sin embargo, tal vez te gusten mucho los lenguajes de programación y prefieras usar Python.
Python
Para capturar el tráfico HTTP en la biblioteca cliente de Python, puedes mostrar el tráfico de encabezado HTTP en la consola activando el modo de depuración en el cliente HTTP. El objeto de servicio tiene un miembro de depuración que puedes establecer en True.
Si se establece la depuración como verdadera, se establecerá la marca de depuración en el objeto HTTPRequest
subyacente que se encuentra en el objeto de servicio.
A continuación, se muestra un ejemplo que repetirá los encabezados HTTP enviados desde el servidor de hojas de cálculo cuando solicites una lista de tus hojas de cálculo.
#!/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
Y verás algo como esto en la consola:
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
A medida que realices operaciones adicionales, como una inserción o una actualización, verás los datos de solicitud correspondientes reflejados en tu consola.
Conclusión
En este breve instructivo, se ilustró cómo puedes agregar funciones básicas de registro a un programa en Java, .NET o Python que usa las bibliotecas cliente de las APIs de Google Data. Estas técnicas pueden ser útiles si necesitas depurar intercambios HTTP, pero no tienes acceso a un analizador de paquetes. Estos ejemplos son solo una pequeña muestra de lo que puedes hacer. Muchos de los mecanismos de registro presentes en estos lenguajes son mucho más potentes que lo que se muestra aquí. Si deseas obtener más información sobre el registro o las APIs de datos de Google, consulta la siguiente lista de recursos.
Encontrarás las bibliotecas cliente que se abordan en este artículo en las siguientes páginas:
Elementos relacionados de la base de conocimiento:
- ¿Cómo obtengo información de registro de HTTP en la biblioteca cliente de Java?
- ¿Cómo obtengo información de registro de HTTP en la biblioteca cliente de .NET?
- ¿Qué herramientas son buenas para la depuración de HTTP?
- ¿Qué es la API de Google Spreadsheets?
Grupos de debate: Tenemos varios y se agregarán más a medida que se lancen más APIs de datos de Google. Supervisamos los grupos de forma activa.
- API de Google Spreadsheets
- API de Google Calendar
- API de Blogger
- API de Google Base
- API de Álbumes web de Picasa
Si tienes preguntas o sugerencias, me encantaría escucharte. Únete al grupo de discusión y comienza a publicar.