Comment implémenter le support des cookies dans ruby ​​net / http?

J’aimerais append le support 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 le format cookie.txt, etc., mais cela semble vouloir dire réinventer la roue. Y a-t-il une meilleure façon d’accomplir cette tâche? Peut-être une sorte de classe de cooie jar pour prendre soin des cookies?

Tiré 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 

mettre à 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 # Resortingeve the cookie back cookies.transaction do cookie = cookies[:some_identifier] end 

La réponse acceptée ne fonctionnera pas si votre serveur retourne et attend plusieurs cookies. Cela peut se produire, par exemple, si le serveur renvoie un ensemble de cookies FedAuth [n]. Si cela vous concerne, vous pourriez envisager d’utiliser plutôt les éléments suivants:

 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 de cookie d’ensemble sont stockées séparément, puis supprimez tout ce qui suit le premier point-virgule de ces chaînes et regroupez-les. Voici le 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 une parsing et un rendu compatibles RFC, plus un jar.

Un exemple brutal qui arrive à suivre une redirection post-login:

 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? Comme les réponses ci-dessus sont incroyablement insuffisantes et ne fonctionnent pas dans de nombreux scénarios compatibles RFC (ce qui m’est arrivé), il est infiniment plus fiable de s’appuyer sur plusieurs bibliothèques pour implémenter plus d’un cas particulier. .

J’ai utilisé Curb and 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, vous devrez écrire votre propre traitement des cookies.

Vous pouvez envoyer des cookies de réception à l’aide d’en-têtes.

Vous pouvez stocker l’en-tête dans n’importe quel framework de persistance. Que ce soit une firebase database ou des fichiers.