web-dev-qa-db-fra.com

Comment implémenter la prise en charge des cookies dans Ruby net / http?

Je voudrais ajouter la prise en charge des cookies à une classe Ruby utilisant net/http pour naviguer sur le Web. Les cookies doivent être stockés dans un fichier pour survivre après la fin du script. Bien sûr, je peux lire les spécifications et écrire une sorte de gestionnaire, utiliser un format cookie.txt et ainsi de suite, mais cela semble vouloir dire réinventer la roue. Y a-t-il une meilleure façon d'accomplir cette tâche? soin des cookies?

46
Fluffy

Extrait de 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

mise à jour

#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
32
khelll

La réponse acceptée ne fonctionnera pas si votre serveur revient et attend plusieurs cookies. Cela peut se produire, par exemple, si le serveur renvoie un ensemble de cookies FedAuth [n]. Si cela vous affecte, vous voudrez peut-être envisager d'utiliser quelque chose comme suit:

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
42
mamills

La réponse acceptée ne fonctionne pas. Vous devez accéder à la représentation interne de l'en-tête de réponse où les multiples valeurs set-cookie sont stockées séparément, puis supprimer tout après le premier point-virgule de ces chaînes et les joindre ensemble. Voici un code qui fonctionne

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

Utilisez http-cookie , qui implémente l'analyse et le rendu conformes à la RFC, plus un bocal.

Un exemple grossier qui arrive à suivre une redirection post-connexion:

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

Pourquoi faire ceci? Parce que les réponses ci-dessus sont incroyablement insuffisantes et ne fonctionnent pas dans de nombreux scénarios conformes à la RFC (ce qui m'est arrivé), donc s'appuyer sur l'implémentation très lib juste ce qui est nécessaire est infiniment plus robuste si vous souhaitez gérer plus d'un cas particulier .

8
Lloeki

J'ai utilisé Curb et Mechanize pour un projet similaire. Activez simplement la prise en charge des cookies et enregistrez les cookies dans un cookiejar temporaire ... Si vous utilisez net/http ou des packages sans prise en charge des cookies intégrée, vous devrez écrire votre propre gestion des cookies.

3
CodeJoust

Vous pouvez envoyer des cookies de réception en utilisant des en-têtes.

Vous pouvez stocker l'en-tête dans n'importe quel cadre de persistance. Qu'il s'agisse d'une sorte de base de données ou de fichiers.

1
Matthew Schinckel