יוני 2007
מבוא
לפעמים אין תחליף. זה נכון במיוחד כשכותבים תוכנה שמשתמשת בשירותי אינטרנט כמו Google Data APIs, הרבה פעולות שקשורות לשליחת בקשות HTTP. אם שום דבר אחר לא יצליח, תוכלו לוודא שהתוכנית שלכם פועלת בהתאם לציפיות שלכם על ידי הצגת הבייטים שהועברו והתקבלו בפועל. לספריות לקוח רבות של ממשקי API של נתוני Google יש מצב ניפוי באגים, שמציג את תנועת ה-HTTP. האפשרות הזו שימושית במיוחד כשאין לכם גישה למפעיל חבילות, כמו WireShark או Fiddler.
אני לא יכול לספור את מספר הפעמים שיכולתי להישבע שהתוכנית שלי נכונה, רק כדי לגלות לאחר שבדקתי את תיעוד החבילות שיש תו חדש נוסף, או כותרת HTTP עם שם שגוי. תכנות מול שירות אינטרנט בלי להסתכל על תנועת ה-HTTP יכול להיות כמו שרשור מחט, כשהעיניים מושתקות.
עם זאת, אתם עשויים למצוא את עצמכם במצב שבו שמטפל בחבילות לא זמין או לא מספיק בשביל לטפל בחבילות מוצפנות. אל תפחדו לעקוף את המגבלה הזו על ידי מינוף של חלק ממנגנוני הרישום בתוכנית. השימוש במתקני הרישום ביומן מאפשר לראות חלק מהנתונים שהוחלפו, גם אם לא את כולם, גם עבור נתוני HTTPS מוצפנים או קוד שפועל מרחוק.
במאמר הזה כתבתי קוד אבחון לדוגמה ב-3 שפות באמצעות ספריות הלקוח של Google Data API ל-Java, ל- .NET ול-Python. בכל אחת מהדוגמאות, אני מפעיל רישום ביומן או ניפוי באגים, מאמת באמצעות התחברות ללקוחות ולאחר מכן מקבל רשימה של הגיליונות האלקטרוניים שלי ב-Google ומדפיס את הכותרות שלהם.
Java
ניתן להשתמש במחלקות java.util.logging
כדי להגדיר את הרמות של רישום ביומן (וכתוצאה מכך לחשוף נתוני תנועה) עבור כמה אובייקטים מרכזיים בספריית הלקוח. בדוגמה הבאה, בחרתי להסתכל על כותרות ה-HTTP ועל הפעילויות של מנתח ה-XML כדי לקבל תמונה מלאה של כל מה שקורה ברשת.
בספריית הלקוח של Google Data Java יש מחלקות נפרדות לטיפול בבקשות HTTP ובניתוח XML, ולכן עליי ליצור שני אובייקטים של יומן רישום לכל מחלקה: 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
היומנים האלה עשויים להיות גדולים למדי, לכן כדאי שתהיה בררנית יותר בהגדרת היומנים. אפשר גם ליצור FileHandler
במקום ConsoleHandler
כדי לאחסן את נתוני היומן לשימוש מאוחר יותר.
כמובן, אם Java אינו התיק שלך, תוכל לנסות את .NET
.NET
כדי לתעד את תנועת ה-HTTP בספריית הלקוח עם הסיומת NET., אפשר להחליף את קובץ ברירת המחדל של הבקשה בלקוח בגרסה GDataLoggingRequestFactory
.
בקשות ה-HTTP בספריית NET .נוצרות על ידי GDataRequestFactory
שנמצא בתוך כל אובייקט שירות. במפעלים הרגילים של בקשות לא מתבצע רישום ביומן, אבל ב-GDataLoggingRequestFactory
, שהוא תת-מחלקה של GDataRequestFactory
, יש רישום מובנה. ניתן לציין את הנתיב המלא של קובץ היומן על ידי הגדרת CombinedFileName
.
אחרי שמגדירים את מפעל הבקשה, צריך להחליף את מפעל הבקשות באובייקט השירות על ידי הגדרת RequestFactory
של אובייקט השירות.
הקוד שלך עשוי להיראות בערך כך:
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.
Python
כדי לתעד את תנועת ה-HTTP בספריית הלקוח ב-Python, אפשר להוסיף הד לתנועה של כותרת ה-HTTP למסוף על ידי הפעלת מצב ניפוי באגים בלקוח ה-HTTP. לאובייקט השירות יש חבר ניפוי באגים שאפשר להגדיר אותו כ-True.
אם מגדירים את האפשרות 'ניפוי באגים' כ-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ים, אבל אין לכם גישה לחבילות נתונים. גירדי את השטח רק באמצעות הדוגמאות האלה. הרבה מהמנגנונים של רישום ביומן בשפות האלה הרבה יותר חזקים ממה שמוצג כאן. למידע נוסף על רישום ביומן או על ממשקי API של נתונים של Google, עיינו ברשימת המשאבים שבהמשך.
אפשר למצוא את ספריות הלקוח שבמאמר זה בדפים הבאים:
פריטים קשורים במאגר הידע:
- איך מקבלים מידע על רישום HTTP בספריית הלקוח של Java?
- איך מקבלים מידע על רישום HTTP בספריית הלקוח NET .
- מהם הכלים הטובים לניפוי באגים ב-HTTP?
- מה זה Google Sheets API?
קבוצות דיון: יש לנו מעט מאוד, אך בקרוב נשיק כמה קמפיינים נוספים. אנחנו עוקבים אחר הקבוצות באופן פעיל.
אם יש לך שאלות או הצעות, אשמח לשמוע ממך. הצטרפו לקבוצת הדיון והתחילו לפרסם.