Skip to content

Commit 0dd249f

Browse files
committed
Refactor cookie API
Remove cookie management from Options. Chainable#cookies now sets the Cookie header directly with no implicit merging (last call wins). Response#cookies returns Array<HTTP::Cookie> instead of CookieJar. Closes #536.
1 parent 65c937b commit 0dd249f

14 files changed

Lines changed: 43 additions & 72 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5454
rejects unknown keys, non-numeric values, string keys, and empty hashes (#754)
5555
- Bumped min llhttp dependency version
5656
- **BREAKING** Handle responses in the reverse order from the requests (#776)
57+
- **BREAKING** `Response#cookies` now returns `Array<HTTP::Cookie>` instead of
58+
`HTTP::CookieJar`. The `cookies` option has been removed from `Options`;
59+
`Chainable#cookies` now sets the `Cookie` header directly with no implicit
60+
merging — the last `.cookies()` call wins (#536)
5761

5862
### Removed
5963

lib/http/chainable.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,20 @@ def headers(headers)
164164
# @example
165165
# HTTP.cookies(session: "abc123").get("http://example.com")
166166
#
167-
# @param [Hash] cookies cookies to set
167+
# @param [Hash, Array<HTTP::Cookie>] cookies cookies to set
168168
# @return [HTTP::Session]
169169
# @api public
170170
def cookies(cookies)
171-
branch default_options.with_cookies(cookies)
171+
value = cookies.map do |entry|
172+
case entry
173+
when HTTP::Cookie then entry.cookie_value
174+
else
175+
name, val = entry
176+
HTTP::Cookie.new(name.to_s, val.to_s).cookie_value
177+
end
178+
end.join("; ")
179+
180+
headers(Headers::COOKIE => value)
172181
end
173182

174183
# Force a specific encoding for response body

lib/http/client/request_builder.rb

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def merge_query_params!(uri, opts)
3939
uri.query_values = uri.query_values(Array).to_a.concat(opts.params.to_a)
4040
end
4141

42-
# Creates request headers with cookies (if any) merged in
42+
# Creates request headers
4343
#
4444
# @return [HTTP::Headers] the constructed headers
4545
# @api private
@@ -49,13 +49,6 @@ def make_request_headers(opts)
4949
# Tell the server to keep the conn open
5050
headers[Headers::CONNECTION] = default_options.persistent? ? Connection::KEEP_ALIVE : Connection::CLOSE
5151

52-
cookies = opts.cookies.values
53-
54-
unless cookies.empty?
55-
cookies = opts.headers.get(Headers::COOKIE).concat(cookies).join("; ")
56-
headers[Headers::COOKIE] = cookies
57-
end
58-
5952
headers
6053
end
6154

lib/http/options.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def []=(option, val)
213213
# @return [Hash]
214214
def default_options_hash
215215
{ response: :auto, encoding: nil, nodelay: false, keep_alive_timeout: 5,
216-
proxy: Hash[], ssl: Hash[], headers: Hash[], cookies: Hash[], features: Hash[],
216+
proxy: Hash[], ssl: Hash[], headers: Hash[], features: Hash[],
217217
timeout_class: self.class.default_timeout_class, timeout_options: Hash[],
218218
socket_class: self.class.default_socket_class,
219219
ssl_socket_class: self.class.default_ssl_socket_class }

lib/http/options/definitions.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,6 @@ class Options
77
headers.merge(new_headers) # steep:ignore
88
end
99

10-
def_option :cookies do |new_cookies|
11-
new_cookies.each_with_object cookies.dup do |(k, v), jar| # steep:ignore
12-
cookie = k.is_a?(Cookie) ? k : Cookie.new(k.to_s, v.to_s)
13-
jar[cookie.name] = cookie.cookie_value
14-
end
15-
end
16-
1710
def_option :encoding do |encoding|
1811
self.encoding = Encoding.find(encoding) # steep:ignore
1912
end

lib/http/redirector.rb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# frozen_string_literal: true
22

3+
require "http/cookie_jar"
34
require "http/headers"
45

56
module HTTP
@@ -125,7 +126,6 @@ def redirect_uri
125126
# @api private
126127
# @return [HTTP::CookieJar]
127128
def cookie_jar
128-
# it seems that @response.cookies instance is reused between responses, so we have to "clone"
129129
@cookie_jar ||= CookieJar.new
130130
end
131131

@@ -147,19 +147,13 @@ def collect_cookies_from_request
147147
# @api private
148148
# @return [void]
149149
def collect_cookies_from_response
150-
# Overwrite previous cookies
151150
@response.cookies.each do |cookie|
152151
if cookie.value == ""
153152
cookie_jar.delete(cookie)
154153
else
155154
cookie_jar.add(cookie)
156155
end
157156
end
158-
159-
# I wish we could just do @response.cookes = cookie_jar
160-
cookie_jar.each do |cookie|
161-
@response.cookies.add(cookie)
162-
end
163157
end
164158

165159
# Check if we reached max amount of redirect hops

lib/http/response.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
require "http/mime_type"
99
require "http/response/status"
1010
require "http/response/inflater"
11-
require "http/cookie_jar"
11+
require "http/cookie"
1212
require "time"
1313

1414
module HTTP
@@ -255,14 +255,12 @@ def content_type
255255
# Cookies from Set-Cookie headers
256256
#
257257
# @example
258-
# response.cookies # => #<HTTP::CookieJar ...>
258+
# response.cookies # => [#<HTTP::Cookie ...>, ...]
259259
#
260-
# @return [HTTP::CookieJar]
260+
# @return [Array<HTTP::Cookie>]
261261
# @api public
262262
def cookies
263-
@cookies ||= headers.get(Headers::SET_COOKIE).each_with_object CookieJar.new do |v, jar|
264-
jar.parse(v, uri)
265-
end
263+
@cookies ||= headers.get(Headers::SET_COOKIE).flat_map { |v| HTTP::Cookie.parse(v, uri) }
266264
end
267265

268266
# Check if the response uses chunked transfer encoding

sig/deps.rbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ module HTTP
195195
attr_reader value: String
196196
attr_reader cookie_value: String
197197

198+
def self.parse: (String, untyped) -> Array[HTTP::Cookie]
198199
def self.cookie_value_to_hash: (String) -> Hash[String, String]
199200
def initialize: (String, String, **untyped) -> void
200201
end

sig/http.rbs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -446,14 +446,12 @@ module HTTP
446446
attr_accessor keep_alive_timeout: Integer
447447
attr_accessor timeout_class: Class
448448
attr_accessor timeout_options: Hash[Symbol, untyped]
449-
attr_accessor cookies: Hash[untyped, untyped]
450449
attr_accessor encoding: Encoding?
451450
attr_reader follow: Hash[untyped, untyped]?
452451
attr_reader retriable: Hash[untyped, untyped]?
453452
attr_reader persistent: String?
454453

455454
def with_headers: (untyped value) -> Options
456-
def with_cookies: (untyped value) -> Options
457455
def with_encoding: (untyped value) -> Options
458456
def with_features: (untyped value) -> Options
459457
def with_follow: (untyped value) -> Options
@@ -673,7 +671,7 @@ module HTTP
673671
extend Forwardable
674672

675673
@content_type: ContentType
676-
@cookies: untyped
674+
@cookies: Array[HTTP::Cookie]?
677675

678676
attr_reader status: Response::Status
679677
attr_reader version: String
@@ -698,7 +696,7 @@ module HTTP
698696
def content_type: () -> ContentType
699697
def mime_type: () -> String?
700698
def charset: () -> String?
701-
def cookies: () -> untyped
699+
def cookies: () -> Array[HTTP::Cookie]
702700
def chunked?: () -> bool
703701
def parse: (?untyped? type) -> untyped
704702
def inspect: () -> String

test/http/options/merge_test.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767
nodelay: false,
6868
ssl_socket_class: HTTP::Options.default_ssl_socket_class,
6969
ssl_context: nil,
70-
cookies: {},
7170
encoding: nil,
7271
features: {}
7372
},

0 commit comments

Comments
 (0)