【问题标题】:How to implement cookie support in ruby net/http?如何在 ruby​​ net/http 中实现 cookie 支持?
【发布时间】:2023-03-24 04:17:01
【问题描述】:

我想为一个使用 net/http 浏览网页的 ruby​​ 类添加 cookie 支持。 Cookie 必须存储在文件中才能在脚本结束后继续存在。当然,我可以阅读规范并编写某种处理程序,使用某种 cookie.txt 格式等等,但这似乎意味着重新发明轮子。有没有更好的方法来完成这项任务?也许是某种用于处理 cookie 的 cooie jar 类?

【问题讨论】:

  • 我原来用过mechanize,看看这个问题stackoverflow.com/questions/1448100/…bounty is still active)
  • 我知道这不是一个真正的答案,但我一直在努力解决这个问题,最后尝试了rest-client,它立即奏效了。我根本不需要手动处理 cookie。

标签: ruby cookies


【解决方案1】:

如果您的服务器返回并需要多个 cookie,则接受的答案将不起作用。例如,如果服务器返回一组 FedAuth[n] cookie,就会发生这种情况。如果这对您有影响,您可能需要考虑使用以下内容:

http = Net::HTTP.new('https://example.com', 443)
http.use_ssl = true
path1 = '/index.html'
path2 = '/index2.html'

# make a request to get the server's cookies
response = http.get(path)
if (response.code == '200')
    all_cookies = response.get_fields('set-cookie')
    cookies_array = Array.new
    all_cookies.each { | cookie |
        cookies_array.push(cookie.split('; ')[0])
    }
    cookies = cookies_array.join('; ')

    # now make a request using the cookies
    response = http.get(path2, { 'Cookie' => cookies })
end

【讨论】:

  • 哦,刚刚发布了我的答案,然后意识到这与我的代码在更多行代码中的作用相同。投票支持公平:)
  • 不,除了 ssl 的东西,你的例子要好得多,因为它是可读的。 'i-can-write-this-in-one-line' 方法适用于练习或 jquery 大师,我相信它与 stackoverflow 无关。
  • 您可以在响应中包含“set-cookie”标头,顺便说一下,这些标头不是代码 200。该代码会错过这些。
  • 太棒了!!您的回答挽救了我的生命.. :-) 您能否将我重定向到一些资源,从那里获得这些信息。
【解决方案2】:

取自DZone Snippets

http = Net::HTTP.new('profil.wp.pl', 443)
http.use_ssl = true
path = '/login.html'

# GET request -> so the host can set his cookies
resp, data = http.get(path, nil)
cookie = resp.response['set-cookie'].split('; ')[0]


# POST request -> logging in
data = 'serwis=wp.pl&url=profil.html&tryLogin=1&countTest=1&logowaniessl=1&login_username=blah&login_password=blah'
headers = {
  'Cookie' => cookie,
  'Referer' => 'http://profil.wp.pl/login.html',
  'Content-Type' => 'application/x-www-form-urlencoded'
}

resp, data = http.post(path, data, headers)


# Output on the screen -> we should get either a 302 redirect (after a successful login) or an error page
puts 'Code = ' + resp.code
puts 'Message = ' + resp.message
resp.each {|key, val| puts key + ' = ' + val}
puts data

更新

#To save the cookies, you can use PStore
cookies = PStore.new("cookies.pstore")

# Save the cookie  
cookies.transaction do
  cookies[:some_identifier] = cookie
end

# Retrieve the cookie back
cookies.transaction do
  cookie = cookies[:some_identifier] 
end

【讨论】:

  • >> "cookies 必须存储在文件中才能在脚本结束后继续存在"
  • -1: 服务器的“set-cookie”标头给出的 cookie 格式与客户端在“cookie”中发送的 cookie 格式相同标题。请注意RFC2109 的 4.2.2 和 4.3.4 部分中分号的不同作用。需要去掉 set-cookie 标头的“cookie-av”部分,否则在将 cookie 发送到服务器时可能会丢失部分 cookie。
  • 更新以使用 PStore 存储 cookie
  • 修复了 rampion 提出的问题
  • 但为什么是 .split('; ')[0] ?
【解决方案3】:

接受的答案不起作用。您需要访问响应标头的内部表示,其中多个 set-cookie 值分别存储,然后从这些字符串中删除第一个分号之后的所有内容并将它们连接在一起。这是有效的代码

r = http.get(path)
cookie = {'Cookie'=>r.to_hash['set-cookie'].collect{|ea|ea[/^.*?;/]}.join}
r = http.get(next_path,cookie)

【讨论】:

  • to_hash[set-cookie] 也许是nil。你可以在现代 Ruby 上使用to_hash['set-cookie']&.collect 来处理它。
  • 很好,那是哪个版本的 Ruby?
  • &.,安全导航运算符,在 Ruby 2.3.0 中引入。
【解决方案4】:

使用http-cookie,它实现了符合RFC的解析和渲染,加上一个jar。

一个发生在登录后重定向之后的粗略示例:

require 'uri'
require 'net/http'
require 'http-cookie'

uri = URI('...')
jar = HTTP::CookieJar.new

Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
  req = Net::HTTP::Post.new uri
  req.form_data = { ... }
  res = http.request req
  res.get_fields('Set-Cookie').each do |value|
    jar.parse(value, req.uri)
  end

  fail unless res.code == '302'

  req = Net::HTTP::Get.new(uri + res['Location'])
  req['Cookie'] = HTTP::Cookie.cookie_value(jar.cookies(uri))
  res = http.request req
end

为什么要这样做?因为上面的答案非常不足,而且在许多符合 RFC 的场景中(发生在我身上)都不起作用,所以如果你想处理一个以上的特定情况,那么依靠 lib 来实现所需的内容会变得更加健壮.

【讨论】:

  • jar 定义在哪里?
【解决方案5】:

我在一个类似的项目中使用了 Curb 和 Mechanize。 只需启用 cookie 支持并将 cookie 保存到临时 cookiejar... 如果您使用 net/http 或没有内置 cookie 支持的包,您将需要编写自己的 cookie 处理。

【讨论】:

  • 我在无法安装路缘石的窗户上:(
【解决方案6】:

您可以使用标头发送接收 cookie。

您可以将标头存储在任何持久性框架中。无论是某种数据库,还是文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 2016-10-28
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多