Xpoint
   [напомнить пароль]

Проблема с LWP и Cookie

Метки: [без меток]
2008-07-07 11:33:53 [обр] sd[досье]

Здравствуйте! Проблема такая. Мне нужно получить страницу с URL http://mysite.ru, передав на неё Cookie вида "id=12345". Причём мне хотелось бы передать этот куки вручную.
Что я делаю:

use LWP::UserAgent;
use LWP::ConnCache;

$ua = LWP::UserAgent->new;
$cache = $ua->conn_cache(LWP::ConnCache->new( )); #просто чтобы держать соединение
$url = 'http://mysite.ru';
$resp = $ua->get($url,
  'Accept' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
  'Accept-Language' => 'ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3',
  'Accept-Encoding' => 'gzip,deflate',
  'Accept-Charset' => 'windows-1251,utf-8;q=0.7,*;q=0.7',
  'Connection' => 'keep-alive',
  'Keep-Alive' => '300',
  'Cookie' => 'id=12345',
);

if ($resp->is_success) {
    print $resp->content;
}
else {
    print $ans->status_line, "\n";
}

Сейчас я ещё опишу немного про настройки сервера, потом будет понятно зачем.

В корне сервера (я имею доступ к серверу) лежит .htaccess, где прописано:
RewriteEngine On
RewriteRule index.htm http://mysite.ru/cgi-bin/index.pl
То есть при обращении к http://mysite.ru выполняется скрипт /cgi-bin/index.pl. Этот редирект (ну или точнее подмена адреса) работает нормально в браузере, да и вообще нормально работает.

Серверный скрипт /cgi-bin/index.pl имеет вид:
#!/usr/bin/perl
print "Content-Type: text/html; charset=windows-1251\n\n";
print "Cookie: $ENV{'HTTP_COOKIE'}";

То есть просто выводит значение куки.

Если, $url в приведённом выше скрипте HTTP-клиента сделать равным 'http://mysite.ru' (как там указано сейчас), то скрипт выводит: "Cookie: ", то есть куки нет (ну на самом деле я проверял, там в хэше окружения вообще нет ключа 'HTTP_COOKIE'), а если изменить $url на 'http://mysite.ru/cgi-bin/index.pl', то всё работает (то есть выводится значение куки: "Cookie: id=12345").
При этом, в браузере куки выводится всегда, как и должно быть.
Как это так??!! Я что-то вообще голову сломал уже =\ Заранее спасибо.

спустя 43 минуты [обр] Роман Чемисов(36/350)[досье]

sd[досье]
По-моему, Ваша кука просто не передаётся при редиректе.
Правильней было бы создать $ua->cookie_jar( $cookie_jar_obj ) и в него "забить" куку, тогда бы она всегда проходила.

Попробуйте посмотреть, что на самом деле происходит с помощью HTTP::Recorder

спустя 9 минут [обр] Иванов Михаил aka Ivanych(0/70)[досье]

Роман Чемисов[досье]
Даже если дело в редиректе, то это все-равно не имеет отношения к тому, как создавать куку. Редирект внутренний, поэтому клиентская сторона о нем ничего не знает.

sd[досье]
Скажите настоящий $url.

спустя 13 минут [обр] sd[досье]

Роман Чемисов, спасибо, я думал испльзовать $cookie_jar_obj (пока не попрбовал), но сейчас уже принципиально хочется разобраться.
HTTP::Recorder к сожаленю под ActiveState Perl 5.10 пока найти не могу. Есть HTTP::RecordedSession, но пока не разобрался ещё что это..

Иванов Михаил aka Ivanych, вот: http://aiu.susu.ru

спустя 21 минуту [обр] Иванов Михаил aka Ivanych(0/70)[досье]

sd[досье]
Ага, ну вот и ответ. У Вас на сервере не внутренний редирект. Вы, определенно, забыли указать фраг [R] в приведеном содержимом .htaccess.

В чем, собственно, дело:

Ваш скрипт делает запрос к http://aiu.susu.ru, в запросе передается кука. Сервер на этот запрос выдает внешний редирект на http://aiu.susu.ru/cgi-bin/index.pl. Скрипт, соответственно, делает новый запрос на указанный адрес, но куки-то в этом новом запросе уже нет. Поэтому в ответ и возвращается пустое "Cookie:".

Решение - использовать сookie_jar, как уже сказал Роман Чемисов[досье].

спустя 1 час 21 минуту [обр] sd[досье]
Хорошо, спасибо большое!
Хотел бы ещё спросить, а как именно вы смогли это проследить? Я так понимаю для этого нужно иметь возможность подробно просма триваь заголовки всех запросов и ответов. Может быть это немножко не по теме, но всё-таки. Какие средства вы могли порекомендовать для этого?
спустя 40 минут [обр] sd[досье]
Как вариант нашёл ещё такое решение:
$ua->default_headers->push_header('Cookie' => 'id=12345');
то есть по умолчанию для каждого запроса от $ua в заголовке будет передаваться данный кукис.
спустя 9 часов [обр] Иванов Михаил aka Ivanych(0/70)[досье]

Определить внешний редирект легко без всяких средств.

Наберите в браузере адрес http://aiu.susu.ru. Если бы никакого редиректа небыло вообще, или, если бы редирект был внутренний, то в браузере просто открылась бы запрошенная страница, а адрес бы не изменился.

Но, как мы видим, набранный адрес вдруг волшебным образом меняется на http://aiu.susu.ru/cgi-bin/index.pl. И только после этого открывается страница. Это говорит от том, что сервер выполнил внешний редирект с http://aiu.susu.ru на http://aiu.susu.ru/cgi-bin/index.pl.

Что касается средств, которые действительно могут пригодиться в более сложных случаях. Средство тут, по сути, одно - просмотр HTTP-заголовков, которыми обмениваются браузер и сервер. Конкретных программ для этого дела имеется во множестве, лично я рекомендую плагин Live HTTP Headers для Файрфокса.

спустя 1 минуту [обр] Иванов Михаил aka Ivanych(0/70)[досье]
Да, на иллюстрации - то, что может показать Live HTTP Headers.
спустя 10 часов [обр] sd[досье]
Спасибо
Powered by POEM™ Engine Copyright © 2002-2005