Ruby's open-uri и печенье - PullRequest
       8

Ruby's open-uri и печенье

23 голосов
/ 01 сентября 2009

Я хотел бы сохранить куки-файлы от одного вызова open-uri и передать их следующему. Я не могу найти правильные документы для этого. Буду признателен, если вы скажете мне правильный способ сделать это.
ЗАМЕЧАНИЯ: w3.org - это не фактический URL, но он короче; притвориться, что печенье имеет значение здесь.

h1 = open("http://www.w3.org/")
h2 = open("http://www.w3.org/People/Berners-Lee/", "Cookie" => h1.FixThisSpot)

Обновление через 2 дня : Хотя это не было риторическим вопросом, я гарантирую, что это возможно. Обновление после переката : Видите (ответ), это возможно. Это заняло у меня некоторое время, но это работает.

Ответы [ 6 ]

30 голосов
/ 02 сентября 2009

Я думал, что кто-то просто узнает, но я думаю, что это обычно не делается с open-uri. Вот уродливая версия, которая не проверяет ни конфиденциальность, ни срок действия, ни правильный домен, ни правильный путь:

h1 = open("http://www.w3.org/")
h2 = open("http://www.w3.org/People/Berners-Lee/",
          "Cookie" => h1.meta['set-cookie'].split('; ',2)[0])

Да, это работает. Нет, это не красиво, не полностью соответствует рекомендациям и не обрабатывает несколько файлов cookie (как есть).

Ясно, что HTTP - очень простой протокол, и open-uri позволяет вам использовать его в большинстве случаев. Я думаю, что мне действительно нужно было знать, как получить cookie из запроса h1, чтобы он мог быть передан в запрос h2 (ту часть, которую я уже знал и показал). Здесь удивительно то, что многие люди в основном хотели ответить, сказав мне не использовать open-uri, и только один из них показал, как получить набор файлов cookie в одном запросе и передать его следующему запросу.

13 голосов
/ 01 сентября 2009

Вам необходимо добавить заголовок «Cookie».

Я не уверен, может ли open-uri сделать это или нет, но это можно сделать с помощью Net :: HTTP.

# Create a new connection object.
conn = Net::HTTP.new(site, port)

# Get the response when we login, to set the cookie.
# body is the encoded arguments to log in.
resp, data = conn.post(login_path, body, {})
cookie = resp.response['set-cookie']

# Headers need to be in a hash.
headers = { "Cookie" => cookie }

# On a get, we don't need a body.
resp, data = conn.get(path, headers)
4 голосов
/ 14 декабря 2010

Спасибо, Мэтью Шинкель, ваш ответ был действительно полезен. Используя Net :: HTTP я был успешным

        # Create a new connection object.
          site = "google.com"
          port = 80
          conn = Net::HTTP.new(site, port)

        # Get the response when we login, to set the cookie.
        # body is the encoded arguments to log in.
          resp, data = conn.post(login_path, body, {})
          cookie = resp.response['set-cookie']

        # Headers need to be in a hash.
          headers = { "Cookie" => cookie }

        # On a get, we don't need a body.
          resp, data = conn.get(path, headers)

          puts resp.body
2 голосов
/ 02 сентября 2009

В зависимости от того, что вы пытаетесь достичь, проверьте webrat . Я знаю, что он обычно используется для тестирования, но он также может поражать живые сайты, и он делает много вещей, которые ваш веб-браузер сделает для вас, например, сохранение файлов cookie между запросами и следование перенаправлениям.

1 голос
/ 01 сентября 2009

вам придется развернуть свою собственную поддержку файлов cookie, проанализировав мета-заголовки при чтении и добавив заголовок cookie при отправке запроса, если вы используете open-uri. Попробуйте использовать httpclient http://raa.ruby -lang.org / project / httpclient / или что-то вроде механизации вместо http://mechanize.rubyforge.org/, поскольку в них встроена поддержка файлов cookie.

0 голосов
/ 13 октября 2011

Существует реализация jar-файлов cookie RFC 2109 и RFC 2965, для которой требуется стандартная совместимая обработка cookie.

https://github.com/dwaite/cookiejar

...