httprb / http

HTTP (The Gem! a.k.a. http.rb) - a fast Ruby HTTP client with a chainable API, streaming support, and timeouts
MIT License
3k stars 321 forks source link

cookie jar save to and load from file #646

Open dsisnero opened 3 years ago

dsisnero commented 3 years ago

jar = HTTP::CookieJar.new jar.load(filename)

or

jar = HTTP::CookiJare.new(store: :mozilla, filename: 'cookies.sqlite')

I want to use another http client to start a session , (cuprite), and then when I am authenticated I want to to use http. Being able to load a cookie jar file would enable one to share sessions between different clients.

tarcieri commented 3 years ago

The HTTP::CookieJar class comes from the http-cookie gem:

https://github.com/sparklemotion/http-cookie

dsisnero commented 3 years ago

I know. Can we add methods on http to save and load cookies?

tarcieri commented 3 years ago

The functionality to do this is already defined on the HTTP::CookieJar class:

https://www.rubydoc.info/gems/http-cookie/1.0.2/HTTP/CookieJar#save-instance_method

Are you asking for some sort of helper method that delegates to HTTP::CookieJar? Why not use the HTTP::CookieJar class directly?

Can you make a more concrete proposal for the functionality you want added? Perhaps a complete example of what you have in mind?

ixti commented 3 years ago

I'm going to work on (have some preliminray code that is not ready to be shared yet) with session alike object (I'm still sketching out API), but the very simple version (if you need this now for your own usage) will look like:

class WebBrowserAlikeClient
  attr_reader :cookies

  def initialize(&block)
    @cookies = HTTP::CookieJar.new
    @http    = block || -> { HTTP }
  end

  %i[get post].each do |verb|
    define_method(verb) { |*args, **kwargs| request(verb, *args, **kwargs) }
  end

  def request(verb, uri, headers: {}, **options)
    headers = HTTP::Headers.coerce(headers || {})
    cookies = @cookies.each(uri.to_s).map(&:to_s).join("; ")

    if cookies.empty?
      headers.delete(HTTP::Headers::COOKIE)
    else
      headers[HTTP::Headers::COOKIE] = cookies
    end

    @http.call.public_send(verb, uri, { :headers => headers, options }).tap do |res|
      response.headers.each do |k, v|
        @cookies.parse(v, res.uri) if HTTP::Headers::SET_COOKIE == k
      end
    end
  end
end