9

基本的な Web クロールを含むプロジェクトに取り組んでいます。私は HttpWebRequest と HttpWebResponse をうまく使ってきました。Cookie の処理については、毎回 HttpWebRequest.CookieContainer に割り当てる CookieContainer が 1 つだけあります。毎回新しい Cookie が自動的に取り込まれ、追加の処理は必要ありません。これは、以前は機能していた Web サイトの 1 つが突然機能しなくなった少し前まで、すべて正常に機能していました。Cookie に問題があることはかなり確信していますが、Cookie が機能していたときの記録を保持していないため、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)));

これは、2 つの Cookie を設定する 2 つのページにアクセスすることをシミュレートします。次に、これらの Cookie のどれが 3 つのページのそれぞれに設定されるかを確認します。

2 つの Cookie のうち、1 つはパスを指定せずに設定され、もう 1 つはパスが指定されています。パスが指定されていない場合、Cookie はそのドメイン内の任意のページに送り返されると想定していましたが、その特定のページにのみ送り返されるようです。一貫性があるので、それは正しいと思います。

私にとっての主な問題は、パスが指定された Cookie の処理です。確かに、パスが指定されている場合、Cookie はそのパスに含まれるすべてのページに送信されます。したがって、上記のコードでは、「CookieWithPath」は、page1.html、page2.html、および page3.html を含む /some/path/ 内のすべてのページに対して有効である必要があります。確かに、2 つの「NoPathCookie」インスタンスをコメント アウトすると、予想どおり、「CookieWithPath」が 3 つのページすべてに送信されます。ただし、上記のように「NoPathCookie」を含めると、「CookieWithPath」は page2.html と page3.html にのみ送信され、page1.html には送信されません。

これはなぜですか、それは正しいですか?

この問題を検索すると、CookieContainer でのドメイン処理に関する問題についての議論に出くわしましたが、パス処理に関する議論は見つかりませんでした。

Visual Studio 2005 / .NET 2.0 を使用しています

4

1 に答える 1

2

パスが指定されていない場合、Cookie はそのドメイン内の任意のページに送り返されると想定していましたが、その特定のページにのみ送り返されるようです。一貫性があるので、それは正しいと思います。

ええ、それは正しいです。ドメインまたはパスが指定されていない場合は常に、現在の URI から取得されます。

では、CookieContainer を見てみましょう。問題のメソッドは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これは、Cookie のパスの (ソートされた) リストです。/directory/subdirectory/より具体的なパス ( など) があまり具体的でないパス ( など) の前に/directory/配置され、そうでない場合は、辞書順 ( の/directory/page1前に配置)でソートされます/directory/page2

コードは実際には次のことを行います: 最初のパス (要求された URI のパスのプレフィックス) が見つかるまで、この Cookie のパスのリストを反復処理します。次に、そのパスの下にある Cookie を出力に追加して に設定flag2しますtrue。これは、「OK、要求された URI に実際に関連するリスト内の場所をようやく見つけました」という意味です。その後、要求された URI のパスのプレフィックスではない最初に一致したパスは、関連するパスの最後であると見なされるため、コードは を実行して Cookie の検索を停止し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 の場合、page2.htmlアイテムを処理する機会がなく、アイテムでコードが壊れ/some/path/ます。

結論として、これは明らかに CookieContainer の別のバグです。接続時に報告する必要があると思います。

PS: 1 つのクラスあたりのバグが多すぎます。このクラスのテストを作成した MS の担当者がすでに解雇されていることを願っています。

于 2013-02-20T12:24:53.113 に答える