socialcast-rapuncel 0.0.7.RC1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://www.rubygems.org'
2
+ gemspec
3
+ gem 'rake', :require => false
4
+
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rapuncel (0.0.6.RC3)
5
+ activesupport (>= 3.0.0)
6
+ nokogiri
7
+
8
+ GEM
9
+ remote: http://www.rubygems.org/
10
+ specs:
11
+ activesupport (3.1.3)
12
+ multi_json (~> 1.0)
13
+ diff-lcs (1.1.2)
14
+ multi_json (1.0.4)
15
+ nokogiri (1.5.0)
16
+ rake (0.9.2)
17
+ rspec (2.6.0)
18
+ rspec-core (~> 2.6.0)
19
+ rspec-expectations (~> 2.6.0)
20
+ rspec-mocks (~> 2.6.0)
21
+ rspec-core (2.6.4)
22
+ rspec-expectations (2.6.0)
23
+ diff-lcs (~> 1.1.2)
24
+ rspec-mocks (2.6.0)
25
+
26
+ PLATFORMS
27
+ ruby
28
+
29
+ DEPENDENCIES
30
+ rake
31
+ rapuncel!
32
+ rspec (>= 2.6.0)
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Kayoom GmbH
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,209 @@
1
+ # Rapuncel - Simple XML-RPC Client
2
+ [![Build Status](https://secure.travis-ci.org/cice/rapuncel.png)](http://travis-ci.org/cice/rapuncel)
3
+
4
+ Rapuncel ([wikipedia](http://en.wikipedia.org/wiki/Rapunzel)) is a simple and lightweight, but fast XML-RPC client library for ruby.
5
+ It's based on Nokogiri for XML parsing and thus provides a major performance improvement for large XML responses.
6
+
7
+ ## I need your help
8
+ I currently have exactly 1 application for Rapuncel, and that's [Kangaroo](https://github.com/kayoom/kangaroo), i.e.
9
+ the OpenERP XMLRPC service, where it works absolutely fine. To improve Rapuncel i need your experience with
10
+ other services and their quirks. Just open a feature request, file a bug report, send me a message.
11
+
12
+ ## Installation
13
+
14
+ ### Rails
15
+ Add this to your Gemfile:
16
+
17
+ gem 'rapuncel'
18
+
19
+ Run
20
+
21
+ bundle install
22
+
23
+ and you're good to go.
24
+
25
+ ### Other Ruby / IRB
26
+ Install it as gem:
27
+
28
+ gem install rapuncel
29
+
30
+ Require **rubygems** and **rapuncel**
31
+
32
+ require 'rubygems'
33
+ require 'rapuncel'
34
+
35
+ ## Usage
36
+
37
+ ### Initialize client
38
+ Usage is pretty straightforward, Rapuncel provides a method proxy to send calls to your XMLRPC service like you would to a normal ruby
39
+ object.
40
+ First you have to create a client with the connection details, e.g.
41
+
42
+ client = Rapuncel::Client.new :host => 'localhost', :port => 8080, :path => '/xmlrpc'
43
+
44
+ Available options are:
45
+
46
+ * **host**
47
+ hostname or ip-address,
48
+ _default_: `localhost`
49
+ * **port**
50
+ port where your XMLRPC service is listening,
51
+ _default_: `8080`
52
+ * **path**
53
+ path to the service,
54
+ _default_: `/`
55
+ * **user**
56
+ Username for HTTP Authentication
57
+ _default_: _empty_
58
+ * **password**
59
+ Password for HTTP Authentication
60
+ _default_: _empty_
61
+ * **headers**
62
+ Hash to set additional HTTP headers for the request, e.g. to send an X-ApiKey header for authentication
63
+ _default_: `{}`
64
+ * **ssl**
65
+ Flag wether to use SSL
66
+ _default_: `false`
67
+ * **raise_on**
68
+ Lets you define the behavior on errors or faults, if set to `:fault`, `:error` or `:both`,
69
+ an Exception will be raised if something goes wrong
70
+ * **serialization**
71
+ Use your own (extended) (De)Serializers. See Custom Serialization
72
+ _default_: `Rapuncel::XmlRpc`
73
+
74
+ ### Get a proxy object and ...
75
+ A proxy object receives ruby method calls, redirects them to your XMLRPC service and returns the response as ruby objects!
76
+
77
+ proxy = client.proxy
78
+
79
+ # suppose your XMLRPC service has a method exposed 'concat_string(string1, string2)'
80
+ proxy.concat_string "foo", "bar"
81
+ -> "foobar"
82
+
83
+ # if you need to access specific interfaces on your service, e.g. 'string.concat(string1, string2)'
84
+ proxy = client.proxy_for 'string'
85
+ proxy.concat 'foo', 'bar'
86
+ -> 'foobar'
87
+
88
+ ## Supported objects
89
+ Rapuncel supports natively following object-types (and all their subclasses):
90
+
91
+ * Integer
92
+ * String
93
+ * Array
94
+ * Hash
95
+ * TrueClass, FalseClass
96
+ * Float / Double
97
+ * BigDecimal (treated like Float, unless you set `double_as_bigdecimal` to true)
98
+ * Time, Time-like objects
99
+ * Base64
100
+
101
+ * Symbols are converted to Strings
102
+ * All Hashs have symbol keys
103
+ * All other objects are transformed into a Hash ('struct' in XMLRPC-speak) containing their instance variables as key-value-pairs.
104
+
105
+ ## Base64
106
+ If you want a string to be encoded as Base64 in your RPC call, just mark it:
107
+
108
+ proxy.some_method "my base64 encoded string".as_base64
109
+
110
+ Return values that arrive Base64 encoded, are instances of Rapuncel::Base64String,
111
+ which is a subclass of String, and therefore can be used as such, but allows you to differentiate
112
+ Base64 return values from normal String return values.
113
+
114
+ ## Supported methods
115
+ You can use most methods via
116
+
117
+ proxy.methodname 'a', 1, [:a, :b], :a => :d
118
+
119
+ However methods starting with \_\_, or ending with a bang \! or a question mark ? are not supported. To call those methods you can always
120
+ use
121
+
122
+ proxy.call! 'methodname', *args
123
+
124
+ or via
125
+
126
+ client.call_to_ruby 'methodname', *args
127
+
128
+ note
129
+
130
+ client.call 'methodname', *args
131
+
132
+ will return a Rapuncel::Response object, use _call\_to\_ruby_ to get a parsed result
133
+
134
+ ## Deserialization options
135
+
136
+ At the moment there are 2 options, to be set quite ugly as class attributes on Rapuncel::XmlRpc::Deserializer,
137
+ which will definitely change.
138
+
139
+ 1. **double\_as\_bigdecimal**
140
+ Deserialize all `<double>` tags as BigDecimal.
141
+ 2. **hash\_keys\_as\_string**
142
+ Don't use Symbols as keys for deserialized `<struct>`, but Strings.
143
+
144
+ ## Custom Serialization
145
+
146
+ module MySpecialSerialization
147
+ class Serializer < Rapuncel::XmlRpc::Serializer
148
+ end
149
+ class Deserializer < Rapuncel::XmlRpc::Deserializer
150
+ end
151
+ end
152
+
153
+ client = Rapuncel::Client.new :serialization => MySpecialSerialization
154
+ # or :serialization => 'MySpecialSerialization'
155
+
156
+ ## Todo ?
157
+
158
+ * RDoc
159
+ * Extensive functional tests
160
+ * HTTP-Proxy support
161
+ * Async requests
162
+ * XMLRPC Extensions (pluggable support)
163
+ * Apache vendor extensions
164
+ * How do i test SSL?
165
+
166
+ ## What happens if something goes wrong?
167
+ ### HTTP Errors / XMLRPC Faults
168
+ See Usage -> configuration -> raise\_on switch
169
+ ### Malformed XML/XMLRPC
170
+ Rapuncel will most likely fail hard.
171
+
172
+ ## Changelog
173
+
174
+ * **0.0.5**
175
+ * Refactored serialization, preparation for pluggable extensions
176
+ * Deserialization option "double\_as\_bigdecimal"
177
+ * Deserialization option "hash\_keys\_as\_string"
178
+ * base64 support
179
+ * Object#to\_xmlrpc now should expect a XmlRpc::Serializer instance,
180
+ not a Builder (you can access the Builder directly via XmlRpc::Serializer#builder)
181
+
182
+ ## Open Source
183
+
184
+ ### License
185
+
186
+ Copyright (c) 2011 Kayoom GmbH
187
+
188
+ Permission is hereby granted, free of charge, to any person obtaining
189
+ a copy of this software and associated documentation files (the
190
+ "Software"), to deal in the Software without restriction, including
191
+ without limitation the rights to use, copy, modify, merge, publish,
192
+ distribute, sublicense, and/or sell copies of the Software, and to
193
+ permit persons to whom the Software is furnished to do so, subject to
194
+ the following conditions:
195
+
196
+ The above copyright notice and this permission notice shall be
197
+ included in all copies or substantial portions of the Software.
198
+
199
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
200
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
201
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
203
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
204
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
205
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
206
+
207
+ ### Contribution
208
+
209
+ Pull requests are very welcome!
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+
6
+ desc 'Generate Rapuncel rdoc.'
7
+ Rake::RDocTask.new(:rdoc) do |rdoc|
8
+ rdoc.rdoc_dir = 'rdoc'
9
+ rdoc.title = 'Rapuncel'
10
+ rdoc.options << '--line-numbers' << '--inline-source'
11
+ rdoc.rdoc_files.include('README.md')
12
+ rdoc.rdoc_files.include('lib/**/*.rb')
13
+ end
14
+
15
+ begin
16
+ require 'rspec/core/rake_task'
17
+ desc 'Run RSpec suite.'
18
+ RSpec::Core::RakeTask.new('spec')
19
+ rescue LoadError
20
+ puts "RSpec is not available. In order to run specs, you must: gem install rspec"
21
+ end
22
+
23
+ desc 'Default: run unit tests.'
24
+ task :default => :spec
@@ -0,0 +1,43 @@
1
+ require 'curb'
2
+
3
+ module Rapuncel
4
+ module Adapters
5
+ module CurbAdapter
6
+ # Small response wrapper
7
+ class HttpResponse
8
+ def initialize body, code
9
+ @body, @code = body, code
10
+ end
11
+
12
+ def success?
13
+ !(@code =~ /^2/)
14
+ end
15
+
16
+ def body
17
+ @body
18
+ end
19
+
20
+ def code
21
+ @code
22
+ end
23
+ end
24
+
25
+ # Dispatch a XMLRPC via HTTP and return a response object.
26
+ def send_method_call str
27
+ @curb ||= Curl::Easy.new "#{connection.protocol}://#{connection.host}:#{connection.port}#{connection.path}"
28
+
29
+ if connection.auth?
30
+ @curb.username = connection.user
31
+ @curb.password = connection.password
32
+ @curb.enable_cookies = true
33
+ @curb.cookiejar = connection.cookie_file_path
34
+ end
35
+ @curb.post_body = str
36
+ @curb.headers = @curb.headers.merge connection.headers
37
+ @curb.perform
38
+
39
+ HttpResponse.new @curb.body_str, @curb.response_code
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,60 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'cookiejar'
4
+ require 'json'
5
+
6
+ module Rapuncel
7
+ module Adapters
8
+ module NetHttpAdapter
9
+ # Small response wrapper
10
+ class HttpResponse
11
+ def initialize response
12
+ @response = response
13
+ end
14
+
15
+ def success?
16
+ @response.is_a? Net::HTTPOK
17
+ end
18
+
19
+ def body
20
+ @response.body
21
+ end
22
+
23
+ def code
24
+ @response.code
25
+ end
26
+ end
27
+
28
+ # Dispatch a XMLRPC via HTTP and return a response object.
29
+ def send_method_call str
30
+ cookie_jar = if File.exists?(connection.cookie_file_path)
31
+ File.open(connection.cookie_file_path, 'r') do |file|
32
+ contents = file.read
33
+ if contents.empty?
34
+ CookieJar::Jar.new
35
+ else
36
+ CookieJar::Jar.json_create(JSON.parse(contents))
37
+ end
38
+ end
39
+ else
40
+ CookieJar::Jar.new
41
+ end
42
+ cookie_header = {}
43
+ cookie_header['Cookie'] = cookie_jar.get_cookie_header("#{connection.ssl? ? 'https' : 'http'}://#{connection.host}/")
44
+
45
+ request = Net::HTTP::Post.new(connection.path, connection.headers.merge(cookie_header))
46
+ request.basic_auth connection.user, connection.password if connection.auth?
47
+ request.body= str
48
+
49
+ http = Net::HTTP.new(connection.host, connection.port)
50
+ http.use_ssl = connection.ssl?
51
+ http.set_debug_output(STDOUT)
52
+ response = http.request(request)
53
+ cookie_jar.set_cookie("#{connection.ssl? ? 'https' : 'http'}://#{connection.host}/", response.header['Set-Cookie'])
54
+
55
+ File.open(connection.cookie_file_path, 'w'){ |file| file.write(cookie_jar.to_json) }
56
+ HttpResponse.new response
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,36 @@
1
+ if RUBY_VERSION =~ /^1\.8/
2
+ require 'base64'
3
+ end
4
+
5
+ class String
6
+ def as_base64
7
+ Rapuncel::Base64String.new self
8
+ end
9
+ end
10
+
11
+ module Rapuncel
12
+ class Base64String < String
13
+
14
+ if RUBY_VERSION =~ /^1\.9/
15
+
16
+ def base64_encoded
17
+ [self].pack 'm'
18
+ end
19
+
20
+ def self.decode_base64 string
21
+ new string.unpack('m')[0]
22
+ end
23
+
24
+ else
25
+
26
+ def base64_encoded
27
+ Base64.encode64 self
28
+ end
29
+
30
+ def self.decode_base64 string
31
+ new Base64.decode64 string
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,83 @@
1
+ require 'logger'
2
+
3
+ module Rapuncel
4
+ module Client::Logging
5
+ attr_accessor :logger
6
+
7
+ def log_level
8
+ @logger.try :level
9
+ end
10
+
11
+ def log_level= log_level
12
+ @logger && @logger.level = log_level
13
+ end
14
+
15
+ def logger= logger
16
+ @logger = case logger
17
+ when Logger
18
+ logger
19
+ when IO
20
+ Logger.new logger
21
+ when String, Symbol
22
+ Logger.new ActiveSupport::Inflector.constantize(logger.to_s.upcase)
23
+ else
24
+ Logger.new STDOUT
25
+ end
26
+ end
27
+
28
+ protected
29
+ def initialize_logging logger, log_level
30
+ self.logger = logger
31
+ if log_level
32
+ self.log_level = log_level
33
+ end
34
+
35
+ @logger.info { with_log_prefix "Initialized." }
36
+ @logger.debug { with_log_prefix "Using (De)Serializer: #{serialization.to_s}" }
37
+ end
38
+
39
+ def _call name, *args
40
+ if logger.debug?
41
+ logger.debug { with_log_prefix "Calling RPC Method \"#{name}\" with #{args.map(&:inspect).join(', ')}" }
42
+ else
43
+ logger.info { with_log_prefix "Calling RPC Method \"#{name}\" with #{args.length} arguments." }
44
+ end
45
+
46
+ super
47
+ end
48
+
49
+ def send_method_call xml
50
+ logger.debug { with_log_prefix "Sending XML:\n #{xml}" }
51
+
52
+ super
53
+ end
54
+
55
+ def execute request
56
+ super.tap do |response|
57
+ case
58
+ when response.success?
59
+ logger.debug { "Received XML-Response: \n #{response.body}" }
60
+ when response.fault?
61
+ level = raise_on_fault ? Logger::ERROR : Logger::WARN
62
+ logger.add(level) { "Received XML-Fault: \n #{response.body}" }
63
+ when response.error?
64
+ level = raise_on_error ? Logger::ERROR : Logger::WARN
65
+ logger.add(level) { "HTTP Error: #{response.status}\n #{response.body}" }
66
+ end
67
+ end
68
+ end
69
+
70
+ private
71
+ def log_host_config
72
+ "#{connection.host}:#{connection.port}#{connection.path}"
73
+ end
74
+
75
+ def with_log_prefix message
76
+ "#{log_prefix} #{message}"
77
+ end
78
+
79
+ def log_prefix
80
+ @log_prefix ||= "[XML-RPC@#{log_host_config}]"
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,117 @@
1
+ begin
2
+ require 'rapuncel/adapters/curb_adapter'
3
+ rescue LoadError
4
+ require 'rapuncel/adapters/net_http_adapter'
5
+ end
6
+ require 'rapuncel/connection'
7
+ require 'rapuncel/xml_rpc/serializer'
8
+ require 'rapuncel/xml_rpc/deserializer'
9
+ require 'active_support/core_ext/hash/except'
10
+ require 'active_support/inflector/methods'
11
+ require 'active_support/deprecation'
12
+
13
+ module Rapuncel
14
+ class Client
15
+ autoload :Logging, 'rapuncel/client/logging'
16
+
17
+ attr_accessor :connection, :raise_on_fault, :raise_on_error
18
+
19
+ if defined?(Adapters::CurbAdapter)
20
+ include Adapters::CurbAdapter
21
+ else
22
+ include Adapters::NetHttpAdapter
23
+ end
24
+
25
+ def initialize configuration = {}
26
+ @connection = Connection.new configuration.except(:raise_on, :serialization)
27
+ @serialization = configuration[:serialization]
28
+
29
+ @raise_on_fault, @raise_on_error = case configuration[:raise_on]
30
+ when :fault
31
+ [true, false]
32
+ when :error
33
+ [false, true]
34
+ when :both
35
+ [true, true]
36
+ else
37
+ [false, false]
38
+ end
39
+
40
+ if logger = configuration[:logger]
41
+ extend Logging
42
+ initialize_logging logger, configuration[:log_level]
43
+ end
44
+ end
45
+
46
+ def proxy_for interface = nil
47
+ if interface.nil?
48
+ @default_proxy ||= Proxy.new self, nil
49
+ else
50
+ @proxies ||= Hash.new do |hash, key|
51
+ hash[key] = Proxy.new self, key
52
+ end
53
+
54
+ @proxies[interface.to_s]
55
+ end
56
+ end
57
+
58
+ def proxy
59
+ proxy_for nil
60
+ end
61
+
62
+ # Dispatch a method call and return the response as Rapuncel::Response object.
63
+ def call name, *args
64
+ ActiveSupport::Deprecation.warn "Using #call is deprecated, please use #call_to_ruby instead.", caller
65
+ _call name, *args
66
+ end
67
+
68
+ # Dispatch a method call and return the response as parsed ruby.
69
+ def call_to_ruby name, *args
70
+ response = _call name, *args
71
+
72
+ raise_on_fault && response.fault? && raise_fault(response)
73
+ raise_on_error && response.error? && raise_error(response)
74
+
75
+ response.to_ruby
76
+ end
77
+
78
+ protected
79
+ def _call name, *args
80
+ execute Request.new(name, *args)
81
+ end
82
+
83
+ def execute request
84
+ xml = serializer[request]
85
+
86
+ Response.new send_method_call(xml), deserializer
87
+ end
88
+
89
+ def serialization
90
+ case @serialization
91
+ when Module
92
+ @serialization
93
+ when String, Symbol
94
+ ActiveSupport::Inflector.constantize(@serialization.to_s)
95
+ else
96
+ XmlRpc
97
+ end
98
+ end
99
+
100
+ def serializer
101
+ @serializer ||= serialization.const_get 'Serializer'
102
+ end
103
+
104
+ def deserializer
105
+ @deserializer ||= serialization.const_get 'Deserializer'
106
+ end
107
+
108
+ private
109
+ def raise_fault response
110
+ raise(Response::Fault, response.fault[:faultCode], response.fault[:faultString].split("\n"))
111
+ end
112
+
113
+ def raise_error response
114
+ raise(Response::Error, "HTTP Error: #{response.error.inspect}")
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,65 @@
1
+ module Rapuncel
2
+ class Connection
3
+ attr_accessor :host, :port, :path, :ssl, :user, :password, :cookie_file_path
4
+ alias_method :ssl?, :ssl
5
+
6
+ def initialize configuration = {}
7
+ load_configuration configuration
8
+ end
9
+
10
+ def url
11
+ "#{protocol}://#{host}:#{port}#{path}"
12
+ end
13
+
14
+ def host= value
15
+ @host = value.to_s.sub /^http(s)?\:\/\//, ''
16
+
17
+ if $1 == 's'
18
+ @ssl = true
19
+ end
20
+
21
+ @host
22
+ end
23
+
24
+ def path= value
25
+ unless value =~ /^\//
26
+ value = "/" + value
27
+ end
28
+
29
+ @path = value
30
+ end
31
+
32
+ def headers= headers
33
+ @headers = {
34
+ 'User-Agent' => 'Rapuncel, Ruby XMLRPC Client'
35
+ }.merge headers.stringify_keys
36
+ end
37
+
38
+ def headers
39
+ @headers.merge 'Accept' => 'text/xml', 'content-type' => 'text/xml'
40
+ end
41
+
42
+ def protocol
43
+ ssl? ? 'https' : 'http'
44
+ end
45
+ alias_method :scheme, :protocol
46
+
47
+ def auth?
48
+ !!user && !!password
49
+ end
50
+
51
+ protected
52
+ def load_configuration configuration
53
+ configuration = configuration.symbolize_keys
54
+
55
+ self.ssl = !!configuration[:ssl]
56
+ self.host = configuration[:host] || 'localhost'
57
+ self.port = configuration[:port] || '8080'
58
+ self.path = configuration[:path] || '/'
59
+ self.headers = configuration[:headers] || {}
60
+ self.user = configuration[:user]
61
+ self.password = configuration[:password]
62
+ self.cookie_file_path = configuration[:cookie_file_path]
63
+ end
64
+ end
65
+ end