Это ошибка CookieContainer?

Что я делаю:
Я разрабатываю "многопоточный", вот и все, смеется.
Мне нужно отправить форму перед извлечением данных со страницы, поэтому макет такой:

  1. ПОЛУЧИТЕ запрос к example.com/path/doc.jsp (мои данные).
  2. Проверьте, присутствует ли форма подтверждения в источнике документа. Если да, перейдите к шагу 3 (мои данные отсутствуют, сначала нужно отправить форму), в противном случае верните (поскольку формы для отправки нет и мои данные здесь).
  3. Получите запрос к example.com/path/sub/other.jsp (необходимое значение ключа).
  4. POST-запрос к example.com/path/submit.jsp (отправить значения).
  5. Проверьте ответ от запроса POST, если все в порядке, перейдите к 6, иначе вернитесь к 1.
  6. ПОЛУЧИТЕ запрос к example.com/path/doc.jsp (мои данные, опять же. Поскольку я отправил форму, теперь мои данные будут присутствовать).

Все работает нормально, за исключением случаев, когда ответ на запрос POST (шаг 4) говорит мне вернуться к шагу 1.

Эта проблема:
Одно из значений в форме мне нужно, чтобы извлечь его из файлов cookie, поэтому я использую GetCookies() функции, но, как я уже сказал, если ответ говорит мне вернуться к шагу 1, ВСЕ запросы (как GET, так и POST) после этого пропускают файлы cookie (и добавляются странные). Смотрите изображение ниже:

Ошибка Cookie
Объяснение изображения:

  • Первый вызов - это запрос GET к doc.jsp, где находятся мои данные.
  • Вторым вызовом является запрос other.jsp, так как форма подтверждения присутствует в исходном коде doc.jsp.
  • Третий вызов - когда я отправляю все значения.
  • Четвертый вызов - это снова запрос GET к doc.jsp, поскольку ответ формы отправки (третий вызов) велел мне повторить процесс. По сути, вызовы 4º ~ 6º совпадают с вызовами 1º ~ 3º, но с cookie-файлами.


Мой код:

public class CWeb : IDisposable
{
    private WebClientEx _wc;
    private string _originalUrl;

    public CWeb()
    {
        _wc = new WebClientEx(new CookieContainer());
    }

    public string downloadPage(string url)
    {
        _originalUrl = url;
        string pgSrc = "error";
        int tries = 0;

        while (tries < 3 && pgSrc == "error)
        {
            try
            {
                pgSrc = _wc.DownloadString(url);
            }
            catch (Exception err)
            {
                tries += 1;
                pgSrc = "error";
                ...
            }
        }

        if (needSubmit(pgSrc)) // needSubmit just peform IndexOf on pgSrc
            do
            {
                pgSrc = sendForm(pgSrc);
            } while (needSubmit(pgSrc));

        return WebUtility.HtmlDecode(pgSrc);
    }

    public string sendForm(pageSource)
    {
        // 1- Get Cookie Value
        string cookie = _wc.CookieContainer.GetCookies(new Uri(_originalUrl))["JSESSIONID"].Value;

        // 2- Get hidden values in pageSource parameter
        // skip this, since there's no web request here, only some html parsing
        // with Html Agility Pack
        ...

        // 3- Get key value
        string tmpStr = _wc.DownloadString("http://example.com/path/sub/other.jsp");
        ... more html parsing ...

        // 4- Build form
        NameValueCollection nvc = new NameValueCollection();
        nvc["param1"] = cookie;
        nvc["param2"] = key;
        ...

        // 5- Send
        _wc.UploadValues("example.com/path/submit.jsp", nvc);

        // 6- Return
        return _wc.DownloadString(_originalUrl);
    }

    public void Dispose()
    {
        _wc.Dispose();
    }
}


Основная программа:

static void Main(string[] args)
{
    // Load tons of 'doc' url list from database...
    List<string> urls = new List<string>();
    ...

    Parallel.ForEach(urls, (url) =>
        {
            using (CWeb crawler = new CWeb())
            {
                string pageData = crawler.downloadPage(url);
                ... parse html data here ...
            }
        });
}


Моя окружающая среда:

  • Использование Visual Studio Professional 2013.
  • Целевой платформой является.NET Framework 4.5.
  • Платформа x86 (отладка).
  • WebClientEx - это расширенная версия WebClient для работы с файлами cookie. Получите это здесь PasteBin. Я пытался реализовать BugFix_CookieDomain() (из этого вопроса), но даже с этим исправлением эта проблема все еще возникает.
  • Все мои URL включают префикс http: //.

  • Использовал Fiddler для просмотра информации о запросах.

  • Английский не мой родной язык... '-'

1 ответ

Я использую System.Net.WebRequest для чего-то похожего на то, что вы делаете. Он обрабатывает куки-файлы при использовании Http (подкласс HttpWebRequest в WebRequest) через свойство CookieContainer. Я заметил, что файлы cookie добавляются и, очевидно, также удаляются из контейнера для файлов cookie. Я считаю, что это полностью контролируется серверной стороной (веб-приложением, к которому вы обращаетесь). Он способен добавлять дополнительные куки.

Кроме того, если у файлов cookie есть дата истечения срока действия, флаг сброса и домен, поэтому, если истекает срок действия файлов cookie, сервер устанавливает флаг сброса или домен меняет список, и список применимых файлов cookie может измениться.

Не уверен, что это полезно, но я стараюсь.

Другие вопросы по тегам