使用 HTTParty 解析 HTTP 标头“set-cookie”

Posted

技术标签:

【中文标题】使用 HTTParty 解析 HTTP 标头“set-cookie”【英文标题】:Parsing HTTP header 'set-cookie' with HTTParty 【发布时间】:2016-07-19 17:01:18 【问题描述】:

我正在使用 HTTParty 发出 HTTP 请求和使用 REST API。现在我想重用我通过 POST 调用的登录页面设置的 cookie。

class SomeImporter
  include HTTParty

  def self.login
    response = self.post('https://www.example.com/login', :query => :user => 'myusername', :password => 'secret')
    self.default_cookies.add_cookies(response.header['set-cookie'])
    self.get('https://www.example.com/protected')
  end
end

使用此代码未正确设置 cookie。 如何正确解析 HTTParty 给出的 'set-cookie' 标头并为下一个请求设置 cookie?

【问题讨论】:

【参考方案1】:

感谢@dineshspabu,我能够遵循他的模式并添加一些修改来处理过期日期。希望对您有所帮助:

def cookies_to_hash(set_cookie)
  set_cookie = set_cookie.gsub(/Expires=[a-zA-Z]+,/) do |m|
    # replace , with #####
    m[0..-2] + "#####"
  end
  set_cookie = set_cookie.split(',')
  # Cookies as array of hashes
  all_cookies = []
  set_cookie.each do |each_cookie|
    ecookie = []
    each_cookie.strip.split(';').each do |cookie_attr|
      # replace ##### with , back
      ecookie << cookie_attr.split("=").map|e| e.gsub(/#####/, ',') if e
    end
    all_cookies << Hash[ecookie]
  end
  all_cookies
end

【讨论】:

【参考方案2】:
def cookies_to_hash(acookies)
    vs = acookies.split(',')
    ak = Array.new
    # Avoiding break in expiry date comma
    vs.each_cons(2) do |v, vn|
        unless(vn.include?("="))
            ak << "#v#vn"
        else
            ak << v if(v.include?("="))
        end
    end
    # Cookies as array of hashes
    all_cookies = []
    ak.each do |each_cookie|
        ecookie = []
        each_cookie.split(';').each do |cookie_attr|
            ecookie << cookie_attr.split("=")
        end
        all_cookies << Hash[ecookie]
    end
    all_cookies
end

上述方法将帮助您将响应标头中的 set-cookies 转换为有效的哈希数组。处理到期时附加逗号的问题。

【讨论】:

很遗憾,它不处理过期日期【参考方案3】:

通常在 HTTP 标头中每个 Set-Cookie 都有一个条目。 HTTParty 将它们合并为一个字符串作为逗号分隔的列表。但是 HTTParty 在将它们添加回默认 cookie 时不会自行拆分它们。您必须自己解析它们。

可以使用以下方法解析“set-cookie”。将其添加到您的班级:

# Parse the 'set-cookie' string
# @param [String] all_cookies_string
# @return [Hash]
def self.parse_set_cookie(all_cookies_string)
  cookies = Hash.new

  if all_cookies_string.present?
    # single cookies are devided with comma
    all_cookies_string.split(',').each 
      # @type [String] cookie_string
        |single_cookie_string|
      # parts of single cookie are seperated by semicolon; first part is key and value of this cookie
      # @type [String]
      cookie_part_string  = single_cookie_string.strip.split(';')[0]
      # remove whitespaces at beginning and end in place and split at '='
      # @type [Array]
      cookie_part         = cookie_part_string.strip.split('=')
      # @type [String]
      key                 = cookie_part[0]
      # @type [String]
      value               = cookie_part[1]

      # add cookie to Hash
      cookies[key] = value
    
  end

  cookies
end

通过调整此行,可以将 cookie 添加到 HTTParty 以用于以下请求:

self.default_cookies.add_cookies(self.parse_set_cookie(response.header['set-cookie']))

self.parse_set_cookie 内,cookie 仅提取名称和值。您可以扩展它以获得更多详细信息,例如PathDomain 等。有关详细信息,请参阅RFC 2109(4.2.2 Set-Cookie 语法)。

【讨论】:

cookie 中有日期,例如 Wed,,你不能用 `,' 分割

以上是关于使用 HTTParty 解析 HTTP 标头“set-cookie”的主要内容,如果未能解决你的问题,请参考以下文章

使用 HTTParty 发送多个文件

尝试使用 HTTParty 或 Net:HTTP(或等)连接到“摘要式身份验证”网络服务

Ruby HTTParty - 获取重定向的 URL

如何关闭 HTTParty 帖子正文中的 URI 编码?

如何使用 ktor 解析 HTTP 标头

带HTTParty Gem的美味API