代码之家  ›  专栏  ›  技术社区  ›  Fluffy

如何在RubyNet/HTTP中实现cookie支持?

  •  44
  • Fluffy  · 技术社区  · 15 年前

    我想向Ruby类添加cookie支持,利用net/http浏览Web。在脚本结束后,必须将cookie存储在一个文件中才能生存。当然,我可以阅读规范并编写某种处理程序,使用cookie.txt格式等等,但这似乎意味着要重新设计轮子。有没有更好的方法来完成这项任务?也许是一个库伊罐子班来做饼干?

    6 回复  |  直到 9 年前
        1
  •  32
  •   Lifeweaver dbrin    9 年前

    取自 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
    
        2
  •  41
  •   mamills    13 年前

    如果您的服务器返回并期望多个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
    
        3
  •  12
  •   akuhn    13 年前

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

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

    使用 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实现所需要的功能是非常强大的。

        5
  •  3
  •   CodeJoust    15 年前

    我在一个类似的项目中使用了路缘石和机械。 只需启用cookies支持并将cookies保存到临时cookiejar… 如果您使用的是NET/HTTP或没有内置cookie支持的包,则需要编写自己的cookie处理。

        6
  •  1
  •   Matthew Schinckel    15 年前

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

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

    推荐文章