Разбор HTTP-заголовка set-cookie с помощью HTTParty

Я использую HTTParty для создания HTTP-запросов и использования REST API. Теперь я хочу повторно использовать файлы cookie, установленные страницей входа, которую я вызвал через POST.

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 не установлены правильно с этим кодом. Как правильно проанализировать заголовок «set-cookie», заданный HTTParty, и установить файлы cookie для следующего запроса?


person Sven R.    schedule 31.03.2016    source источник


Ответы (3)


Обычно для каждого Set-Cookie в заголовке HTTP имеется одна запись. 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 извлекаются только с именем и значением. Вы можете расширить его, чтобы получить больше деталей, таких как Path, Domain и так далее. Дополнительные сведения см. в RFC 2109 (4.2.2 Синтаксис Set-Cookie).

person Sven R.    schedule 31.03.2016
comment
В файле cookie есть дата, такая как Wed,, которую нельзя разделить на `,' - person tkhuynh; 09.08.2018

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 в заголовках ответов в действительный массив хэшей. Решены проблемы с дополнительными запятыми в конце срока действия.

person dineshsprabu    schedule 01.03.2017
comment
К сожалению, он не обрабатывает дату истечения срока действия - person tkhuynh; 10.08.2018

Благодаря @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
person tkhuynh    schedule 09.08.2018