json-rpc-client 0.1.1

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 45369d3297682f37bcf9119e27b3756a89ed464c
4
+ data.tar.gz: 9e1d8b669fcb8c51dd814161c7337abf7a7769d0
5
+ SHA512:
6
+ metadata.gz: e5d14d9afa48ab3f7b084d9d435aa081b54b411490b4530b189f27f90fa585942a1cb266b14a93e440656eaa663db528f40e683af47d02c1eb484edc5375a64b
7
+ data.tar.gz: 3c6093337ccce5a371c8115a5ef5ef248869405b5e00a628813d080e48d7d5b9eb3f5db2823ccda06bc4b002168b817a4d6dbd0628f41dc9d29dbeadcd2d90d6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'bundler'
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Copyright (C) 2012-2013 Textalk AB
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4
+ and associated documentation files (the "Software"), to deal in the Software without restriction,
5
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
6
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
7
+ furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial
10
+ portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,87 @@
1
+ Asynchronous (EventMachine) JSON-RPC 2.0 client
2
+ ===============================================
3
+
4
+ This gem is a client implementation for JSON-RPC 2.0. It uses EventMachine to
5
+ enable asynchronous communication with a JSON-RPC server. It can be used synchronously if
6
+ called within a (non-root) fiber.
7
+
8
+ Usage example for asynchronous behaviour:
9
+ ```Ruby
10
+ wallet = JsonRpcClient.new('https://localhost:8332/') # Local bitcoin wallet
11
+ balance_rpc = wallet.getbalance()
12
+ balance_rpc.callback do |result|
13
+ puts result # => 90.12345678
14
+ end
15
+
16
+ balance_rpc.errback do |error|
17
+ puts error
18
+ # => "JsonRpcClient.Error: Bad method, code: -32601, data: nil"
19
+ end
20
+ ```
21
+
22
+ Usage example for synchronous behaviour:
23
+ ```Ruby
24
+ require 'eventmachine'
25
+ require 'json-rpc-client'
26
+ require 'fiber'
27
+
28
+ EventMachine.run do
29
+ # To use the syncing behaviour, use it in a fiber.
30
+ fiber = Fiber.new do
31
+ article = JsonRpcClient.new(
32
+ 'https://shop.textalk.se/backend/jsonrpc/Article/14284660',
33
+ {asynchronous_calls: false}
34
+ )
35
+ puts article.get({name: true})
36
+ # => {:name=>{:sv=>"Presentkort 1000 kr", :en=>"Gift certificate 1000 SEK"}}
37
+
38
+ EventMachine.stop
39
+ end
40
+
41
+ fiber.resume
42
+ end
43
+ ```
44
+
45
+ Logging
46
+ -------
47
+
48
+ The client supports both a default logger (for all instances) and a per instance logger.
49
+ Simply attach a logger of your choice(that responds to info, warning, error and debug) and
50
+ any interaction will be output as debug, and any errors as errors. Any per instance logger will
51
+ override the default logger for that instance.
52
+
53
+ ```Ruby
54
+ require 'logger'
55
+ JsonRpcClient.default_logger = Logger.new($STDOUT)
56
+ wallet = JsonRpcClient.new('https://localhost:8332/') # Local bitcoin wallet
57
+ wallet.logger = MyCustomLogger.new()
58
+ ```
59
+
60
+ Development
61
+ -----------
62
+
63
+ To set up a development environment, simply do:
64
+
65
+ ```bash
66
+ bundle install
67
+ bundle exec rake # run the test suite
68
+ ```
69
+
70
+ There are autotests located in the test folder and the framework used is
71
+ [Bacon](https://github.com/chneukirchen/bacon). They're all mocked with
72
+ [VCR](https://github.com/vcr/vcr)/[Webmock](https://github.com/bblimke/webmock)
73
+ so no internet connection is required to run them.
74
+
75
+ JSON-RPC 2.0
76
+ ------------
77
+
78
+ JSON-RPC 2.0 is a very simple protocol for remote procedure calls,
79
+ agnostic of carrier (http, websocket, tcp, whatever…).
80
+
81
+ [JSON-RPC 2.0 Specification](http://www.jsonrpc.org/specification)
82
+
83
+ Copyright
84
+ ---------
85
+ Copyright (C) 2012-2013, Textalk AB <http://textalk.se/>
86
+
87
+ JSON-RPC client is freely distributable under the terms of an MIT license. See [LICENCE](LICENSE).
@@ -0,0 +1,7 @@
1
+ desc 'Runs the test suite'
2
+ task :test do
3
+ sh "bacon test/json-rpc-test.rb"
4
+ end
5
+
6
+ desc "Run tests"
7
+ task :default => :test
@@ -0,0 +1,261 @@
1
+ require 'em-http-request'
2
+ require 'json'
3
+ require 'addressable/uri'
4
+
5
+ # This implements a client for JSON-RPC (version 2) calls.
6
+ #
7
+ # @example Asynchronous
8
+ # wallet = JsonRpcClient.new('https://localhost:8332/') # Local bitcoin wallet
9
+ # balance_rpc = wallet.getbalance()
10
+ # balance_rpc.callback do |result|
11
+ # puts result # => 90.12345678
12
+ # end
13
+ #
14
+ # balance_rpc.errback do |error|
15
+ # puts error
16
+ # # => "JsonRpcClient.Error: Bad method, code: -32601, data: nil"
17
+ # end
18
+ #
19
+ # @example Synchronous
20
+ # require 'eventmachine'
21
+ # require 'json-rpc-client'
22
+ # require 'fiber'
23
+ #
24
+ # EventMachine.run do
25
+ # # To use the syncing behaviour, use it in a fiber.
26
+ # fiber = Fiber.new do
27
+ # article = JsonRpcClient.new(
28
+ # 'https://shop.textalk.se/backend/jsonrpc/Article/14284660',
29
+ # {asynchronous_calls: false}
30
+ # )
31
+ # puts article.get({name: true})
32
+ # # => {:name=>{:sv=>"Presentkort 1000 kr", :en=>"Gift certificate 1000 SEK"}}
33
+
34
+ # EventMachine.stop
35
+ # end
36
+
37
+ # fiber.resume
38
+ # end
39
+ #
40
+ # @!attribute asynchronous_calls
41
+ # @return [Boolean] If method_missing calls are made asynchronously. Default: true
42
+ # @!attribute symbolize_names
43
+ # @return [Boolean] If the result of sync calls should have the names be symbols. Default: true
44
+ # @!attribute logger
45
+ # @return [Logger] The logger instance attached to the instance of JsonRpcClient.
46
+ # Should accept method calls to debug, info, warning & error. Use JsonRpcClient.log for logging
47
+ class JsonRpcClient
48
+ attr_accessor :asynchronous_calls, :symbolize_names, :logger
49
+
50
+ # Invalid JSON was received by the server.
51
+ # An error occurred on the server while parsing the JSON text.
52
+ INVALID_JSON = -32700
53
+ # The JSON sent is not a valid Request object.
54
+ INVALID_REQUEST = -32600
55
+ # The method does not exist / is not available.
56
+ METHOD_NOT_FOUND = -32601
57
+ # Invalid method parameter(s).
58
+ INVALID_PARAMS = -32602
59
+ # Internal JSON-RPC error.
60
+ INTERNAL_ERROR = -32603
61
+
62
+ # Create an instance to call the RPC methods on.
63
+ #
64
+ # @param [String, Addressable::URI, #to_str] service_uri The URI to connect to.
65
+ # @param [Hash] options Options hash to pass to the instance.
66
+ # See Instance Attribute Details in the documentation for more details on supported options.
67
+ def initialize(service_uri, options = {})
68
+ @uri = Addressable::URI.parse(service_uri)
69
+ @asynchronous_calls = options.has_key?(:asynchronous_calls) ?
70
+ !!options[:asynchronous_calls] :
71
+ true
72
+ @symbolize_names = options.has_key?(:symbolize_names) ? !!options[:symbolize_names] : true
73
+ @logger = options[:logger]
74
+ end
75
+
76
+ # Called whenever the current object receives a method call that it does not respond to.
77
+ # Will make a call asynchronously or synchronously depending on asynchronous_calls.
78
+ #
79
+ # @param [String] method the API method, ie get, set.
80
+ # @param [Array] params the parameters sent with the method call.
81
+ def method_missing(method, *params)
82
+ @asynchronous_calls ? self._call_async(method, params) : self._call_sync(method, params)
83
+ end
84
+
85
+ # Makes the call asynchronously and returns a EM::Deferrable.
86
+ # The underscore is there to avoid conflicts with server methods, not to denote a private method.
87
+ #
88
+ # @param [String] method The API method, ie get, set etc.
89
+ # @param [Array, Hash] params The parameters that should be sent along in the post body.
90
+ # @return [EM::Deferrable] The JsonRpcClient::Request as data.
91
+ def _call_async(method, params)
92
+ return Request.new({
93
+ service_uri: @uri.to_s,
94
+ method: method,
95
+ params: params,
96
+ logger: @logger,
97
+ symbolize_names: @symbolize_names
98
+ });
99
+ end
100
+
101
+ # Make the call synchronously, returns the result directly.
102
+ # The underscore is there to avoid conflicts with server methods, not to denote a private method.
103
+ #
104
+ # @param [String] method The API method, ie get, set etc.
105
+ # @param [Array, Hash] params The parameters that should be sent along in the post body.
106
+ # @return [Hash] The result.
107
+ # @raise JsonRpcClient::Error When the request responds with failed status.
108
+ def _call_sync(method, params)
109
+ f = Fiber.current
110
+
111
+ request = _call_async(method, params)
112
+
113
+ request.callback do |*args|
114
+ # If we happen to be in the calling fiber, return the data directly.
115
+ return args.size == 1 ? args.first : args if f == Fiber.current
116
+ # else, return it to the yield call below (in the correct fiber).
117
+ f.resume(*args)
118
+ end
119
+
120
+ request.errback do |error|
121
+ json_rpc_error = Error.new(error[:message], error[:code], error[:data])
122
+ # If we happen to be in the calling fiber, raise the error directly.
123
+ raise json_rpc_error if f == Fiber.current
124
+ # else, return it to the yield call below (in the correct fiber).
125
+ f.resume(json_rpc_error)
126
+ end
127
+
128
+ begin
129
+ response = Fiber.yield # will yield and return the data or raise the error.
130
+ rescue FiberError
131
+ raise "To to use the syncing behaviour in JsonRpcClient, the call must be in a fiber."
132
+ end
133
+ raise response if response.kind_of?(Error)
134
+ return response
135
+ end
136
+
137
+ # Makes a notify call by just sending a HTTP request and not caring about the response.
138
+ # The underscore is there to avoid conflicts with server methods, not to denote a private method.
139
+ #
140
+ # @param [String] method The API method, ie get, set etc.
141
+ # @param [Array, Hash] params The parameters that should be sent along in the post body.
142
+ def _notify(method, params)
143
+ post_body = {
144
+ method: method,
145
+ params: params,
146
+ jsonrpc: '2.0'
147
+ }.to_json
148
+
149
+
150
+ EM::HttpRequest.new(@uri.to_s).post :body => post_body
151
+ self.class.log(:debug, "NOTIFY: #{@uri.to_s} --> #{post_body}", @logger)
152
+ end
153
+
154
+ # The logger to be used for an instances if they don't have a logger set on that instance.
155
+ @@default_logger = nil
156
+
157
+ # @return The default logger object.
158
+ def self.default_logger()
159
+ @@default_logger
160
+ end
161
+
162
+ # Add a default logging instance, that should accept method calls to debug, info, warning & error.
163
+ # Don't use directly, use self.log.
164
+ def self.default_logger=(logger)
165
+ @@default_logger = logger
166
+ end
167
+
168
+ # Logging class that takes severity and message. Only logs if a logger is attached.
169
+ #
170
+ # @param [Symbol, String] level The severity, ie a method of a logger, (info, debug, warn, error).
171
+ # @param [String] message The log message.
172
+ # @param [Logger] logger An instance of a logger class.
173
+ def self.log(level, message, logger = nil)
174
+ logger = logger || @@default_logger
175
+ logger.send(level.to_sym, message) if logger.respond_to?(level.to_sym)
176
+ end
177
+
178
+ # This class corresponds to the JSON-RPC error object gotten from the server.
179
+ # A "faked" instance of this will be thrown for communication errors as well.
180
+ class Error < RuntimeError
181
+ attr_reader :code, :data
182
+ def initialize(msg, code, data)
183
+ super(msg)
184
+ @code = code
185
+ @data = data
186
+ end
187
+
188
+
189
+ # Returns the contents of the current error object as a string.
190
+ #
191
+ # @return [String]
192
+ def inspect
193
+ %|#{self.class}: #{self.message}, code: #{@code.inspect}, data: #{@data.inspect}|
194
+ end
195
+ end
196
+
197
+ # This class makes a single request to the JSON-RPC service as a EventMachine::Deferrable.
198
+ # The deferrable object will give a successful callback in the result-part of the response.
199
+ # A unsuccessful request will set the deferred status as failed, and will not deliver a result
200
+ # only the JSON-RPC error object as a Hash.
201
+ class Request
202
+ include EM::Deferrable
203
+
204
+ def initialize(params)
205
+ service_uri = params[:service_uri]
206
+ post_body = {
207
+ method: params[:method],
208
+ params: params[:params],
209
+ id: 'jsonrpc',
210
+ jsonrpc: '2.0',
211
+ }.to_json
212
+
213
+ http = EM::HttpRequest.new(service_uri).post :body => post_body
214
+ JsonRpcClient.log(:debug, "NEW REQUEST: #{service_uri} --> #{post_body}", params[:logger])
215
+
216
+ http.callback do |response|
217
+ begin
218
+ resp = JSON.parse(response.response, {symbolize_names: params[:symbolize_names]})
219
+ JsonRpcClient.log(
220
+ :debug,
221
+ "REQUEST FINISH: #{service_uri} METHOD: #{params[:method]} RESULT: #{resp}",
222
+ params[:logger]
223
+ )
224
+
225
+ if resp.has_key?(:error) || resp.has_key?("error")
226
+ JsonRpcClient.log(
227
+ :error,
228
+ "Error in response from #{service_uri}: #{resp[:error]}",
229
+ params[:logger]
230
+ )
231
+ self.set_deferred_status :failed, resp[:error] || resp["error"]
232
+ end
233
+ self.set_deferred_status :succeeded, resp[:result] || resp["result"]
234
+ rescue JSON::ParserError => e
235
+ JsonRpcClient.log(
236
+ :error,
237
+ "Got exception during parsing of #{response}: #{e}",
238
+ params[:logger]
239
+ )
240
+
241
+ # Making an error object in the same style as a JSON RPC error.
242
+ set_deferred_status :failed, {
243
+ code: JsonRpcClient::INVALID_JSON,
244
+ message: e.message,
245
+ data: e
246
+ }
247
+ end
248
+ end
249
+
250
+ http.errback do |response|
251
+ JsonRpcClient.log(:error, "Error in http request: #{response.error}", params[:logger])
252
+ set_deferred_status :failed, {
253
+ code: JsonRpcClient::INVALID_JSON,
254
+ message: response.error
255
+ }
256
+ end
257
+
258
+ self
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,162 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'em-spec/bacon'
3
+ require 'vcr'
4
+ require 'json'
5
+ require File.expand_path(File.dirname(__FILE__) + '/test-helper.rb')
6
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib/json-rpc-client'))
7
+
8
+ # Sets up a eventmachine channel to be able to notify subscribers when a http request has been done
9
+ # With the async nature and with _notify not returning a Deferrable we can't know if it sent
10
+ # Or when it finished it's request, hence why we hook onto after_http_request and use that.
11
+ vcr_channel = EventMachine::Channel.new
12
+
13
+ VCR.configure do |c|
14
+ c.cassette_library_dir = File.expand_path(File.dirname(__FILE__)) + '/vcr_cassettes'
15
+ c.hook_into :webmock
16
+ # After a http request, push a notification in the EM channel with the request and response.
17
+ c.after_http_request do |request, response|
18
+ vcr_channel.push({request: request, response: response})
19
+ end
20
+ end
21
+
22
+ EM.spec_backend = EventMachine::Spec::Bacon
23
+ EM.describe 'json-rpc-test' do
24
+
25
+ should 'Test default logging' do
26
+ VCR.use_cassette('logger-test') do
27
+ custom_logger = CustomLogger.new()
28
+ JsonRpcClient.default_logger = custom_logger
29
+ client = JsonRpcClient.new('https://shop.textalk.se/backend/jsonrpc/Article/12565607')
30
+ (JsonRpcClient.default_logger == custom_logger).should.equal true
31
+ JsonRpcClient.default_logger = nil #cleanup
32
+ end
33
+
34
+ done
35
+ end
36
+
37
+ should 'Make a sucessful sync json-rpc call and recieve symbolized values' do
38
+ VCR.use_cassette('sync-symbolized') do
39
+ client = JsonRpcClient.new(
40
+ 'https://shop.textalk.se/backend/jsonrpc/Article/12565484',
41
+ {asynchronous_calls: false}
42
+ )
43
+ client.logger = CustomLogger.new()
44
+ uid = client.get(uid: true) # Calling method get on RPC backend, only asking for uid
45
+ client.logger.logs[0] == "NEW REQUEST: https://shop.textalk.se/backend/jsonrpc/Article/12565484 --> {\"method\":\"get\",\"params\":[{\"uid\":true}],\"id\":\"jsonrpc\",\"jsonrpc\":\"2.0\"}"
46
+ client.logger.logs[1] == "REQUEST FINISH: https://shop.textalk.se/backend/jsonrpc/Article/12565484 METHOD: get RESULT: {:jsonrpc=>\"2.0\", :id=>\"jsonrpc\", :result=>{:uid=>\"12565484\"}}"
47
+ (uid == {uid: "12565484"}).should.equal true
48
+ end
49
+
50
+ done
51
+ end
52
+
53
+ should 'Make a sucessful sync json-rpc call and recieve non-symbolized values' do
54
+ VCR.use_cassette('sync-nonsymbolized') do
55
+ client = JsonRpcClient.new('https://shop.textalk.se/backend/jsonrpc/Article/14284660', {
56
+ asynchronous_calls: false,
57
+ symbolize_names: false
58
+ })
59
+ name = client.get(name: true) # Calling same method, asking for name. Should not symobolize result
60
+ (name == {"name"=>{"sv"=>"Presentkort 1000 kr", "en"=>"Gift certificate 1000 SEK"}}).should.equal true
61
+ end
62
+
63
+ done
64
+ end
65
+
66
+ should 'Make a sucessful async json-rpc call and recieve a JsonRpcClient::Request' do
67
+ VCR.insert_cassette("async")
68
+ client = JsonRpcClient.new('https://shop.textalk.se/backend/jsonrpc/Article/12565605')
69
+ request = client.uid() # Calling a valid uri, should get a request back
70
+ request.is_a?(JsonRpcClient::Request).should.equal true
71
+ request.is_a?(EM::Deferrable).should.equal true
72
+ request.callback do |result|
73
+ result.should.equal "12565605"
74
+ VCR.eject_cassette
75
+ done
76
+ end
77
+ end
78
+
79
+ should 'Make a notify call' do
80
+ VCR.insert_cassette("notify")
81
+ # Subscribe to the EM channel, so that we only after the request do the matching and
82
+ # eject the VCR cassette and end the request.
83
+ subscription = vcr_channel.subscribe do |request_response_hash|
84
+ request = request_response_hash[:request]
85
+ (JSON.parse(request[:body]) == {"method"=>"uid", "params"=>{}, "jsonrpc"=>"2.0"}).should.equal true
86
+ vcr_channel.unsubscribe(subscription) # Unsub from the channel
87
+ VCR.eject_cassette
88
+ done # Exit out of the request
89
+ end
90
+ client = JsonRpcClient.new('https://shop.textalk.se/backend/jsonrpc/Article/12565604')
91
+ client._notify(:uid, {}) # Just shouldn't raise an error, and should hit backend.
92
+ end
93
+
94
+ should 'raise jsonrpcerror on bad response' do
95
+ should.raise(JsonRpcClient::Error) do
96
+ VCR.use_cassette('bad-response') do
97
+ client = JsonRpcClient.new('http://www.google.com/', {asynchronous_calls: false})
98
+ client.dummy() # Calling non-existing method on non-rpc backend.
99
+ end
100
+ end
101
+
102
+ done
103
+ end
104
+
105
+ should 'get an http error and raise jsonrpcerror on bad backend url' do
106
+ should.raise(JsonRpcClient::Error) do
107
+ VCR.use_cassette('weird-url') do
108
+ client = JsonRpcClient.new('http://@ł€®þ.com/', {asynchronous_calls: false})
109
+ client.dummy() # Calling non-existing method on non-rpc backend.
110
+ end
111
+ end
112
+
113
+ done
114
+ end
115
+
116
+ should 'get a jsonrpcerror from the backend' do
117
+ should.raise(JsonRpcClient::Error) do
118
+ VCR.use_cassette('jsonrpcerror-method-missing') do
119
+ client = JsonRpcClient.new(
120
+ 'http://shop.textalk.se/backend/jsonrpc/Foo',
121
+ {asynchronous_calls: false}
122
+ )
123
+ error = client.dummy() # Calling non-existing method on rpc backend.
124
+ end
125
+ end
126
+
127
+ done
128
+ end
129
+
130
+ should 'test the error inspect method' do
131
+ VCR.use_cassette('inspect') do
132
+ begin
133
+ client = JsonRpcClient.new(
134
+ 'http://shop.textalk.se/backend/jsonrpc/Article/12565604',
135
+ {asynchronous_calls: false}
136
+ )
137
+ client.dummy()
138
+ rescue JsonRpcClient::Error => e
139
+ e.inspect.should.equal "JsonRpcClient::Error: Method not found: dummy, code: -32601, data: nil"
140
+ end
141
+ end
142
+
143
+ done
144
+ end
145
+ end
146
+
147
+ describe 'Non-fiber' do
148
+
149
+ should 'raise an error about no fibers being used' do
150
+ VCR.use_cassette('non-fiber') do
151
+ should.raise(RuntimeError) do
152
+ EM.run do
153
+ client = JsonRpcClient.new(
154
+ 'http://shop.textalk.se/backend/jsonrpc/Article/12565604',
155
+ {asynchronous_calls: false}
156
+ )
157
+ client.get()
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,23 @@
1
+ require 'simplecov'
2
+ require 'simplecov-rcov'
3
+ require 'logger'
4
+
5
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
6
+ SimpleCov.command_name 'bacon'
7
+ SimpleCov.start
8
+
9
+ # A small custom logger for the tests, all log messages are saved to an array.
10
+ class CustomLogger < Logger
11
+ attr_reader :logs
12
+ def initialize()
13
+ @logs = []
14
+ end
15
+
16
+ def debug(message)
17
+ @logs << message
18
+ end
19
+
20
+ def error(message)
21
+ @logs << message
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,207 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json-rpc-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Fredrik Liljegren
8
+ - Lars Olsson
9
+ - Denis Dervisevic
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-04-18 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: addressable
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: em-http-request
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: json
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: bacon
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: em-spec
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: rack
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: rake
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ - !ruby/object:Gem::Dependency
114
+ name: simplecov
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: simplecov-rcov
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ - !ruby/object:Gem::Dependency
142
+ name: vcr
143
+ requirement: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ type: :development
149
+ prerelease: false
150
+ version_requirements: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ - !ruby/object:Gem::Dependency
156
+ name: webmock
157
+ requirement: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - '='
160
+ - !ruby/object:Gem::Version
161
+ version: 1.9.0
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - '='
167
+ - !ruby/object:Gem::Version
168
+ version: 1.9.0
169
+ description: Asynchronous (EventMachine) JSON-RPC 2.0 over HTTP client.
170
+ email:
171
+ executables: []
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - lib/json-rpc-client.rb
176
+ - Gemfile
177
+ - LICENSE
178
+ - README.md
179
+ - Rakefile
180
+ - test/json-rpc-test.rb
181
+ - test/test-helper.rb
182
+ homepage: https://github.com/Textalk/json-rpc-client-ruby
183
+ licenses:
184
+ - MIT
185
+ metadata: {}
186
+ post_install_message:
187
+ rdoc_options: []
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '>='
193
+ - !ruby/object:Gem::Version
194
+ version: 1.9.0
195
+ required_rubygems_version: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - '>='
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ requirements: []
201
+ rubyforge_project:
202
+ rubygems_version: 2.0.3
203
+ signing_key:
204
+ specification_version: 4
205
+ summary: JSON-RPC 2.0 client.
206
+ test_files: []
207
+ has_rdoc: