rufus-verbs 0.10 → 1.0.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.
@@ -0,0 +1,3 @@
1
+
2
+ require 'rufus/verbs'
3
+
@@ -1,6 +1,5 @@
1
- #
2
1
  #--
3
- # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2008-2010, John Mettraux, jmettraux@gmail.com
4
3
  #
5
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -20,17 +19,9 @@
20
19
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
20
  # THE SOFTWARE.
22
21
  #
23
- # (MIT license)
22
+ # Made in Japan.
24
23
  #++
25
- #
26
24
 
27
- #
28
- # John Mettraux
29
- #
30
- # Made in Japan
31
- #
32
- # 2008/01/11
33
- #
34
25
 
35
26
  require 'rufus/verbs/endpoint'
36
27
  require 'rufus/verbs/conditional'
@@ -39,94 +30,94 @@ require 'rufus/verbs/conditional'
39
30
  module Rufus::Verbs
40
31
 
41
32
 
42
- #
43
- # GET
44
- #
45
- def get (*args)
46
-
47
- EndPoint.request :get, args
48
- end
33
+ #
34
+ # GET
35
+ #
36
+ def get (*args)
49
37
 
50
- #
51
- # POST
52
- #
53
- def post (*args, &block)
38
+ EndPoint.request :get, args
39
+ end
54
40
 
55
- EndPoint.request :post, args, &block
56
- end
41
+ #
42
+ # POST
43
+ #
44
+ def post (*args, &block)
57
45
 
58
- #
59
- # PUT
60
- #
61
- def put (*args, &block)
46
+ EndPoint.request :post, args, &block
47
+ end
62
48
 
63
- EndPoint.request :put, args, &block
64
- end
49
+ #
50
+ # PUT
51
+ #
52
+ def put (*args, &block)
65
53
 
66
- #
67
- # DELETE
68
- #
69
- def delete (*args)
54
+ EndPoint.request :put, args, &block
55
+ end
70
56
 
71
- EndPoint.request :delete, args
72
- end
57
+ #
58
+ # DELETE
59
+ #
60
+ def delete (*args)
73
61
 
74
- #
75
- # HEAD
76
- #
77
- def head (*args)
62
+ EndPoint.request :delete, args
63
+ end
78
64
 
79
- EndPoint.request :head, args
80
- end
65
+ #
66
+ # HEAD
67
+ #
68
+ def head (*args)
81
69
 
82
- #
83
- # OPTIONS
84
- #
85
- def options (*args)
70
+ EndPoint.request :head, args
71
+ end
86
72
 
87
- EndPoint.request :options, args
88
- end
73
+ #
74
+ # OPTIONS
75
+ #
76
+ def options (*args)
89
77
 
90
- #
91
- # Opens a file or a URI (GETs it and return the reply). Will tolerate
92
- # a HTTP[S] URI or a file path.
93
- #
94
- # It is not named open() in order not to collide with File.open and
95
- # open-uri's open.
96
- #
97
- def fopen (uri, *args, &block)
78
+ EndPoint.request :options, args
79
+ end
98
80
 
99
- # should I really care about blocks here ? ...
81
+ #
82
+ # Opens a file or a URI (GETs it and return the reply). Will tolerate
83
+ # a HTTP[S] URI or a file path.
84
+ #
85
+ # It is not named open() in order not to collide with File.open and
86
+ # open-uri's open.
87
+ #
88
+ def fopen (uri, *args, &block)
100
89
 
101
- u = URI.parse uri.to_s
90
+ # should I really care about blocks here ? ...
102
91
 
103
- return File.open(uri.to_s, &block) \
104
- if u.scheme == nil
92
+ u = URI.parse uri.to_s
105
93
 
106
- return File.open(uri.to_s[5..-1], &block) \
107
- if u.scheme == 'file'
94
+ return File.open(uri.to_s, &block) \
95
+ if u.scheme == nil
108
96
 
109
- if u.scheme == 'http' or u.scheme == 'https'
97
+ return File.open(uri.to_s[5..-1], &block) \
98
+ if u.scheme == 'file'
110
99
 
111
- r = EndPoint.request(:get, [ uri ] + args) \
100
+ if u.scheme == 'http' or u.scheme == 'https'
112
101
 
113
- if block
114
- block.call r
115
- return
116
- end
102
+ r = EndPoint.request(:get, [ uri ] + args) \
117
103
 
118
- class << r
119
- def read
120
- self.body
121
- end
122
- end unless r.respond_to?(:read)
104
+ if block
105
+ block.call r
106
+ return
107
+ end
123
108
 
124
- return r
109
+ class << r
110
+ def read
111
+ self.body
125
112
  end
113
+ end unless r.respond_to?(:read)
126
114
 
127
- raise "can't handle scheme '#{u.scheme}' for #{u.to_s}"
115
+ return r
128
116
  end
129
117
 
130
- extend self
118
+ raise "can't handle scheme '#{u.scheme}' for #{u.to_s}"
119
+ end
120
+
121
+ extend self
131
122
  end
132
123
 
@@ -1,6 +1,5 @@
1
- #
2
1
  #--
3
- # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2008-2010, John Mettraux, jmettraux@gmail.com
4
3
  #
5
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -8,10 +7,10 @@
8
7
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
8
  # copies of the Software, and to permit persons to whom the Software is
10
9
  # furnished to do so, subject to the following conditions:
11
- #
10
+ #
12
11
  # The above copyright notice and this permission notice shall be included in
13
12
  # all copies or substantial portions of the Software.
14
- #
13
+ #
15
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
15
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
16
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -20,120 +19,111 @@
20
19
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
20
  # THE SOFTWARE.
22
21
  #
23
- # (MIT license)
22
+ # Made in Japan.
24
23
  #++
25
- #
26
24
 
27
- #
28
- # John Mettraux
29
- #
30
- # Made in Japan
31
- #
32
- # 2008/01/16
33
- #
34
25
 
35
- #require 'rubygems'
36
26
  require 'rufus/lru'
37
27
 
38
28
 
39
29
  module Rufus::Verbs
40
30
 
31
+ #
32
+ # An EndPoint with a cache for conditional GETs.
33
+ #
34
+ # ep = ConditionalEndPoint.new(
35
+ # :host => "restful.server",
36
+ # :port => 7080,
37
+ # :resource => "inventory/tools")
38
+ #
39
+ # res = ep.get :id => 1
40
+ # # first call will retrieve the representation completely
41
+ #
42
+ # res = ep.get :id => 1
43
+ # # the server (provided that it supports conditional GET) only
44
+ # # returned a 304 answer, the response is returned from the
45
+ # # ConditionalEndPoint cache
46
+ #
47
+ # The :cache_size option allows to set the size of the conditional GET
48
+ # cache. The default size is currently 147.
49
+ #
50
+ class ConditionalEndPoint < EndPoint
51
+
52
+ def initialize (opts)
53
+
54
+ super
55
+
56
+ cs = opts[:cache_size] || 147
57
+
58
+ @cache = LruHash.new cs
59
+ end
60
+
41
61
  #
42
- # An EndPoint with a cache for conditional GETs.
43
- #
44
- # ep = ConditionalEndPoint.new(
45
- # :host => "restful.server",
46
- # :port => 7080,
47
- # :resource => "inventory/tools")
48
- #
49
- # res = ep.get :id => 1
50
- # # first call will retrieve the representation completely
51
- #
52
- # res = ep.get :id => 1
53
- # # the server (provided that it supports conditional GET) only
54
- # # returned a 304 answer, the response is returned from the
55
- # # ConditionalEndPoint cache
56
- #
57
- # The :cache_size option allows to set the size of the conditional GET
58
- # cache. The default size is currently 147.
62
+ # Returns the count of representation 'cached' here for the
63
+ # purpose of conditional GET requests.
59
64
  #
60
- class ConditionalEndPoint < EndPoint
61
-
62
- def initialize (opts)
63
-
64
- super
65
+ def cache_current_size
65
66
 
66
- cs = opts[:cache_size] || 147
67
-
68
- @cache = LruHash.new cs
69
- end
70
-
71
- #
72
- # Returns the count of representation 'cached' here for the
73
- # purpose of conditional GET requests.
74
- #
75
- def cache_current_size
76
-
77
- @cache.size
78
- end
67
+ @cache.size
68
+ end
79
69
 
80
- #
81
- # Returns the max size of the conditional GET cache.
82
- #
83
- def cache_size
70
+ #
71
+ # Returns the max size of the conditional GET cache.
72
+ #
73
+ def cache_size
84
74
 
85
- @cache.maxsize
86
- end
75
+ @cache.maxsize
76
+ end
87
77
 
88
- private
78
+ private
89
79
 
90
- #
91
- # If the representation has already been gotten, send
92
- # potential If-Modified-Since and/or If-None-Match.
93
- #
94
- def add_conditional_headers (req, opts)
80
+ #
81
+ # If the representation has already been gotten, send
82
+ # potential If-Modified-Since and/or If-None-Match.
83
+ #
84
+ def add_conditional_headers (req, opts)
95
85
 
96
- # if path is cached send since and/or match
86
+ # if path is cached send since and/or match
97
87
 
98
- e = @cache[opts[:c_uri]]
88
+ e = @cache[opts[:c_uri]]
99
89
 
100
- return unless e # not cached
90
+ return unless e # not cached
101
91
 
102
- req['If-Modified-Since'] = e.lastmod if e.lastmod
103
- req['If-None-Match'] = e.etag if e.etag
92
+ req['If-Modified-Since'] = e.lastmod if e.lastmod
93
+ req['If-None-Match'] = e.etag if e.etag
104
94
 
105
- opts[:c_cached] = e
106
- end
95
+ opts[:c_cached] = e
96
+ end
107
97
 
108
- def handle_response (method, res, opts)
98
+ def handle_response (method, res, opts)
109
99
 
110
- # if method is get and reply is 200, cache (if et and/or lm)
111
- # if method is get and reply is 304, return from cache
100
+ # if method is get and reply is 200, cache (if et and/or lm)
101
+ # if method is get and reply is 304, return from cache
112
102
 
113
- super
103
+ super
114
104
 
115
- code = res.code.to_i
105
+ code = res.code.to_i
116
106
 
117
- return opts[:c_cached] if code == 304
107
+ return opts[:c_cached] if code == 304
118
108
 
119
- cache(res, opts) if code == 200
109
+ cache(res, opts) if code == 200
120
110
 
121
- res
122
- end
111
+ res
112
+ end
123
113
 
124
- def cache (res, opts)
114
+ def cache (res, opts)
125
115
 
126
- class << res
127
- def lastmod
128
- self['Last-Modified']
129
- end
130
- def etag
131
- self['Etag']
132
- end
133
- end
116
+ class << res
117
+ def lastmod
118
+ self['Last-Modified']
119
+ end
120
+ def etag
121
+ self['Etag']
122
+ end
123
+ end
134
124
 
135
- @cache[opts[:c_uri]] = res
136
- end
125
+ @cache[opts[:c_uri]] = res
137
126
  end
127
+ end
138
128
  end
139
129
 
@@ -1,6 +1,5 @@
1
- #
2
1
  #--
3
- # Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
2
+ # Copyright (c) 2008-2010, John Mettraux, jmettraux@gmail.com
4
3
  #
5
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
5
  # of this software and associated documentation files (the "Software"), to deal
@@ -8,10 +7,10 @@
8
7
  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
8
  # copies of the Software, and to permit persons to whom the Software is
10
9
  # furnished to do so, subject to the following conditions:
11
- #
10
+ #
12
11
  # The above copyright notice and this permission notice shall be included in
13
12
  # all copies or substantial portions of the Software.
14
- #
13
+ #
15
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
15
  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
16
  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -20,308 +19,299 @@
20
19
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
20
  # THE SOFTWARE.
22
21
  #
23
- # (MIT license)
22
+ # Made in Japan.
24
23
  #++
25
- #
26
24
 
27
- #
28
- # John Mettraux
29
- #
30
- # Made in Japan
31
- #
32
- # 2008/01/19
33
- #
34
25
 
35
26
  require 'webrick/cookie'
36
27
 
37
- #require 'rubygems'
38
28
  require 'rufus/lru'
39
29
 
40
30
 
41
31
  module Rufus
42
32
  module Verbs
43
33
 
34
+ #
35
+ # Cookies related methods
36
+ #
37
+ # http://www.ietf.org/rfc/rfc2109.txt
38
+ #
39
+ module CookieMixin
40
+
44
41
  #
45
- # Cookies related methods
46
- #
47
- # http://www.ietf.org/rfc/rfc2109.txt
42
+ # making the cookie jar available
48
43
  #
49
- module CookieMixin
50
-
51
- #
52
- # making the cookie jar available
53
- #
54
- attr_reader :cookies
44
+ attr_reader :cookies
55
45
 
56
- protected
46
+ protected
57
47
 
58
- #
59
- # Prepares the instance variable @cookies for storing
60
- # cooking for this endpoint.
61
- #
62
- # Reads the :cookies endpoint option for determining the
63
- # size of the cookie jar (77 by default).
64
- #
65
- def prepare_cookie_jar
48
+ #
49
+ # Prepares the instance variable @cookies for storing
50
+ # cooking for this endpoint.
51
+ #
52
+ # Reads the :cookies endpoint option for determining the
53
+ # size of the cookie jar (77 by default).
54
+ #
55
+ def prepare_cookie_jar
66
56
 
67
- o = @opts[:cookies]
57
+ o = @opts[:cookies]
68
58
 
69
- return unless o and o != false
59
+ return unless o and o != false
70
60
 
71
- s = o.to_s.to_i
72
- s = 77 if s < 1
61
+ s = o.to_s.to_i
62
+ s = 77 if s < 1
73
63
 
74
- @cookies = CookieJar.new s
75
- end
64
+ @cookies = CookieJar.new s
65
+ end
76
66
 
77
- #
78
- # Parses the HTTP response for a potential 'Set-Cookie' header,
79
- # parses and returns it as a hash.
80
- #
81
- def parse_cookies (response)
67
+ #
68
+ # Parses the HTTP response for a potential 'Set-Cookie' header,
69
+ # parses and returns it as a hash.
70
+ #
71
+ def parse_cookies (response)
82
72
 
83
- c = response['Set-Cookie']
84
- return nil unless c
85
- Cookie.parse_set_cookies c
86
- end
73
+ c = response['Set-Cookie']
74
+ return nil unless c
75
+ Cookie.parse_set_cookies c
76
+ end
87
77
 
88
- #
89
- # (This method will have no effect if the EndPoint is not
90
- # tracking cookies)
91
- #
92
- # Registers a potential cookie set by the server.
93
- #
94
- def register_cookies (response, opts)
78
+ #
79
+ # (This method will have no effect if the EndPoint is not
80
+ # tracking cookies)
81
+ #
82
+ # Registers a potential cookie set by the server.
83
+ #
84
+ def register_cookies (response, opts)
95
85
 
96
- return unless @cookies
86
+ return unless @cookies
97
87
 
98
- cs = parse_cookies response
88
+ cs = parse_cookies response
99
89
 
100
- return unless cs
90
+ return unless cs
101
91
 
102
- # "The origin server effectively ends a session by
103
- # sending the client a Set-Cookie header with Max-Age=0"
92
+ # "The origin server effectively ends a session by
93
+ # sending the client a Set-Cookie header with Max-Age=0"
104
94
 
105
- cs.each do |c|
95
+ cs.each do |c|
106
96
 
107
- host = opts[:host]
108
- path = opts[:path]
109
- cpath = c.path || "/"
97
+ host = opts[:host]
98
+ path = opts[:path]
99
+ cpath = c.path || "/"
110
100
 
111
- next unless cookie_acceptable?(opts, response, c)
101
+ next unless cookie_acceptable?(opts, response, c)
112
102
 
113
- domain = c.domain || host
103
+ domain = c.domain || host
114
104
 
115
- if c.max_age == 0
116
- @cookies.remove_cookie domain, path, c
117
- else
118
- @cookies.add_cookie domain, path, c
119
- end
120
- end
121
- end
105
+ if c.max_age == 0
106
+ @cookies.remove_cookie domain, path, c
107
+ else
108
+ @cookies.add_cookie domain, path, c
109
+ end
110
+ end
111
+ end
122
112
 
123
- #
124
- # Checks if the cookie is acceptable in the context of
125
- # the request that sent it.
126
- #
127
- def cookie_acceptable? (opts, response, cookie)
113
+ #
114
+ # Checks if the cookie is acceptable in the context of
115
+ # the request that sent it.
116
+ #
117
+ def cookie_acceptable? (opts, response, cookie)
128
118
 
129
- # reject if :
130
- #
131
- # * The value for the Path attribute is not a prefix of the
132
- # request-URI.
133
- # * The value for the Domain attribute contains no embedded dots
134
- # or does not start with a dot.
135
- # * The value for the request-host does not domain-match the
136
- # Domain attribute.
137
- # * The request-host is a FQDN (not IP address) and has the form
138
- # HD, where D is the value of the Domain attribute, and H is a
139
- # string that contains one or more dots.
119
+ # reject if :
120
+ #
121
+ # * The value for the Path attribute is not a prefix of the
122
+ # request-URI.
123
+ # * The value for the Domain attribute contains no embedded dots
124
+ # or does not start with a dot.
125
+ # * The value for the request-host does not domain-match the
126
+ # Domain attribute.
127
+ # * The request-host is a FQDN (not IP address) and has the form
128
+ # HD, where D is the value of the Domain attribute, and H is a
129
+ # string that contains one or more dots.
140
130
 
141
- cdomain = cookie.domain
131
+ cdomain = cookie.domain
142
132
 
143
- if cdomain
133
+ if cdomain
144
134
 
145
- return false unless cdomain.index '.'
146
- return false if cdomain[0, 1] != '.'
135
+ return false unless cdomain.index '.'
136
+ return false if cdomain[0, 1] != '.'
147
137
 
148
- h, d = split_host(opts[:host])
149
- return false if d != cdomain
150
- end
138
+ h, d = split_host(opts[:host])
139
+ return false if d != cdomain
140
+ end
151
141
 
152
- #path = opts[:path]
153
- path = response.request.path
142
+ #path = opts[:path]
143
+ path = response.request.path
154
144
 
155
- cpath = cookie.path || "/"
145
+ cpath = cookie.path || "/"
156
146
 
157
- return false if path[0..cpath.length-1] != cpath
147
+ return false if path[0..cpath.length-1] != cpath
158
148
 
159
- true
160
- end
149
+ true
150
+ end
161
151
 
162
- #
163
- # Places the 'Cookie' header in the request if appropriate.
164
- #
165
- # (This method will have no effect if the EndPoint is not
166
- # tracking cookies)
167
- #
168
- def mention_cookies (request, opts)
152
+ #
153
+ # Places the 'Cookie' header in the request if appropriate.
154
+ #
155
+ # (This method will have no effect if the EndPoint is not
156
+ # tracking cookies)
157
+ #
158
+ def mention_cookies (request, opts)
169
159
 
170
- return unless @cookies
160
+ return unless @cookies
171
161
 
172
- cs = @cookies.fetch_cookies opts[:host], opts[:path]
162
+ cs = @cookies.fetch_cookies opts[:host], opts[:path]
173
163
 
174
- request['Cookie'] = cs.collect { |c| c.to_header_s }.join(",")
175
- end
164
+ request['Cookie'] = cs.collect { |c| c.to_header_s }.join(",")
165
+ end
166
+ end
167
+
168
+ #
169
+ # An extension of the cookie implementation found in WEBrick.
170
+ #
171
+ # Unmodified for now.
172
+ #
173
+ class Cookie < WEBrick::Cookie
174
+
175
+ def to_header_s
176
+
177
+ ret = ''
178
+ ret << @name << '=' << @value
179
+ ret << '; ' << '$Version=' << @version.to_s if @version > 0
180
+ ret << '; ' << '$Domain=' << @domain if @domain
181
+ ret << '; ' << '$Port=' << @port if @port
182
+ ret << '; ' << '$Path=' << @path if @path
183
+ ret
176
184
  end
185
+ end
177
186
 
178
- #
179
- # An extension of the cookie implementation found in WEBrick.
180
- #
181
- # Unmodified for now.
182
- #
183
- class Cookie < WEBrick::Cookie
187
+ #
188
+ # Cookies are stored by domain, they via this CookieKey which gathers
189
+ # path and name of the cookie.
190
+ #
191
+ class CookieKey
184
192
 
185
- def to_header_s
193
+ attr_reader :name, :path
186
194
 
187
- ret = ""
188
- ret << @name << "=" << @value
189
- ret << "; " << "$Version=" << @version.to_s if @version > 0
190
- ret << "; " << "$Domain=" << @domain if @domain
191
- ret << "; " << "$Port=" << @port if @port
192
- ret << "; " << "$Path=" << @path if @path
193
- ret
194
- end
195
+ def initialize (path, cookie)
196
+
197
+ @name = cookie.name
198
+ @path = path || cookie.path
195
199
  end
196
200
 
197
201
  #
198
- # Cookies are stored by domain, they via this CookieKey which gathers
199
- # path and name of the cookie.
202
+ # longer paths first
200
203
  #
201
- class CookieKey
202
-
203
- attr_reader :name, :path
204
+ def <=> (other)
204
205
 
205
- def initialize (path, cookie)
206
+ -1 * (@path <=> other.path)
207
+ end
206
208
 
207
- @name = cookie.name
208
- @path = path || cookie.path
209
- end
209
+ def hash
210
+ "#{@name}|#{@path}".hash
211
+ end
210
212
 
211
- #
212
- # longer paths first
213
- #
214
- def <=> (other)
213
+ def == (other)
214
+ (@path == other.path and @name == other.name)
215
+ end
215
216
 
216
- -1 * (@path <=> other.path)
217
- end
217
+ alias eql? ==
218
+ end
218
219
 
219
- def hash
220
- "#{@name}|#{@path}".hash
221
- end
220
+ #
221
+ # A few methods about hostnames.
222
+ #
223
+ # (in a mixin... could be helpful somewhere else later)
224
+ #
225
+ module HostMixin
222
226
 
223
- def == (other)
224
- (@path == other.path and @name == other.name)
225
- end
226
-
227
- alias eql? ==
228
- end
227
+ #
228
+ # Matching a classical IP address (not a v6 though).
229
+ # Should be sufficient for now.
230
+ #
231
+ IP_REGEX = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
229
232
 
230
233
  #
231
- # A few methods about hostnames.
234
+ # Returns a pair host/domain, note that the domain starts with a dot.
232
235
  #
233
- # (in a mixin... could be helpful somewhere else later)
236
+ # split_host('localhost') --> [ 'localhost', nil ]
237
+ # split_host('benz.car.co.nz') --> [ 'benz', '.car.co.nz' ]
238
+ # split_host('127.0.0.1') --> [ '127.0.0.1', nil ]
239
+ # split_host('::1') --> [ '::1', nil ]
234
240
  #
235
- module HostMixin
236
-
237
- #
238
- # Matching a classical IP address (not a v6 though).
239
- # Should be sufficient for now.
240
- #
241
- IP_REGEX = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
242
-
243
- #
244
- # Returns a pair host/domain, note that the domain starts with a dot.
245
- #
246
- # split_host('localhost') --> [ 'localhost', nil ]
247
- # split_host('benz.car.co.nz') --> [ 'benz', '.car.co.nz' ]
248
- # split_host('127.0.0.1') --> [ '127.0.0.1', nil ]
249
- # split_host('::1') --> [ '::1', nil ]
250
- #
251
- def split_host (host)
252
-
253
- return [ host, nil ] if IP_REGEX.match host
254
- i = host.index('.')
255
- return [ host, nil ] unless i
256
- [ host[0..i-1], host[i..-1] ]
257
- end
241
+ def split_host (host)
242
+
243
+ return [ host, nil ] if IP_REGEX.match host
244
+ i = host.index('.')
245
+ return [ host, nil ] unless i
246
+ [ host[0..i-1], host[i..-1] ]
258
247
  end
248
+ end
259
249
 
260
- #
261
- # The container for cookies. Features methods for storing and retrieving
262
- # cookies easily.
263
- #
264
- class CookieJar
265
- include HostMixin
250
+ #
251
+ # The container for cookies. Features methods for storing and retrieving
252
+ # cookies easily.
253
+ #
254
+ class CookieJar
255
+ include HostMixin
266
256
 
267
- def initialize (jar_size)
257
+ def initialize (jar_size)
268
258
 
269
- @per_domain = LruHash.new jar_size
270
- end
259
+ @per_domain = LruHash.new jar_size
260
+ end
271
261
 
272
- #
273
- # Returns the count of cookies currently stored in this jar.
274
- #
275
- def size
262
+ #
263
+ # Returns the count of cookies currently stored in this jar.
264
+ #
265
+ def size
276
266
 
277
- @per_domain.keys.inject(0) { |i, d| i + @per_domain[d].size }
278
- end
267
+ @per_domain.keys.inject(0) { |i, d| i + @per_domain[d].size }
268
+ end
279
269
 
280
- def add_cookie (domain, path, cookie)
270
+ def add_cookie (domain, path, cookie)
281
271
 
282
- (@per_domain[domain] ||= {})[CookieKey.new(path, cookie)] = cookie
283
- end
272
+ (@per_domain[domain] ||= {})[CookieKey.new(path, cookie)] = cookie
273
+ end
284
274
 
285
- def remove_cookie (domain, path, cookie)
275
+ def remove_cookie (domain, path, cookie)
286
276
 
287
- (d = @per_domain[domain])
288
- return unless d
289
- d.delete CookieKey.new(path, cookie)
290
- end
277
+ (d = @per_domain[domain])
278
+ return unless d
279
+ d.delete CookieKey.new(path, cookie)
280
+ end
291
281
 
292
- #
293
- # Retrieves the cookies that matches the combination host/path.
294
- # If the retrieved cookie is expired, will remove it from the jar
295
- # and return nil.
296
- #
297
- def fetch_cookies (host, path)
282
+ #
283
+ # Retrieves the cookies that matches the combination host/path.
284
+ # If the retrieved cookie is expired, will remove it from the jar
285
+ # and return nil.
286
+ #
287
+ def fetch_cookies (host, path)
298
288
 
299
- c = do_fetch(@per_domain[host], path)
289
+ c = do_fetch(@per_domain[host], path)
300
290
 
301
- h, d = split_host host
302
- c += do_fetch(@per_domain[d], path) if d
291
+ h, d = split_host host
292
+ c += do_fetch(@per_domain[d], path) if d
303
293
 
304
- c
305
- end
294
+ c
295
+ end
306
296
 
307
- private
297
+ private
308
298
 
309
- #
310
- # Returns all the cookies that match a domain (host) and a path.
311
- #
312
- def do_fetch (dh, path)
299
+ #
300
+ # Returns all the cookies that match a domain (host) and a path.
301
+ #
302
+ def do_fetch (dh, path)
313
303
 
314
- return [] unless dh
304
+ return [] unless dh
315
305
 
316
- keys = dh.keys.sort.find_all do |k|
317
- path[0..k.path.length-1] == k.path
318
- end
319
- keys.inject([]) do |r, k|
320
- r << dh[k]
321
- r
322
- end
323
- end
306
+ keys = dh.keys.sort.find_all do |k|
307
+ path[0..k.path.length-1] == k.path
308
+ end
309
+ keys.inject([]) do |r, k|
310
+ r << dh[k]
311
+ r
312
+ end
324
313
  end
314
+ end
325
315
  end
326
316
  end
327
317