9

I'd like to open my stackoverflow.com page via ruby.
And I'd like to see it as if I am authenticated.

I took usr cookie from Google Chrome and created the following snippet:

require 'net/http'
require 'cgi'

url = "http://stackoverflow.com/users/1650525/alex-smolov"
uri = URI(url)
http = Net::HTTP.new(uri.host, 80)
request = Net::HTTP::Get.new(uri.request_uri)

cookie = CGI::Cookie.new("usr", "[my cookie is here]")
request['Cookie'] = cookie
r = http.request(request)
puts r.body

It does output a page, but I'm not authenticated there.

Is it possible to make a Net::HTTP::Get request in Ruby with cookie?

Alex Smolov
  • 1,831
  • 4
  • 24
  • 43

2 Answers2

10

You need to call CGI::Cookie.to_s method.

request['Cookie'] = cookie.to_s

Try following code with / without .to_s.

require 'net/http'
require 'cgi'

uri = URI("http://httpbin.org/cookies")
http = Net::HTTP.new(uri.host, 80)
request = Net::HTTP::Get.new(uri.request_uri)
cookie1 = CGI::Cookie.new('usr', 'blah')
request['Cookie'] = cookie1.to_s # <---
r = http.request(request)
puts r.body

UPDATE

As the other answer mentioned, the resulted string is for server output. You need to strip out ; path= part.

CGI::Cookie.new('usr', 'value').to_s.sub(/; path=$/, '')
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Thank you very much! It still doesn't work at `stackoverflow`, but it could be that I am using the wrong cookies. I'll figure it out. Thanks again!! – Alex Smolov Mar 23 '14 at 17:57
9

The accepted answer is imho incorrect. CGI::Cookie#to_s generates string which should SERVER send to client, not something Net::HTTP should use. It can be easily demonstrated:

[1] pry(main)> require 'cgi'
=> true
[2] pry(main)> CGI::Cookie.new('usr', 'value').to_s
=> "usr=value; path="

Code like this should work better.

require 'net/http'
require 'cgi'

uri = URI("http://httpbin.org/cookies")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
request['Cookie'] = "usr=#{CGI.encode cookie_value}"
r = http.request(request)
puts r.body

Or in case you have multiple cookies in a hash:

h = {'cookie1' => 'val1', 'cookie2' => 'val2'}
req['Cookie'] = h.map { |k,v| "#{k}=#{CGI.encode v}" } .join('; ')
graywolf
  • 7,092
  • 7
  • 53
  • 77
  • Nice pointing it out. I missed that. I updated the answer to address the issue. Thank you. – falsetru Mar 21 '17 at 00:54
  • Out of curiosity, why are you sticking with `CGI::Cookie` so much, I don't see any benefit when you still have to manipulte `#to_s` output afterward – graywolf Mar 21 '17 at 10:56
  • It was coming from original question. My point was to use `to_s` to get the string. BTW, using `CGI::Cookie`, you don't need to call CGI.encode yourself. – falsetru Mar 21 '17 at 15:40