# frozen_string_literal: true require "forwardable" module HTTPX module Plugins # # This plugin implements a persistent cookie jar for the duration of a session. # # It also adds a *#cookies* helper, so that you can pre-fill the cookies of a session. # # https://gitlab.com/honeyryderchuck/httpx/wikis/Cookies # module Cookies using URIExtensions def self.extra_options(options) Class.new(options.class) do def_option(:cookies) do |cookies| return cookies if cookies.is_a?(Store) Store.new(cookies) end end.new(options) end class Store def initialize(cookies = nil) @store = Hash.new { |hash, origin| hash[origin] = HTTP::CookieJar.new } return unless cookies cookies = cookies.split(/ *; */) if cookies.is_a?(String) @default_cookies = cookies.map do |cookie, v| if cookie.is_a?(HTTP::Cookie) cookie else HTTP::Cookie.new(cookie.to_s, v.to_s) end end end def set(origin, cookies) return unless cookies @store[origin].parse(cookies, origin) end def [](uri) store = @store[uri.origin] @default_cookies.each do |cookie| c = cookie.dup c.domain ||= uri.authority c.path ||= uri.path store.add(c) end if @default_cookies store end end def self.load_dependencies(*) require "http/cookie" end module InstanceMethods extend Forwardable def_delegator :@options, :cookies def initialize(options = {}, &blk) super({ cookies: Store.new }.merge(options), &blk) end def with_cookies(cookies) branch(default_options.with_cookies(cookies)) end def wrap return super unless block_given? super do |session| old_cookies_store = @options.cookies.dup begin yield session ensure @options = @options.with_cookies(old_cookies_store) end end end private def on_response(request, response) @options.cookies.set(request.origin, response.headers["set-cookie"]) if response.respond_to?(:headers) super end def build_request(*, _) request = super request.headers.set_cookie(@options.cookies[request.uri]) request end end module HeadersMethods def set_cookie(jar) return unless jar cookie_value = HTTP::Cookie.cookie_value(jar.cookies) return if cookie_value.empty? add("cookie", cookie_value) end end end register_plugin :cookies, Cookies end end