2010-09-15 17 views
9

Tôi đang làm việc trên một dự án có liên quan đến một số thu thập dữ liệu web cơ bản. Tôi đã sử dụng HttpWebRequest và HttpWebResponse khá thành công. Để xử lý cookie, tôi chỉ có một CookieContainer mà tôi gán cho HttpWebRequest.CookieContainer mỗi lần. Tôi tự động được phổ biến với các cookie mới mỗi lần và không yêu cầu xử lý thêm từ tôi. Điều này tất cả đã được làm việc tốt cho đến khi một thời gian ngắn trước đây khi một trong những trang web mà được sử dụng để làm việc đột nhiên ngừng làm việc. Tôi chắc chắn nó là một vấn đề với các tập tin cookie, nhưng tôi đã không giữ một bản ghi của các cookie từ khi nó được sử dụng để làm việc vì vậy tôi không chắc chắn 100%.CookieContainer xử lý đường dẫn (Ai đã ăn cookie của tôi?)

tôi đã quản lý để mô phỏng vấn đề như tôi nhìn thấy nó với đoạn mã sau:

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))); 

này mô phỏng quý khách đến thăm hai trang, cả hai đều đặt hai tập tin cookie. Sau đó, nó sẽ kiểm tra xem cookie nào trong số ba trang đó sẽ được đặt thành từng trang.

Trong số hai cookie, một cookie được đặt mà không chỉ định đường dẫn và đường còn lại có đường dẫn được chỉ định. Khi một đường dẫn không được chỉ định, tôi đã giả định rằng cookie sẽ được gửi trở lại bất kỳ trang nào trong miền đó, nhưng dường như nó chỉ được gửi trở lại trang cụ thể đó. Tôi bây giờ giả định rằng đó là chính xác vì nó là phù hợp.

Vấn đề chính đối với tôi là việc xử lý cookie có đường dẫn được chỉ định. Chắc chắn, nếu đường dẫn được chỉ định thì cookie sẽ được gửi đến bất kỳ trang nào có trong đường dẫn đó. Vì vậy, trong đoạn mã trên, 'CookieWithPath' phải hợp lệ cho bất kỳ trang nào trong/some/path /, bao gồm page1.html, page2.html và page3.html. Chắc chắn nếu bạn bình luận ra hai trường hợp 'NoPathCookie', thì 'CookieWithPath' được gửi đến cả ba trang như tôi mong đợi. Tuy nhiên, với việc bao gồm 'NoPathCookie' như trên, thì 'CookieWithPath' chỉ được gửi đến page2.html và page3.html, nhưng không được gửi đến page1.html.

Tại sao điều này và chính xác?

Tìm kiếm vấn đề này Tôi đã bàn luận về một vấn đề với xử lý miền trong CookieContainer, nhưng không thể tìm thấy bất kỳ cuộc thảo luận nào về xử lý đường dẫn.

Tôi đang sử dụng Visual Studio 2005/NET 2,0

Trả lời

2

Khi một con đường không được xác định, tôi đã giả định rằng cookie sẽ được gửi trả lại cho bất kỳ trang nào trong phạm vi đó, nhưng nó dường như chỉ được gửi trở lại trang cụ thể đó. Tôi bây giờ giả định rằng đó là chính xác vì nó là phù hợp.

Đúng, đó là chính xác. Bất cứ khi nào tên miền hoặc đường dẫn không được chỉ định, nó được lấy từ URI hiện tại.

OK, chúng ta hãy xem CookieContainer. Phương thức được đề cập là InternalGetCookies(Uri). Đây là phần thú vị:

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 đây là danh sách các đường dẫn cookie (được sắp xếp). Nó được sắp xếp theo cách như vậy, các đường dẫn cụ thể hơn (như /directory/subdirectory/) đi trước các đường cụ thể ít hơn (như /directory/) và ngược lại - theo thứ tự từ điển (/directory/page1 trước /directory/page2).

Mã thực sự như sau: nó lặp qua danh sách đường dẫn cookie này cho đến khi tìm thấy đường dẫn đầu tiên, đó là tiền tố cho đường dẫn URI được yêu cầu.Sau đó, nó thêm cookie vào đường dẫn đến đầu ra và đặt flag2 thành true, có nghĩa là "OK, cuối cùng tôi đã tìm thấy địa điểm trong danh sách thực sự liên quan đến URI được yêu cầu". Sau đó, đường dẫn gặp gỡ đầu tiên, đó KHÔNG phải là tiền tố cho đường dẫn URI được yêu cầu được coi là kết thúc của các đường dẫn có liên quan, do đó mã ngừng tìm kiếm cookie bằng cách thực hiện break.

Rõ ràng, đây là một số loại tối ưu hóa để ngăn chặn quét toàn bộ danh sách và nó dường như hoạt động nếu không có đường dẫn nào dẫn đến trang cụ thể. Bây giờ, đối với trường hợp của bạn, danh sách đường trông như thế:

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

Bạn có thể kiểm tra với một trình gỡ lỗi, nhìn lên ((System.Net.PathList)(cookieJar.m_domainTable["www.somedomain.com"])).m_list trong cửa sổ xem

Vì vậy, đối với 'page1.html' URI, mã vi phạm trên page2.html mục, không có cơ hội xử lý cũng /some/path/ mục.

Kết luận: đây rõ ràng là một lỗi khác trong CookieContainer. Tôi tin rằng nó cần được báo cáo về kết nối.

PS: Quá nhiều lỗi trên một lớp. Tôi chỉ hy vọng anh chàng ở MS đã viết bài kiểm tra cho lớp này đã bị sa thải.

Các vấn đề liên quan