2010-09-15 5 views
9

मैं एक ऐसे प्रोजेक्ट पर काम कर रहा हूं जिसमें कुछ मूल वेब क्रॉलिंग शामिल है। मैं बहुत सफलतापूर्वक HttpWebRequest और HttpWebResponse का उपयोग कर रहा हूं। कुकी हैंडलिंग के लिए मेरे पास सिर्फ एक कुकी कंटनर है जिसे मैं प्रत्येक बार HttpWebRequest.CookieContainer को असाइन करता हूं। मैं स्वचालित रूप से हर बार नई कुकीज़ के साथ आबादी प्राप्त करता हूं और मुझे मुझसे कोई अतिरिक्त हैंडलिंग की आवश्यकता नहीं होती है। यह सब थोड़ी देर पहले ठीक काम कर रहा है जब काम करने के लिए उपयोग की जाने वाली वेबसाइटों में से एक अचानक काम करना बंद कर दिया। मुझे यकीन है कि यह कुकीज़ के साथ एक समस्या है, लेकिन जब मैं काम करता था तब से मैंने कुकीज का रिकॉर्ड नहीं रखा था इसलिए मैं 100% निश्चित नहीं हूं।कुकी कंटैनर पथों का संचालन (किसने मेरी कुकी खाई?)

मैं इस मुद्दे अनुकरण करने के लिए के रूप में मैं इसे निम्न कोड के साथ देख प्रबंधित किया है:

CookieContainer cookieJar = new CookieContainer(); 

Uri uri1 = new Uri("http://www.somedomain.com/some/path/page1.html"); 
CookieCollection cookies1 = new CookieCollection(); 
cookies1.Add(new Cookie("NoPathCookie", "Page1Value")); 
cookies1.Add(new Cookie("CookieWithPath", "Page1Value", "/some/path/")); 

Uri uri2 = new Uri("http://www.somedomain.com/some/path/page2.html"); 
CookieCollection cookies2 = new CookieCollection(); 
cookies2.Add(new Cookie("NoPathCookie", "Page2Value")); 
cookies2.Add(new Cookie("CookieWithPath", "Page2Value", "/some/path/")); 

Uri uri3 = new Uri("http://www.somedomain.com/some/path/page3.html"); 

// Add the cookies from page1.html 
cookieJar.Add(uri1, cookies1); 

// Add the cookies from page2.html 
cookieJar.Add(uri2, cookies2); 

// We should now have 3 cookies 
Console.WriteLine(string.Format("CookieJar contains {0} cookies", cookieJar.Count)); 

Console.WriteLine(string.Format("Cookies to send to page1.html: {0}", cookieJar.GetCookieHeader(uri1))); 
Console.WriteLine(string.Format("Cookies to send to page2.html: {0}", cookieJar.GetCookieHeader(uri2))); 
Console.WriteLine(string.Format("Cookies to send to page3.html: {0}", cookieJar.GetCookieHeader(uri3))); 

इसे दो पृष्ठों की, जो दोनों के दो कुकीज़ सेट पर जाकर simulates। फिर यह जांचता है कि इनमें से कौन सी कुकीज़ तीन पृष्ठों में से प्रत्येक पर सेट की जाएगी।

दो कुकीज़ में से एक को पथ निर्दिष्ट किए बिना सेट किया गया है और दूसरे के पास पथ निर्दिष्ट है। जब कोई पथ निर्दिष्ट नहीं किया गया है, तो मैंने माना था कि कुकी को उस डोमेन के किसी भी पृष्ठ पर वापस भेजा जाएगा, लेकिन ऐसा लगता है कि केवल उस विशिष्ट पृष्ठ पर वापस भेजा जाता है। अब मैं मान रहा हूं कि यह सही है क्योंकि यह सुसंगत है।

मेरे लिए मुख्य समस्या निर्दिष्ट पथ वाले कुकीज़ का संचालन है। निश्चित रूप से, यदि कोई पथ निर्दिष्ट किया गया है तो कुकी को उस पथ के भीतर मौजूद किसी भी पृष्ठ पर भेजा जाना चाहिए। तो, उपर्युक्त कोड में, 'कुकीविथपाथ' किसी भी पृष्ठ के लिए/कुछ/पथ/के भीतर मान्य होना चाहिए, जिसमें पृष्ठ 1.html, पृष्ठ 2.html और पृष्ठ 3.html शामिल है। निश्चित रूप से यदि आप दो 'नोपाथकुकी' उदाहरणों पर टिप्पणी करते हैं, तो 'कुकी विथपाथ' को उन सभी तीन पृष्ठों पर भेजा जाता है जैसा मैं उम्मीद करता हूं। हालांकि, उपरोक्त के रूप में 'नोपाथकुकी' को शामिल करने के साथ, 'कुकीविथपाथ' केवल पृष्ठ 2.html और पेज 3.html पर भेजा जाता है, लेकिन पृष्ठ 1.html नहीं।

यह क्यों है, और यह सही है?

इस समस्या की तलाश में मैंने कुकी कोंटेनर में डोमेन हैंडलिंग के साथ किसी समस्या के बारे में चर्चा की है, लेकिन पथ प्रबंधन के बारे में कोई चर्चा नहीं पाई है।

मैं दृश्य स्टूडियो का उपयोग कर रहा 2005/नेट 2,0

उत्तर

2

एक पथ निर्दिष्ट नहीं किया जाता है, तो मैं मान लिया था कि कुकी कि डोमेन में किसी भी पृष्ठ पर वापस भेज दिया जायेगा, लेकिन यह केवल करने लगता है उस विशिष्ट पृष्ठ पर वापस भेज दें। अब मैं मान रहा हूं कि यह सही है क्योंकि यह सुसंगत है।

हाँ, यह सही है। जब भी डोमेन या पथ निर्दिष्ट नहीं किया जाता है, तो यह वर्तमान यूआरआई से लिया जाता है।

ठीक है, चलो कुकी कोंटेनर पर नज़र डालें। प्रश्न में विधि InternalGetCookies(Uri) है।

while (enumerator2.MoveNext()) 
{ 
    DictionaryEntry dictionaryEntry = (DictionaryEntry)enumerator2.get_Current(); 
    string text2 = (string)dictionaryEntry.get_Key(); 
    if (!uri.AbsolutePath.StartsWith(CookieParser.CheckQuoted(text2))) 
    { 
     if (flag2) 
     { 
      break; 
     } 
     else 
     { 
      continue; 
     } 
    } 
    flag2 = true; 
    CookieCollection cookieCollection2 = (CookieCollection)dictionaryEntry.get_Value(); 
    cookieCollection2.TimeStamp(CookieCollection.Stamp.Set); 
    this.MergeUpdateCollections(cookieCollection, cookieCollection2, port, flag, i < 0); 
    if (!(text2 == "/")) 
    { 
     continue; 
    } 
    flag3 = true; 
    continue; 
} 

यहाँ enumerator2 एक (क्रमबद्ध) कुकी 'पथों की सूची है: यहाँ दिलचस्प हिस्सा है। इसे इस तरह से हल किया जाता है, कि अधिक विशिष्ट पथ (जैसे /directory/subdirectory/) कम विशिष्ट वाले (जैसे /directory/) से पहले जाएं, और अन्यथा - लेक्सिकोोग्राफ़िकल ऑर्डर में (/directory/page1/directory/page2 से पहले चला जाता है)।

कोड वास्तव में निम्न कार्य करता है: यह कुकीज़ के पथों की इस सूची में तब तक चलता है जब तक कि यह पहला पथ नहीं पाता है, यह अनुरोध किया गया है कि यह यूआरआई के पथ के लिए उपसर्ग है।फिर यह आउटपुट के लिए उस पथ के नीचे एक कुकीज जोड़ता है और flag2 से true सेट करता है, जिसका अर्थ है "ठीक है, मुझे आखिर में उस सूची में जगह मिली जो वास्तव में अनुरोधित यूआरआई से संबंधित है"। उसके बाद, पहला पूरा पथ, जो अनुरोधित यूआरआई पथ के लिए उपसर्ग नहीं है, को संबंधित पथों का अंत माना जाता है, इसलिए कोड break कर कुकीज़ के लिए खोज करना बंद कर देता है।

जाहिर है, यह पूरी सूची स्कैन करने से रोकने के लिए कुछ प्रकार का अनुकूलन है और यह स्पष्ट रूप से काम करता है यदि पथों में से कोई भी ठोस पृष्ठ तक नहीं जाता है। अब, अपने मामले के लिए, पथ की सूची है कि तरह लग रहा है:

/some/path/page1.html 
/some/path/page2.html 
/some/path/ 

आप देख सकते हैं कि एक डिबगर के साथ, ऊपर ((System.Net.PathList)(cookieJar.m_domainTable["www.somedomain.com"])).m_list घड़ी विंडो में देख

तो, 'page1.html' URI, कोड के लिए आइटम पर ब्रेक, /some/path/ आइटम को संसाधित करने का मौका नहीं है।

निष्कर्ष में: यह स्पष्ट रूप से कुकी कोंटेनर में एक और बग है। मुझे विश्वास है कि कनेक्ट पर इसकी सूचना दी जानी चाहिए।

पीएस: यह एक वर्ग प्रति बहुत अधिक बग है। मुझे उम्मीद है कि एमएस में लड़के ने इस वर्ग के लिए परीक्षण लिखे हैं, पहले से ही निकाल दिया गया है।