Giugno 2007
Introduzione
A volte non c'è niente di meglio che vedere cosa viene trasmesso via cavo. Ciò è particolarmente vero quando si scrive software che utilizza servizi web come le API Google Data, in cui molte operazioni comportano l'invio di richieste HTTP. Quando tutto il resto fallisce, puoi verificare che il tuo programma stia facendo ciò che ti aspetti visualizzando i byte effettivamente trasmessi e ricevuti. Molte delle librerie client per le API di Google Data hanno una modalità di debug che mostra il traffico HTTP. Questa funzionalità è particolarmente utile quando non hai accesso a un packet sniffer come WireShark o Fiddler.
Non riesco a contare il numero di volte in cui avrei potuto giurare che il mio programma fosse corretto, solo per scoprire, dopo aver esaminato una traccia di pacchetti, che c'era un carattere di nuova riga aggiuntivo o un'intestazione HTTP con un nome errato. La programmazione in base a un servizio web senza esaminare il traffico HTTP può essere come cercare di infilare un ago con gli occhi chiusi.
Tuttavia, potresti trovarti in una situazione in cui uno sniffer di pacchetti non è disponibile o non è adeguato per gestire i pacchetti criptati. Non temere, puoi aggirare questa limitazione sfruttando alcuni meccanismi di logging nel programma. Utilizzando queste funzionalità di logging, puoi visualizzare alcuni, se non tutti, i dati scambiati, anche per i dati HTTPS criptati o il codice in esecuzione da remoto.
Per questo articolo, ho scritto un codice diagnostico di esempio in tre lingue utilizzando le librerie client dell'API Google Data per Java, .NET e Python. In ogni esempio, attivo la registrazione o il debug, eseguo l'autenticazione utilizzando l'accesso client e poi ottengo un elenco dei miei Fogli Google e stampo i relativi titoli.
Java
Puoi utilizzare le classi java.util.logging
per impostare i livelli di logging (e di conseguenza esporre i dati sul traffico) per un paio di oggetti chiave nella libreria client. Nell'esempio seguente, ho scelto di esaminare le intestazioni HTTP
e le attività del parser XML per avere una visione completa di ciò che
viene trasmesso via cavo.
La libreria client Java di Google Data ha classi separate per
gestire le richieste HTTP e l'analisi XML; pertanto, devo creare due oggetti Logger,
uno per ogni classe:
com.google.gdata.client.http.HttpGDataRequest
gestisce il traffico HTTP, mentre com.google.gdata.util.XmlParser
è responsabile dell'analisi XML.
Le istanze del logger registreranno le attività per
HttpGDataRequest
e XmlParser
e potrai controllare
il livello di dettaglio dell'output di ciascun logger. Per
questa dimostrazione, ho scelto di visualizzare tutti gli eventi prodotti dagli oggetti HttpGDataRequest
e XmlParser
.
Una volta creati
e configurati i miei logger, devo indicare loro cosa fare quando ricevono un evento dalle loro classi. Per il momento, voglio scrivere tutte le informazioni di logging
nella console, quindi creo un ConsoleHandler
e lo aggiungo a entrambi i miei logger.
Ecco il mio codice di esempio:
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());
}
}
}
Quando esegui questo programma, nella console viene visualizzato un risultato simile al seguente (ho omesso alcune delle parti meno interessanti):
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
Questi log possono diventare piuttosto grandi, quindi ti consigliamo di essere più selettivo nell'impostazione dei livelli dei logger. Puoi anche creare un FileHandler
anziché un ConsoleHandler
per archiviare i dati dei log per un utilizzo successivo.
Naturalmente, se Java non fa per te, puoi provare .NET.
.NET
Per acquisire il traffico HTTP nella libreria client .NET, puoi sostituire la factory di richieste predefinita nel client con un GDataLoggingRequestFactory
.
Le richieste HTTP nella libreria .NET vengono create da GDataRequestFactory
, che si trova all'interno di ogni oggetto Service. Le normali fabbriche di richieste non eseguono
alcun logging, ma GDataLoggingRequestFactory
, che è una sottoclasse di GDataRequestFactory
, ha il logging integrato. Puoi specificare il percorso completo del
file di log impostando CombinedFileName
.
Dopo aver configurato la fabbrica di richieste, devi sostituirla nell'oggetto Service impostando RequestFactory
dell'oggetto Service.
Il codice potrebbe avere un aspetto simile al seguente:
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();
}
}
}
Il file di log risultante contiene le richieste e le risposte XML. Ecco un esempio abbreviato che ho formattato utilizzando 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>
Ma magari ti piacciono molto i linguaggi di scripting e preferisci usare Python.
Python
Per acquisire il traffico HTTP nella libreria client Python, puoi visualizzare l'intestazione HTTP nella console attivando la modalità di debug nel client HTTP. L'oggetto servizio ha un membro di debug che puoi impostare su True.
Se imposti debug su true, il flag di debug viene impostato nell'oggetto HTTPRequest
sottostante contenuto nell'oggetto servizio.
Ecco un esempio che ripete le intestazioni HTTP inviate dal server dei fogli di lavoro quando richiedi un elenco dei tuoi fogli di lavoro.
#!/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
Nella console verrà visualizzato un risultato simile al seguente:
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
Man mano che esegui altre operazioni, come un inserimento o un aggiornamento, nella console vengono visualizzati i dati delle richieste corrispondenti.
Conclusione
Questo breve tutorial ha illustrato come aggiungere funzionalità di logging di base a un programma Java, .NET o Python che utilizza le librerie client dell'API Google Data. Queste tecniche possono essere utili se devi eseguire il debug degli scambi HTTP, ma non hai accesso a uno sniffer di pacchetti. Con questi esempi ho solo scalfito la superficie. Molti dei meccanismi di logging presenti in queste lingue sono molto più potenti di quelli mostrati qui. Se vuoi saperne di più sulla registrazione o sulle API Google Data, consulta l'elenco di risorse riportato di seguito.
Le librerie client trattate in questo articolo sono disponibili nelle seguenti pagine:
Articoli della knowledge base correlati:
- Come faccio a ottenere informazioni di logging HTTP nella libreria client Java?
- Come faccio a ottenere informazioni di logging HTTP nella libreria client .NET?
- Quali sono alcuni strumenti utili per il debug HTTP?
- Che cos'è l'API Google Spreadsheets?
Gruppi di discussione: ne abbiamo diversi e ne arriveranno altri man mano che verranno implementate altre API di Google Data. Monitoriamo attivamente i gruppi.
Se hai domande o suggerimenti, non esitare a contattarmi. Partecipa al gruppo di discussione e inizia a pubblicare.