最近我使用Mechanize来做这种事情,但是我想使用Typhoeus,我已经在其他地方使用了它.我想模仿Mechanize的行为,问题是我想登录到一个站点并按登录用户的身份执行请求.这是脚本的通用版本:
require 'rubygems' require 'typhoeus' GET_URL = 'http://localhost:3000' POST_URL = "http://localhost:3000/admins/sign_in" URL = "http://localhost:3000/dashboard" USERNAME_FIELD = 'admin[email]' PASSWORD_FIELD = 'admin[password]' USERNAME = "admin@example.com" PASSWORD = "my_secret_password" def merge_cookies_into_cookie_jar(response) if response.headers_hash['set-cookie'].instance_of? Array response.headers_hash['set-cookie'].each do |cookie| @cookie_jar << cookie.split('; ')[0] end elsif response.headers_hash['set-cookie'].instance_of? String @cookie_jar << response.headers_hash['set-cookie'].split('; ')[0] end end # initialize cookie jar @cookie_jar = [] # for server to establish me a session response = Typhoeus::Request.get( GET_URL,:follow_location => true ) merge_cookies_into_cookie_jar(response) # like submiting a log in form response = Typhoeus::Request.post( POST_URL,:params => { USERNAME_FIELD => USERNAME,PASSWORD_FIELD => PASSWORD },:headers => { 'Cookie' => @cookie_jar.join('; ') } ) merge_cookies_into_cookie_jar(response) # the page I'd like to get in a first place,# but not working,redirects me back to login form with 401 Unauthorized :-( response = Typhoeus::Request.get( URL,:follow_location => true,:headers => { 'Cookie' => @cookie_jar.join('; ') } )
cookie被发送到服务器,但由于某种原因我没有登录.我在两个不同的站点上测试了它(其中一个是我的Rails应用程序的管理).知道我做错了什么,或者更好或更广泛适用于这个问题的解决方案?
解决方法
这是我能够成功运行的代码.
首先,你的cookie jar是一个数组,在我的代码中它需要是一个带替换的数组(或一个哈希).当我在我的真实应用程序上运行代码时,GET_URL响应返回会话cookie,但POST_URL响应返回不同的会话cookie.
# initialize cookie jar as a Hash @cookie_jar = {}
调整解析,以便获得每个cookie的名称和值:
def merge_cookies_into_cookie_jar(response) x = response.headers_hash['set-cookie'] case x ... when String x.split('; ').each{|cookie| key,value=cookie.split('=',2) @cookie_jar[key]=value } end end
cookie jar需要转换为字符串:
def cookie_jar_to_s @cookie_jar.to_a.map{|key,val| "#{key}=#{val}"}.join("; ") end
最后,更改标题以使用新的cookie_jar_to_s:
:headers => { 'Cookie' => cookie_jar_to_s }
奖励将是使cookie罐成为自己的类,也许是这样的:
class CookieJar < Hash def to_s self.to_a.map{|key,val| "#{key}=#{val}"}.join("; ") end def parse(*cookie_strings) cookie_strings.each{|s| s.split('; ').each{|cookie| key,2) self.[key]=value } } end end