rack-test 1.1.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +120 -1
- data/MIT-LICENSE.txt +1 -0
- data/README.md +53 -64
- data/lib/rack/test/cookie_jar.rb +108 -50
- data/lib/rack/test/methods.rb +57 -46
- data/lib/rack/test/uploaded_file.rb +44 -16
- data/lib/rack/test/utils.rb +73 -61
- data/lib/rack/test/version.rb +1 -1
- data/lib/rack/test.rb +230 -182
- metadata +30 -101
- data/lib/rack/mock_session.rb +0 -63
- data/lib/rack/test/mock_digest_request.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98bb9656717c512790c5f65b20a8f0cfc7c2f14e4d9d98d5069e6e5910b256e5
|
4
|
+
data.tar.gz: 6305cac1636eef820a082a1431cef2bc24b445b1f902b65c550f976ba84f08e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 420e60a08ec2fa5fd92a358d28c0b17e0a943eb30962756360185091753bdd4eb55b7b58005aa84bb1907cfb7e8129166d1aed6282596f45b8b0f42dd1003306
|
7
|
+
data.tar.gz: b7446d71bf41a0f69b9812e867f7b472488ee0534d6206435b77e8266617486687044a814dd6c085003b823e0e349c83b1ca47ea296f1f23346957d66cbed0bc
|
data/History.md
CHANGED
@@ -1,3 +1,122 @@
|
|
1
|
+
## 2.1.0 / 2023-03-14
|
2
|
+
|
3
|
+
* Breaking changes:
|
4
|
+
* Digest authentication support, deprecated in 2.0.0, has been
|
5
|
+
removed (Jeremy Evans #307)
|
6
|
+
* requiring rack/mock_session, deprecated in 2.0.0, has been removed
|
7
|
+
(Jeremy Evans #307)
|
8
|
+
|
9
|
+
* Minor enhancements:
|
10
|
+
* The `original_filename` for `Rack::Test::UploadedFile` can now be
|
11
|
+
set even if the content of the file comes from a file path
|
12
|
+
(Stuart Chinery #314)
|
13
|
+
* Add `Rack::Test::Session#restore_state`, for executing a block
|
14
|
+
and restoring current state (last request, last response, and
|
15
|
+
cookies) after the block (Jeremy Evans #316)
|
16
|
+
* Make `Rack::Test::Methods` support `default_host` method similar to
|
17
|
+
`app`, which will set the default host used for requests to the app
|
18
|
+
(Jeremy Evans #317 #318)
|
19
|
+
* Allow responses to set cookie paths not matching the current
|
20
|
+
request URI. Such cookies will only be sent for paths matching
|
21
|
+
the cookie path (Chris Waters #322)
|
22
|
+
* Ignore leading dot for cookie domains, per RFC 6265 (Stephen Crosby
|
23
|
+
#329)
|
24
|
+
* Avoid creating empty multipart body if params is empty in
|
25
|
+
`Rack::Test::Session#env_for` (Ryunosuke Sato #331)
|
26
|
+
|
27
|
+
## 2.0.2 / 2022-06-28
|
28
|
+
|
29
|
+
* Bug fixes:
|
30
|
+
* Fix additional incompatible character encodings error when building
|
31
|
+
uploaded bodies (Jeremy Evans #311)
|
32
|
+
|
33
|
+
## 2.0.1 / 2022-06-27
|
34
|
+
|
35
|
+
* Bug fixes:
|
36
|
+
* Fix incompatible character encodings error when building uploaded
|
37
|
+
file bodies (Jeremy Evans #308 #309)
|
38
|
+
|
39
|
+
## 2.0.0 / 2022-06-24
|
40
|
+
|
41
|
+
* Breaking changes:
|
42
|
+
* Digest authentication support is now deprecated, as it relies on
|
43
|
+
digest authentication support in rack, which has been deprecated
|
44
|
+
(Jeremy Evans #294)
|
45
|
+
* `Rack::Test::Utils.build_primitive_part` no longer handles array
|
46
|
+
values (Jeremy Evans #292)
|
47
|
+
* `Rack::Test::Utils` module methods other than `build_nested_query`
|
48
|
+
and `build_multipart` are now private methods (Jeremy Evans #297)
|
49
|
+
* `Rack::MockSession` has been combined into `Rack::Test::Session`,
|
50
|
+
and remains as an alias to `Rack::Test::Session`, but to keep some
|
51
|
+
backwards compatibility, `Rack::Test::Session.new` will accept a
|
52
|
+
`Rack::Test::Session` instance and return it (Jeremy Evans #297)
|
53
|
+
* Previously protected methods in `Rack::Test::Cookie{,Jar}` are now
|
54
|
+
private methods (Jeremy Evans #297)
|
55
|
+
* `Rack::Test::Methods` no longer defines `build_rack_mock_session`,
|
56
|
+
but for backwards compatibility, `build_rack_test_session` will call
|
57
|
+
`build_rack_mock_session` if it is defined (Jeremy Evans #297)
|
58
|
+
* `Rack::Test::Methods::METHODS` is no longer defined
|
59
|
+
(Jeremy Evans #297)
|
60
|
+
* `Rack::Test::Methods#_current_session_names` has been removed
|
61
|
+
(Jeremy Evans #297)
|
62
|
+
* Headers used/accessed by rack-test are now lower case, for rack 3
|
63
|
+
compliance (Jeremy Evans #295)
|
64
|
+
* Frozen literal strings are now used internally, which may break
|
65
|
+
code that mutates static strings returned by rack-test, if any
|
66
|
+
(Jeremy Evans #304)
|
67
|
+
|
68
|
+
* Minor enhancements:
|
69
|
+
* rack-test now works with the rack main branch (what will be rack 3)
|
70
|
+
(Jeremy Evans #280 #292)
|
71
|
+
* rack-test only loads the parts of rack it uses when running on the
|
72
|
+
rack main branch (what will be rack 3) (Jeremy Evans #292)
|
73
|
+
* Development dependencies have been significantly reduced, and are
|
74
|
+
now a subset of the development dependencies of rack itself
|
75
|
+
(Jeremy Evans #292)
|
76
|
+
* Avoid creating multiple large copies of uploaded file data in
|
77
|
+
memory (Jeremy Evans #286)
|
78
|
+
* Specify HTTP/1.0 when submitting requests, to avoid responses with
|
79
|
+
Transfer-Encoding: chunked (Jeremy Evans #288)
|
80
|
+
* Support `:query_params` in rack environment for parameters that
|
81
|
+
are appended to the query string instead of used in the request
|
82
|
+
body (Jeremy Evans #150 #287)
|
83
|
+
* Reduce required ruby version to 2.0, since tests run fine on
|
84
|
+
Ruby 2.0 (Jeremy Evans #292)
|
85
|
+
* Support :multipart env key for request methods to force multipart
|
86
|
+
input (Jeremy Evans #303)
|
87
|
+
* Force multipart input for request methods if content type starts
|
88
|
+
with multipart (Jeremy Evans #303)
|
89
|
+
* Improve performance of Utils.build_multipart by using an
|
90
|
+
append-only design (Jeremy Evans #304)
|
91
|
+
* Improve performance of Utils.build_nested_query for array values
|
92
|
+
(Jeremy Evans #304)
|
93
|
+
|
94
|
+
* Bug fixes:
|
95
|
+
* The `CONTENT_TYPE` of multipart requests is now respected, if it
|
96
|
+
starts with `multipart/` (Tom Knig #238)
|
97
|
+
* Work correctly with responses that respond to `to_a` but not
|
98
|
+
`to_ary` (Sergio Faria #276)
|
99
|
+
* Raise an ArgumentError instead of a TypeError when providing a
|
100
|
+
StringIO without an original filename when creating an
|
101
|
+
UploadedFile (Nuno Correia #279)
|
102
|
+
* Allow combining both an UploadedFile and a plain string when
|
103
|
+
building a multipart upload (Mitsuhiro Shibuya #278)
|
104
|
+
* Fix the generation of filenames with spaces to use path
|
105
|
+
escaping instead of regular escaping, since path unescaping is
|
106
|
+
used to decode it (Muir Manders, Jeremy Evans #275 #284)
|
107
|
+
* Rewind tempfile used for multipart uploads before it is
|
108
|
+
submitted to the application
|
109
|
+
(Jeremy Evans, Alexander Dervish #261 #268 #286)
|
110
|
+
* Fix Rack::Test.encoding_aware_strings to be true only on rack
|
111
|
+
1.6+ (Jeremy Evans #292)
|
112
|
+
* Make Rack::Test::CookieJar#valid? return true/false
|
113
|
+
(Jeremy Evans #292)
|
114
|
+
* Cookies without a domain attribute no longer are submitted to
|
115
|
+
requests for subdomains of that domain, for RFC 6265
|
116
|
+
compliance (Jeremy Evans #292)
|
117
|
+
* Increase required rack version to 1.3, since tests fail on
|
118
|
+
rack 1.2 and below (Jeremy Evans #293)
|
119
|
+
|
1
120
|
## 1.1.0 / 2018-07-21
|
2
121
|
|
3
122
|
* Breaking changes:
|
@@ -8,7 +127,7 @@
|
|
8
127
|
* follow_direct: Include rack.session.options (Mark Edmondson #233)
|
9
128
|
* [CI] Add simplecov (fatkodima #227)
|
10
129
|
|
11
|
-
Bug fixes:
|
130
|
+
* Bug fixes:
|
12
131
|
* Follow relative locations correctly. (Samuel Williams #230)
|
13
132
|
|
14
133
|
## 1.0.0 / 2018-03-27
|
data/MIT-LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
# Rack::Test
|
2
2
|
[](https://badge.fury.io/rb/rack-test)
|
3
|
-
[<img src="https://travis-ci.org/rack-test/rack-test.svg?branch=master" />](https://travis-ci.org/rack-test/rack-test)
|
4
|
-
[](https://codeclimate.com/github/rack-test/rack-test)
|
5
|
-
[](https://codeclimate.com/github/rack-test/rack-test/coverage)
|
6
3
|
|
7
|
-
Code: https://github.com/rack
|
4
|
+
Code: https://github.com/rack/rack-test
|
8
5
|
|
9
6
|
## Description
|
10
7
|
|
@@ -14,76 +11,66 @@ to build on.
|
|
14
11
|
|
15
12
|
## Features
|
16
13
|
|
14
|
+
* Allows for submitting requests and testing responses
|
17
15
|
* Maintains a cookie jar across requests
|
18
|
-
*
|
19
|
-
*
|
20
|
-
* Small footprint. Approximately 200 LOC
|
21
|
-
|
22
|
-
## Supported platforms
|
23
|
-
|
24
|
-
* 2.2.2+
|
25
|
-
* 2.3
|
26
|
-
* 2.4
|
27
|
-
* JRuby 9.1.+
|
28
|
-
|
29
|
-
If you are using Ruby 1.8, 1.9 or JRuby 1.7, use rack-test 0.6.3.
|
30
|
-
|
31
|
-
## Known incompatibilites
|
32
|
-
|
33
|
-
* `rack-test >= 0.71` _does not_ work with older Capybara versions (`< 2.17`). See [#214](https://github.com/rack-test/rack-test/issues/214) for more details.
|
16
|
+
* Supports request headers used for subsequent requests
|
17
|
+
* Follow redirects when requested
|
34
18
|
|
35
19
|
## Examples
|
36
|
-
|
20
|
+
|
21
|
+
These examples use `test/unit` but it's equally possible to use `rack-test` with
|
22
|
+
other testing frameworks such as `minitest` or `rspec`.
|
37
23
|
|
38
24
|
```ruby
|
39
25
|
require "test/unit"
|
40
26
|
require "rack/test"
|
27
|
+
require "json"
|
41
28
|
|
42
29
|
class HomepageTest < Test::Unit::TestCase
|
43
30
|
include Rack::Test::Methods
|
44
31
|
|
45
32
|
def app
|
46
|
-
|
47
|
-
builder = Rack::Builder.new
|
48
|
-
builder.run app
|
33
|
+
lambda { |env| [200, {'content-type' => 'text/plain'}, ['All responses are OK']] }
|
49
34
|
end
|
50
35
|
|
51
36
|
def test_response_is_ok
|
52
|
-
|
53
|
-
|
54
|
-
assert last_response.ok?
|
55
|
-
assert_equal last_response.body, 'All responses are OK'
|
56
|
-
end
|
37
|
+
# Optionally set headers used for all requests in this spec:
|
38
|
+
#header 'accept-charset', 'utf-8'
|
57
39
|
|
58
|
-
|
59
|
-
header 'Accept-Charset', 'utf-8'
|
40
|
+
# First argument is treated as the path
|
60
41
|
get '/'
|
61
42
|
|
62
43
|
assert last_response.ok?
|
63
|
-
assert_equal
|
44
|
+
assert_equal 'All responses are OK', last_response.body
|
64
45
|
end
|
65
46
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
47
|
+
def delete_with_url_params_and_body
|
48
|
+
# First argument can have a query string
|
49
|
+
#
|
50
|
+
# Second argument is used as the parameters for the request, which will be
|
51
|
+
# included in the request body for non-GET requests.
|
52
|
+
delete '/?foo=bar', JSON.generate('baz' => 'zot')
|
71
53
|
end
|
72
54
|
|
73
55
|
def post_with_json
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
56
|
+
# Third argument is the rack environment to use for the request. The following
|
57
|
+
# entries in the submitted rack environment are treated specially (in addition
|
58
|
+
# to options supported by `Rack::MockRequest#env_for`:
|
59
|
+
#
|
60
|
+
# :cookie : Set a cookie for the current session before submitting the request.
|
61
|
+
#
|
62
|
+
# :query_params : Set parameters for the query string (as opposed to the body).
|
63
|
+
# Value should be a hash of parameters.
|
64
|
+
#
|
65
|
+
# :xhr : Set HTTP_X_REQUESTED_WITH env key to XMLHttpRequest.
|
66
|
+
post(uri, JSON.generate('baz' => 'zot'), 'CONTENT_TYPE' => 'application/json')
|
82
67
|
end
|
83
68
|
end
|
84
69
|
```
|
85
70
|
|
86
|
-
|
71
|
+
`rack-test` will test the app returned by the `app` method. If you are loading middleware
|
72
|
+
in a `config.ru` file, and want to test that, you should load the Rack app created from
|
73
|
+
the `config.ru` file:
|
87
74
|
|
88
75
|
```ruby
|
89
76
|
OUTER_APP = Rack::Builder.parse_file("config.ru").first
|
@@ -102,7 +89,6 @@ class TestApp < Test::Unit::TestCase
|
|
102
89
|
end
|
103
90
|
```
|
104
91
|
|
105
|
-
|
106
92
|
## Install
|
107
93
|
|
108
94
|
To install the latest release as a gem:
|
@@ -111,40 +97,43 @@ To install the latest release as a gem:
|
|
111
97
|
gem install rack-test
|
112
98
|
```
|
113
99
|
|
114
|
-
Or
|
100
|
+
Or add to your `Gemfile`:
|
115
101
|
|
116
102
|
```
|
117
103
|
gem 'rack-test'
|
118
104
|
```
|
119
105
|
|
120
|
-
|
106
|
+
## Contribution
|
121
107
|
|
122
|
-
|
123
|
-
|
124
|
-
|
108
|
+
Contributions are welcome. Please make sure to:
|
109
|
+
|
110
|
+
* Use a regular forking workflow
|
111
|
+
* Write tests for the new or changed behaviour
|
112
|
+
* Provide an explanation/motivation in your commit message / PR message
|
113
|
+
* Ensure `History.md` is updated
|
125
114
|
|
126
115
|
## Authors
|
127
116
|
|
128
|
-
- Contributions from Bryan Helmkamp, Simon Rozet,
|
117
|
+
- Contributions from Bryan Helmkamp, Jeremy Evans, Simon Rozet, and others
|
129
118
|
- Much of the original code was extracted from Merb 1.0's request helper
|
130
119
|
|
131
120
|
## License
|
132
|
-
`rack-test` is released under the [MIT License](MIT-LICENSE.txt).
|
133
121
|
|
134
|
-
|
122
|
+
`rack-test` is released under the [MIT License](MIT-LICENSE.txt).
|
135
123
|
|
136
|
-
|
124
|
+
## Supported platforms
|
137
125
|
|
138
|
-
*
|
139
|
-
*
|
140
|
-
* Provide an explanation/motivation in your commit message / PR message
|
141
|
-
* Ensure History.txt is updated
|
126
|
+
* Ruby 2.0+
|
127
|
+
* JRuby 9.1+
|
142
128
|
|
143
129
|
## Releasing
|
144
130
|
|
145
|
-
* Ensure `History.md` is up-to-date
|
146
131
|
* Bump VERSION in lib/rack/test/version.rb
|
147
|
-
* `
|
132
|
+
* Ensure `History.md` is up-to-date, including correct version and date
|
133
|
+
* `git commit . -m 'Release $VERSION'`
|
148
134
|
* `git push`
|
149
|
-
*
|
150
|
-
*
|
135
|
+
* `git tag -a -m 'Tag the $VERSION release' $VERSION`
|
136
|
+
* `git push --tags`
|
137
|
+
* `gem build rack-test.gemspec`
|
138
|
+
* `gem push rack-test-$VERSION.gem`
|
139
|
+
* Add a discussion post for the release
|
data/lib/rack/test/cookie_jar.rb
CHANGED
@@ -1,94 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
require 'time'
|
3
5
|
|
4
6
|
module Rack
|
5
7
|
module Test
|
8
|
+
# Represents individual cookies in the cookie jar. This is considered private
|
9
|
+
# API and behavior of this class can change at any time.
|
6
10
|
class Cookie # :nodoc:
|
7
11
|
include Rack::Utils
|
8
12
|
|
9
|
-
#
|
10
|
-
attr_reader :name
|
13
|
+
# The name of the cookie, will be a string
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
# The value of the cookie, will be a string or nil if there is no value.
|
17
|
+
attr_reader :value
|
18
|
+
|
19
|
+
# The raw string for the cookie, without options. Will generally be in
|
20
|
+
# name=value format is name and value are provided.
|
21
|
+
attr_reader :raw
|
11
22
|
|
12
|
-
# :api: private
|
13
23
|
def initialize(raw, uri = nil, default_host = DEFAULT_HOST)
|
14
24
|
@default_host = default_host
|
15
25
|
uri ||= default_uri
|
16
26
|
|
17
27
|
# separate the name / value pair from the cookie options
|
18
|
-
@
|
28
|
+
@raw, options = raw.split(/[;,] */n, 2)
|
19
29
|
|
20
|
-
@name, @value = parse_query(@
|
30
|
+
@name, @value = parse_query(@raw, ';').to_a.first
|
21
31
|
@options = parse_query(options, ';')
|
22
32
|
|
23
|
-
@options['domain']
|
24
|
-
|
33
|
+
if domain = @options['domain']
|
34
|
+
@exact_domain_match = false
|
35
|
+
domain[0] = '' if domain[0] == '.'
|
36
|
+
else
|
37
|
+
# If the domain attribute is not present in the cookie,
|
38
|
+
# the domain must match exactly.
|
39
|
+
@exact_domain_match = true
|
40
|
+
@options['domain'] = (uri.host || default_host)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set the path for the cookie to the directory containing
|
44
|
+
# the request if it isn't set.
|
45
|
+
@options['path'] ||= uri.path.sub(/\/[^\/]*\Z/, '')
|
25
46
|
end
|
26
47
|
|
48
|
+
# Wether the given cookie can replace the current cookie in the cookie jar.
|
27
49
|
def replaces?(other)
|
28
50
|
[name.downcase, domain, path] == [other.name.downcase, other.domain, other.path]
|
29
51
|
end
|
30
52
|
|
31
|
-
#
|
32
|
-
def raw
|
33
|
-
@name_value_raw
|
34
|
-
end
|
35
|
-
|
36
|
-
# :api: private
|
53
|
+
# Whether the cookie has a value.
|
37
54
|
def empty?
|
38
55
|
@value.nil? || @value.empty?
|
39
56
|
end
|
40
57
|
|
41
|
-
#
|
58
|
+
# The explicit or implicit domain for the cookie.
|
42
59
|
def domain
|
43
60
|
@options['domain']
|
44
61
|
end
|
45
62
|
|
63
|
+
# Whether the cookie has the secure flag, indicating it can only be sent over
|
64
|
+
# an encrypted connection.
|
46
65
|
def secure?
|
47
66
|
@options.key?('secure')
|
48
67
|
end
|
49
68
|
|
69
|
+
# Whether the cookie has the httponly flag, indicating it is not available via
|
70
|
+
# a javascript API.
|
50
71
|
def http_only?
|
51
|
-
@options.key?('HttpOnly')
|
72
|
+
@options.key?('HttpOnly') || @options.key?('httponly')
|
52
73
|
end
|
53
74
|
|
54
|
-
#
|
75
|
+
# The explicit or implicit path for the cookie.
|
55
76
|
def path
|
56
77
|
([*@options['path']].first.split(',').first || '/').strip
|
57
78
|
end
|
58
79
|
|
59
|
-
#
|
80
|
+
# A Time value for when the cookie expires, if the expires option is set.
|
60
81
|
def expires
|
61
82
|
Time.parse(@options['expires']) if @options['expires']
|
62
83
|
end
|
63
84
|
|
64
|
-
#
|
85
|
+
# Whether the cookie is currently expired.
|
65
86
|
def expired?
|
66
87
|
expires && expires < Time.now
|
67
88
|
end
|
68
89
|
|
69
|
-
#
|
90
|
+
# Whether the cookie is valid for the given URI.
|
70
91
|
def valid?(uri)
|
71
92
|
uri ||= default_uri
|
72
93
|
|
73
94
|
uri.host = @default_host if uri.host.nil?
|
74
95
|
|
75
96
|
real_domain = domain =~ /^\./ ? domain[1..-1] : domain
|
76
|
-
(!secure? || (secure? && uri.scheme == 'https')) &&
|
77
|
-
uri.host =~ Regexp.new("#{Regexp.escape(real_domain)}$", Regexp::IGNORECASE)
|
78
|
-
uri.path =~ Regexp.new("^#{Regexp.escape(path)}")
|
97
|
+
!!((!secure? || (secure? && uri.scheme == 'https')) &&
|
98
|
+
uri.host =~ Regexp.new("#{'^' if @exact_domain_match}#{Regexp.escape(real_domain)}$", Regexp::IGNORECASE))
|
79
99
|
end
|
80
100
|
|
81
|
-
#
|
101
|
+
# Cookies that do not match the URI will not be sent in requests to the URI.
|
82
102
|
def matches?(uri)
|
83
|
-
!expired? && valid?(uri)
|
103
|
+
!expired? && valid?(uri) && uri.path.start_with?(path)
|
84
104
|
end
|
85
105
|
|
86
|
-
#
|
106
|
+
# Order cookies by name, path, and domain.
|
87
107
|
def <=>(other)
|
88
|
-
# Orders the cookies from least specific to most
|
89
108
|
[name, path, domain.reverse] <=> [other.name, other.path, other.domain.reverse]
|
90
109
|
end
|
91
110
|
|
111
|
+
# A hash of cookie options, including the cookie value, but excluding the cookie name.
|
92
112
|
def to_h
|
93
113
|
@options.merge(
|
94
114
|
'value' => @value,
|
@@ -98,43 +118,68 @@ module Rack
|
|
98
118
|
end
|
99
119
|
alias to_hash to_h
|
100
120
|
|
101
|
-
|
121
|
+
private
|
102
122
|
|
123
|
+
# The default URI to use for the cookie, including just the host.
|
103
124
|
def default_uri
|
104
125
|
URI.parse('//' + @default_host + '/')
|
105
126
|
end
|
106
127
|
end
|
107
128
|
|
129
|
+
# Represents all cookies for a session, handling adding and
|
130
|
+
# removing cookies, and finding which cookies apply to a given
|
131
|
+
# request. This is considered private API and behavior of this
|
132
|
+
# class can change at any time.
|
108
133
|
class CookieJar # :nodoc:
|
109
134
|
DELIMITER = '; '.freeze
|
110
135
|
|
111
|
-
# :api: private
|
112
136
|
def initialize(cookies = [], default_host = DEFAULT_HOST)
|
113
137
|
@default_host = default_host
|
114
|
-
@cookies = cookies
|
115
|
-
@cookies.sort!
|
138
|
+
@cookies = cookies.sort!
|
116
139
|
end
|
117
140
|
|
141
|
+
# Ensure the copy uses a distinct cookies array.
|
142
|
+
def initialize_copy(other)
|
143
|
+
super
|
144
|
+
@cookies = @cookies.dup
|
145
|
+
end
|
146
|
+
|
147
|
+
# Return the value for first cookie with the given name, or nil
|
148
|
+
# if no such cookie exists.
|
118
149
|
def [](name)
|
119
|
-
|
120
|
-
|
121
|
-
|
150
|
+
name = name.to_s
|
151
|
+
@cookies.each do |cookie|
|
152
|
+
return cookie.value if cookie.name == name
|
153
|
+
end
|
154
|
+
nil
|
122
155
|
end
|
123
156
|
|
157
|
+
# Set a cookie with the given name and value in the
|
158
|
+
# cookie jar.
|
124
159
|
def []=(name, value)
|
125
160
|
merge("#{name}=#{Rack::Utils.escape(value)}")
|
126
161
|
end
|
127
162
|
|
163
|
+
# Return the first cookie with the given name, or nil if
|
164
|
+
# no such cookie exists.
|
128
165
|
def get_cookie(name)
|
129
|
-
|
166
|
+
@cookies.each do |cookie|
|
167
|
+
return cookie if cookie.name == name
|
168
|
+
end
|
169
|
+
nil
|
130
170
|
end
|
131
171
|
|
172
|
+
# Delete all cookies with the given name from the cookie jar.
|
132
173
|
def delete(name)
|
133
174
|
@cookies.reject! do |cookie|
|
134
175
|
cookie.name == name
|
135
176
|
end
|
177
|
+
nil
|
136
178
|
end
|
137
179
|
|
180
|
+
# Add a string of raw cookie information to the cookie jar,
|
181
|
+
# if the cookie is valid for the given URI.
|
182
|
+
# Cookies should be separated with a newline.
|
138
183
|
def merge(raw_cookies, uri = nil)
|
139
184
|
return unless raw_cookies
|
140
185
|
|
@@ -149,6 +194,7 @@ module Rack
|
|
149
194
|
end
|
150
195
|
end
|
151
196
|
|
197
|
+
# Add a Cookie to the cookie jar.
|
152
198
|
def <<(new_cookie)
|
153
199
|
@cookies.reject! do |existing_cookie|
|
154
200
|
new_cookie.replaces?(existing_cookie)
|
@@ -158,36 +204,48 @@ module Rack
|
|
158
204
|
@cookies.sort!
|
159
205
|
end
|
160
206
|
|
161
|
-
#
|
207
|
+
# Return a raw cookie string for the cookie header to
|
208
|
+
# use for the given URI.
|
162
209
|
def for(uri)
|
163
|
-
|
210
|
+
buf = String.new
|
211
|
+
delimiter = nil
|
212
|
+
|
213
|
+
each_cookie_for(uri) do |cookie|
|
214
|
+
if delimiter
|
215
|
+
buf << delimiter
|
216
|
+
else
|
217
|
+
delimiter = DELIMITER
|
218
|
+
end
|
219
|
+
buf << cookie.raw
|
220
|
+
end
|
221
|
+
|
222
|
+
buf
|
164
223
|
end
|
165
224
|
|
225
|
+
# Return a hash cookie names and cookie values for cookies in the jar.
|
166
226
|
def to_hash
|
167
227
|
cookies = {}
|
168
228
|
|
169
|
-
|
170
|
-
cookies[name] = cookie.value
|
229
|
+
@cookies.each do |cookie|
|
230
|
+
cookies[cookie.name] = cookie.value
|
171
231
|
end
|
172
232
|
|
173
233
|
cookies
|
174
234
|
end
|
175
235
|
|
176
|
-
|
177
|
-
|
178
|
-
def hash_for(uri = nil)
|
179
|
-
cookies = {}
|
236
|
+
private
|
180
237
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
238
|
+
# Yield each cookie that matches for the URI.
|
239
|
+
#
|
240
|
+
# The cookies are sorted by most specific first. So, we loop through
|
241
|
+
# all the cookies in order and add it to a hash by cookie name if
|
242
|
+
# the cookie can be sent to the current URI. It's added to the hash
|
243
|
+
# so that when we are done, the cookies will be unique by name and
|
244
|
+
# we'll have grabbed the most specific to the URI.
|
245
|
+
def each_cookie_for(uri)
|
186
246
|
@cookies.each do |cookie|
|
187
|
-
|
247
|
+
yield cookie if !uri || cookie.matches?(uri)
|
188
248
|
end
|
189
|
-
|
190
|
-
cookies
|
191
249
|
end
|
192
250
|
end
|
193
251
|
end
|