2012-06-27 18 views
2

我使用HttpWebRequestHttpWebResponse来抓取网站。我为每个请求使用相同的CookieContainer,确保cookie自动处理。当Cookie的路径未设置时CookieCollection问题

但是,其中一个请求需要一个特定的cookie,该cookie是在先前的响应中设置的。虽然这存在于集合中,但其Path属性显示不正确。根据RFC2109(第7页),当Cookie设置为空路径(如本文所述)时,路径应设置为请求的URL,但不包括最终斜线。实际发生的情况是,它被设置为整个 URL路径,这意味着该cookie不能被相同子域中的不同URL读取。

一个例子:

  1. 我在http://www.myserver.com/sub/mypage.php
  2. 响应请求的页面包括Set-Cookie标头,读取的myCookie = 12345; expires = 2012年6月27日星期三16:20:00 GMT
  3. 该Cookie已添加到.NET CookieCollection中。由于没有路径设置,路径为 的初始化为/sub/mypage.php
  4. 我在同一个子域下请求另一个页面,但需要mycookie cookie,例如, http://www.myserver.com/sub/anotherpage.php
  5. Cookie不是由.NET提供的,因为路径不完全匹配。如果路径是/分,它会一直担任正确

我已经执行使用Firefox浏览器的Firebug和Firecookie扩展相同的导航步骤。在真实浏览器会话中,路径设置正确,即对子域。

任何人都可以证实这一点,并可能指向我的解决方法或解决此问题?非常感谢。

回答

3

下面是有关内部代码的问题。看起来不像是一个意外的错误。如果不遵循标准,你应该报告问题。

switch (this.m_cookieVariant) 
{ 
    case CookieVariant.Plain: 
     this.m_path = absolutePath; 
     break; 

    case CookieVariant.Rfc2109: 
     this.m_path = absolutePath.Substring(0, absolutePath.LastIndexOf('/')); 
     break; 

    default: 
     this.m_path = absolutePath.Substring(0, absolutePath.LastIndexOf('/') + 1); 
     break; 
} 

因此,它使用普通cookie变体,除非cookie本身另有规定。你将不得不迭代所有的cookie检查。真的,这是我讨厌.net的cookie处理的众多原因之一。无法轻松获取所有网域/ Cookie。最简单的解决方法是执行以下操作。但是,您最终会得到重复的Cookie。所以你可能想要通过uri获取cookie。

public static CookieCollection FixCookies(CookieCollection collection) 
{ 
    foreach (Cookie cookie in collection) 
    { 
     if (string.IsNullOrEmpty(cookie.Path)) 
      continue; 

     int idx = cookie.Path.LastIndexOf('/'); 
     if (idx == -1) 
      continue; 

     cookie.Path = cookie.Path.Substring(0, idx); 
    } 
    return collection; 
} 

[STAThread] 
private static void Main(string[] args) 
{ 
    var http = (HttpWebRequest)WebRequest.Create("http://localhost/test/test.php"); 
    http.CookieContainer = new CookieContainer(); 
    var resp = (HttpWebResponse)http.GetResponse(); 
    http.CookieContainer.Add(FixCookies(resp.Cookies)); 
} 
+0

谢谢,威尔。它看起来像.NET默认cookie的'平原'版本0变种(从原始的Netscape实现),我不知道其实是正确的。我有兴趣了解Version和CookieVariant在内部是否被重写,但在那之前我会坚持使用您推荐解决此问题的解决方案。再次感谢! –

+0

该变体通过发送像'mycookie = 12345; expires = Wed,版本= 1,端口= 80'。设置版本会将其设置为Rfc2109。设置端口将改为将其设置为Rfc2965。 – Will