web-dev-qa-db-ja.com

Ruby net / httpでCookieサポートを実装するには?

Net/httpを利用してWebを閲覧するRubyクラスにcookieサポートを追加したいと思います。スクリプトの終了後も存続するには、Cookieをファイルに保存する必要があります。もちろん、仕様を読んで何らかのハンドラーを作成し、cookie.txt形式などを使用することもできますが、それは車輪の再発明を意味するようです。このタスクを達成するためのより良い方法はありますか?たぶん、クッキーの世話をするクーリージャークラスのようなものでしょうか?

46
Fluffy

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

update

#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

サーバーが戻って複数のCookieを予期している場合、受け入れられた回答は機能しません。これは、たとえば、サーバーがFedAuth [n] Cookieのセットを返す場合に発生する可能性があります。これが影響する場合は、代わりに次の行に沿って何かを使用することを検討してください。

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

受け入れられた答えは機能しません。複数のset-cookie値が個別に格納されている応答ヘッダーの内部表現にアクセスし、これらの文字列から最初のセミコロン以降をすべて削除して、それらを結合する必要があります。動作するコードは次のとおりです

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

http-cookie を使用します。これは、RFC準拠の解析とレンダリング、およびjarを実装します。

ログイン後のリダイレクトをたまたま辿る粗雑な例:

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

どうしてですか?上記の答えは信じられないほど不十分であり、フラットアウトは多くのRFC準拠のシナリオでは機能しないため(私に起こりました)、複数の特定のケースを処理したい場合、必要なものだけを実装する非常にlibに依存することは無限に堅牢です。

8
Lloeki

同様のプロジェクトにCurbとMechanizeを使用しました。 Cookieのサポートを有効にして、一時的なCookiejarにCookieを保存するだけです。net/ httpまたはCookieのサポートが組み込まれていないパッケージを使用している場合は、独自のCookie処理を記述する必要があります。

3
CodeJoust

ヘッダーを使用して受信Cookieを送信できます。

ヘッダーは永続フレームワークに保存できます。何らかのデータベースか、ファイルか。

1