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?
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
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
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)
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 .
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.
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.