jimson 0.8.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5745486a124bbc3d73284db9d6294aac57eb23d1815e2ad8c98f145f9fc124a9
4
+ data.tar.gz: 258d62e7212cc0c559d167aacf1f511a5cbf88e2b022ff423634537cefa570a9
5
+ SHA512:
6
+ metadata.gz: 2f2c58014cf11afea61ed91cc2bbb6e4b57bd3622ac58b2c4b4372054ce72c25938bfa72bfbbdc233c4ec1afaa698103d8e889ab22496d580c161ee99858d49e
7
+ data.tar.gz: c2b1642505d7ff5846c8cb9314be37ec95d409bf466eb126120870cb76ec5b5db0a5cb58693e4e50e932e05c148f5395890dffcd75ea397fb0d9c396fbc7a053
@@ -1,17 +1,57 @@
1
- == 0.8.0 / 2012-08-17
1
+ # 0.12.0 / 2021-05-05
2
+
3
+ * Major enhancements
4
+
5
+ * Add ability to specify custom content type
6
+ * Add support for named parameters
7
+ * Add Router :ns_sep option for custom namespace
8
+ * made it possible to overwrite advanced RestClient values, like ssl_ca_file
9
+
10
+ * Minor enhancements
11
+
12
+ * Unified Bignum and Fixnum to Integer
13
+ * Add data returned to invalid response exception
14
+ * Fix json variable name on invalid json response
15
+
16
+ # 0.11.0 / 2016-03-13
17
+
18
+ * Minor enhancements
19
+
20
+ * Update dependency versions for Ruby 2.*
21
+ * Remove Gemfile.lock
22
+
23
+ # 0.10.0 / 2013-06-28
24
+
25
+ * Minor enhancements
26
+
27
+ * Update dependency versions
28
+
29
+ # 0.9.1 / 2012-09-18
30
+
31
+ * Bug fixes
32
+
33
+ * Allow opts to be passed to Server.with_routes
34
+
35
+ # 0.9.0 / 2012-08-22
36
+
37
+ * Minor enhancements
38
+
39
+ * Add show_errors option to server, which will cause application errors to include the error name and the first line of the backtrace
40
+
41
+ # 0.8.0 / 2012-08-17
2
42
 
3
43
  * Major enhancements
4
44
 
5
45
  * Add namespaced method calls to client (e.g. 'client[:foo].sum(1,2,3) # calls foo.sum')
6
46
  * Add Server.with_routes to quickly created a routed server
7
47
 
8
- == 0.7.1 / 2012-08-16
48
+ # 0.7.1 / 2012-08-16
9
49
 
10
50
  * Bug fixes
11
51
 
12
52
  * Fix handling of array params in client, which were erroneously being flattened
13
53
 
14
- == 0.7.0 / 2012-04-13
54
+ # 0.7.0 / 2012-04-13
15
55
 
16
56
  * Major enhancements
17
57
 
@@ -21,13 +61,13 @@
21
61
 
22
62
  * Fix deprecation warning about RDoc task in Rakefile
23
63
 
24
- == 0.6.0 / 2012-03-14
64
+ # 0.6.0 / 2012-03-14
25
65
 
26
66
  * Minor enhancements
27
67
 
28
68
  * Add ability to pass options to Rack and RestClient
29
69
 
30
- == 0.5.0 / 2012-03-06
70
+ # 0.5.0 / 2012-03-06
31
71
 
32
72
  * Major enhancements
33
73
 
@@ -37,37 +77,37 @@
37
77
 
38
78
  * Allow BigNum in 'id' field of request and response
39
79
 
40
- == 0.3.1 / 2011-08-11
80
+ # 0.3.1 / 2011-08-11
41
81
 
42
82
  * Minor enhancements
43
83
 
44
84
  * Refactor the way the server is intantiated/started to work better with config.ru
45
85
 
46
- == 0.3.0 / 2011-08-11
86
+ # 0.3.0 / 2011-08-11
47
87
 
48
88
  * Major enhancements
49
89
 
50
90
  * Replace eventmachine-httpserver with rack for more cross-platform goodness
51
91
 
52
- == 0.2.3 / 2011-08-01
92
+ # 0.2.3 / 2011-08-01
53
93
 
54
94
  * Bug fixes
55
95
 
56
96
  * Fix argument error in client error handling
57
97
 
58
- == 0.2.2 / 2011-07-28
98
+ # 0.2.2 / 2011-07-28
59
99
 
60
100
  * Bug fixes
61
101
 
62
102
  * Fix invalid local variable error in client error handling
63
103
 
64
- == 0.2.1 / 2011-07-27
104
+ # 0.2.1 / 2011-07-27
65
105
 
66
106
  * Bug fixes
67
107
 
68
108
  * Fix error in client handling some errors caused by errant 'new' keyword
69
109
 
70
- == 0.2.0 / 2011-07-20
110
+ # 0.2.0 / 2011-07-20
71
111
 
72
112
  * Major enhancements
73
113
 
data/README.md CHANGED
@@ -1,29 +1,41 @@
1
1
  # Jimson
2
+
2
3
  ### JSON-RPC 2.0 Client and Server for Ruby
3
- ![next build status](https://secure.travis-ci.org/chriskite/jimson.png?branch=next)
4
+
5
+ [![Build Status](https://github.com/chriskite/jimson/actions/workflows/ruby.yml/badge.svg?branch=main)](https://github.com/chriskite/jimson/actions/workflows/ruby.yml)
4
6
 
5
7
  ## Client: Quick Start
6
- require 'jimson'
7
- client = Jimson::Client.new("http://www.example.com:8999") # the URL for the JSON-RPC 2.0 server to connect to
8
- result = client.sum(1,2) # call the 'sum' method on the RPC server and save the result '3'
8
+
9
+ ```ruby
10
+ require 'jimson'
11
+ client = Jimson::Client.new("http://www.example.com:8999") # the URL for the JSON-RPC 2.0 server to connect to
12
+ result = client.sum(1,2) # call the 'sum' method on the RPC server and save the result '3'
13
+ ```
9
14
 
10
15
  ## Server: Quick Start
11
- require 'jimson'
12
16
 
13
- class MyHandler
14
- extend Jimson::Handler
17
+ ```ruby
18
+ require 'jimson'
15
19
 
16
- def sum(a,b)
17
- a + b
18
- end
19
- end
20
+ class MyHandler
21
+ extend Jimson::Handler
20
22
 
21
- server = Jimson::Server.new(MyHandler.new)
22
- server.start # serve with webrick on http://0.0.0.0:8999/
23
+ def sum(a,b)
24
+ a + b
25
+ end
26
+ end
27
+
28
+ server = Jimson::Server.new(MyHandler.new)
29
+ server.start # serve with webrick on http://0.0.0.0:8999/
30
+ ```
23
31
 
24
32
  ## JSON Engine
33
+
25
34
  Jimson uses multi\_json, so you can load the JSON library of your choice in your application and Jimson will use it automatically.
26
35
 
27
36
  For example, require the 'json' gem in your application:
28
- require 'json'
37
+
38
+ ```ruby
39
+ require 'json'
40
+ ```
29
41
 
data/Rakefile CHANGED
@@ -1,26 +1,26 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/lib/')
2
+ require 'jimson/version'
1
3
  require 'rubygems'
2
4
  require 'rake'
3
5
  require 'rspec/core/rake_task'
4
6
 
7
+ gem 'rubygems-tasks', '~> 0.2'
8
+ require 'rubygems/tasks'
9
+
10
+ Gem::Tasks.new
11
+
5
12
  desc "Run all specs"
6
13
  RSpec::Core::RakeTask.new(:rspec) do |spec|
7
14
  spec.pattern = 'spec/**/*_spec.rb'
8
15
  end
9
16
 
10
- RSpec::Core::RakeTask.new(:rcov) do |spec|
11
- spec.pattern = 'spec/**/*_spec.rb'
12
- spec.rcov = true
13
- end
14
-
15
17
  task :default => :rspec
16
18
 
17
19
  require 'rdoc/task'
18
20
 
19
21
  Rake::RDocTask.new do |rdoc|
20
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
21
-
22
22
  rdoc.rdoc_dir = 'rdoc'
23
- rdoc.title = "jimson #{version}"
23
+ rdoc.title = "jimson #{Jimson::VERSION}"
24
24
  rdoc.rdoc_files.include('README*')
25
25
  rdoc.rdoc_files.include('lib/**/*.rb')
26
26
  end
data/lib/jimson/client.rb CHANGED
@@ -12,13 +12,14 @@ module Jimson
12
12
  rand(10**12)
13
13
  end
14
14
 
15
- def initialize(url, opts = {}, namespace = nil)
15
+ def initialize(url, opts = {}, namespace = nil, client_opts = {})
16
16
  @url = url
17
17
  URI.parse(@url) # for the sake of validating the url
18
18
  @batch = []
19
19
  @opts = opts
20
20
  @namespace = namespace
21
- @opts[:content_type] = 'application/json'
21
+ @opts[:content_type] ||= 'application/json'
22
+ @client_opts = client_opts
22
23
  end
23
24
 
24
25
  def process_call(sym, args)
@@ -45,9 +46,9 @@ module Jimson
45
46
  'params' => args,
46
47
  'id' => self.class.make_id
47
48
  })
48
- resp = RestClient.post(@url, post_data, @opts)
49
+ resp = RestClient::Request.execute(@client_opts.merge(:method => :post, :url => @url, :payload => post_data, :headers => @opts))
49
50
  if resp.nil? || resp.body.nil? || resp.body.empty?
50
- raise Client::Error::InvalidResponse.new
51
+ raise Client::Error::InvalidResponse.new(resp)
51
52
  end
52
53
 
53
54
  return resp.body
@@ -55,9 +56,9 @@ module Jimson
55
56
 
56
57
  def send_batch_request(batch)
57
58
  post_data = MultiJson.encode(batch)
58
- resp = RestClient.post(@url, post_data, @opts)
59
+ resp = RestClient::Request.execute(@client_opts.merge(:method => :post, :url => @url, :payload => post_data, :headers => @opts))
59
60
  if resp.nil? || resp.body.nil? || resp.body.empty?
60
- raise Client::Error::InvalidResponse.new
61
+ raise Client::Error::InvalidResponse.new(resp)
61
62
  end
62
63
 
63
64
  return resp.body
@@ -72,7 +73,7 @@ module Jimson
72
73
  end
73
74
 
74
75
  def process_single_response(data)
75
- raise Client::Error::InvalidResponse.new if !valid_response?(data)
76
+ raise Client::Error::InvalidResponse.new(data) if !valid_response?(data)
76
77
 
77
78
  if !!data['error']
78
79
  code = data['error']['code']
@@ -93,17 +94,17 @@ module Jimson
93
94
  return false if data.has_key?('error') && data.has_key?('result')
94
95
 
95
96
  if data.has_key?('error')
96
- if !data['error'].is_a?(Hash) || !data['error'].has_key?('code') || !data['error'].has_key?('message')
97
+ if !data['error'].is_a?(Hash) || !data['error'].has_key?('code') || !data['error'].has_key?('message')
97
98
  return false
98
99
  end
99
100
 
100
- if !data['error']['code'].is_a?(Fixnum) || !data['error']['message'].is_a?(String)
101
+ if !data['error']['code'].is_a?(Integer) || !data['error']['message'].is_a?(String)
101
102
  return false
102
103
  end
103
104
  end
104
105
 
105
106
  return true
106
-
107
+
107
108
  rescue
108
109
  return false
109
110
  end
@@ -116,13 +117,13 @@ module Jimson
116
117
  end
117
118
 
118
119
  def send_batch
119
- batch = @batch.map(&:first) # get the requests
120
+ batch = @batch.map(&:first) # get the requests
120
121
  response = send_batch_request(batch)
121
122
 
122
123
  begin
123
124
  responses = MultiJson.decode(response)
124
125
  rescue
125
- raise Client::Error::InvalidJSON.new(json)
126
+ raise Client::Error::InvalidJSON.new(response)
126
127
  end
127
128
 
128
129
  process_batch_response(responses)
@@ -132,14 +133,14 @@ module Jimson
132
133
  end
133
134
 
134
135
  class BatchClient < BlankSlate
135
-
136
+
136
137
  def initialize(helper)
137
138
  @helper = helper
138
139
  end
139
140
 
140
141
  def method_missing(sym, *args, &block)
141
142
  request = Jimson::Request.new(sym.to_s, args)
142
- @helper.push_batch_request(request)
143
+ @helper.push_batch_request(request)
143
144
  end
144
145
 
145
146
  end
@@ -148,7 +149,7 @@ module Jimson
148
149
  reveal :instance_variable_get
149
150
  reveal :inspect
150
151
  reveal :to_s
151
-
152
+
152
153
  def self.batch(client)
153
154
  helper = client.instance_variable_get(:@helper)
154
155
  batch_client = BatchClient.new(helper)
@@ -156,12 +157,13 @@ module Jimson
156
157
  helper.send_batch
157
158
  end
158
159
 
159
- def initialize(url, opts = {}, namespace = nil)
160
- @url, @opts, @namespace = url, opts, namespace
161
- @helper = ClientHelper.new(url, opts, namespace)
160
+ def initialize(url, opts = {}, namespace = nil, client_opts = {})
161
+ @url, @opts, @namespace, @client_opts = url, opts, namespace, client_opts
162
+ @helper = ClientHelper.new(url, opts, namespace, client_opts)
162
163
  end
163
164
 
164
165
  def method_missing(sym, *args, &block)
166
+ args = args.first if args.size == 1 && args.first.is_a?(Hash)
165
167
  @helper.process_call(sym, args)
166
168
  end
167
169
 
@@ -2,8 +2,8 @@ module Jimson
2
2
  class Client
3
3
  module Error
4
4
  class InvalidResponse < StandardError
5
- def initialize()
6
- super('Invalid or empty response from server.')
5
+ def initialize(response = nil)
6
+ super("Invalid or empty response from server:\n#{response.inspect}")
7
7
  end
8
8
  end
9
9
 
data/lib/jimson/router.rb CHANGED
@@ -11,8 +11,8 @@ module Jimson
11
11
  :jimson_methods,
12
12
  :strip_method_namespace
13
13
 
14
- def initialize
15
- @map = Map.new
14
+ def initialize(opts = {})
15
+ @map = Map.new(opts)
16
16
  end
17
17
 
18
18
  def draw(&block)
@@ -7,8 +7,10 @@ module Jimson
7
7
  #
8
8
  class Map
9
9
 
10
- def initialize
10
+ def initialize(opts = {})
11
11
  @routes = {}
12
+ @opts = opts
13
+ @ns_sep = opts[:ns_sep] || '.'
12
14
  end
13
15
 
14
16
  #
@@ -28,7 +30,7 @@ module Jimson
28
30
  @routes[ns.to_s] = handler
29
31
  else
30
32
  # passed a block for nested namespacing
31
- map = Jimson::Router::Map.new
33
+ map = Jimson::Router::Map.new(@opts)
32
34
  @routes[ns.to_s] = map
33
35
  map.instance_eval &block
34
36
  end
@@ -38,11 +40,11 @@ module Jimson
38
40
  # Return the handler for a (possibly namespaced) method name
39
41
  #
40
42
  def handler_for_method(method)
41
- parts = method.split('.')
42
- ns = (method.index('.') == nil ? '' : parts.first)
43
+ parts = method.split(@ns_sep)
44
+ ns = (method.index(@ns_sep) == nil ? '' : parts.first)
43
45
  handler = @routes[ns]
44
46
  if handler.is_a?(Jimson::Router::Map)
45
- return handler.handler_for_method(parts[1..-1].join('.'))
47
+ return handler.handler_for_method(parts[1..-1].join(@ns_sep))
46
48
  end
47
49
  handler
48
50
  end
@@ -51,7 +53,7 @@ module Jimson
51
53
  # Strip off the namespace part of a method and return the bare method name
52
54
  #
53
55
  def strip_method_namespace(method)
54
- method.split('.').last
56
+ method.split(@ns_sep).last
55
57
  end
56
58
 
57
59
  #
@@ -59,7 +61,7 @@ module Jimson
59
61
  #
60
62
  def jimson_methods
61
63
  arr = @routes.keys.map do |ns|
62
- prefix = (ns == '' ? '' : "#{ns}.")
64
+ prefix = (ns == '' ? '' : "#{ns}#{@ns_sep}")
63
65
  handler = @routes[ns]
64
66
  if handler.is_a?(Jimson::Router::Map)
65
67
  handler.jimson_methods
data/lib/jimson/server.rb CHANGED
@@ -27,15 +27,15 @@ module Jimson
27
27
 
28
28
  JSON_RPC_VERSION = '2.0'
29
29
 
30
- attr_accessor :router, :host, :port, :opts
30
+ attr_accessor :router, :host, :port, :show_errors, :opts
31
31
 
32
32
  #
33
33
  # Create a Server with routes defined
34
34
  #
35
- def self.with_routes(&block)
35
+ def self.with_routes(opts = {}, &block)
36
36
  router = Router.new
37
37
  router.send(:draw, &block)
38
- self.new(router)
38
+ self.new(router, opts)
39
39
  end
40
40
 
41
41
  #
@@ -45,6 +45,7 @@ module Jimson
45
45
  # * :host - the hostname or ip to bind to
46
46
  # * :port - the port to listen on
47
47
  # * :server - the rack handler to use, e.g. 'webrick' or 'thin'
48
+ # * :show_errors - true or false, send backtraces in error responses?
48
49
  #
49
50
  # Remaining options are forwarded to the underlying Rack server.
50
51
  #
@@ -61,6 +62,7 @@ module Jimson
61
62
 
62
63
  @host = opts.delete(:host) || '0.0.0.0'
63
64
  @port = opts.delete(:port) || 8999
65
+ @show_errors = opts.delete(:show_errors) || false
64
66
  @opts = opts
65
67
  end
66
68
 
@@ -131,7 +133,7 @@ module Jimson
131
133
  'jsonrpc' => [String],
132
134
  'method' => [String],
133
135
  'params' => [Hash, Array],
134
- 'id' => [String, Fixnum, Bignum, NilClass]
136
+ 'id' => [String, Integer, NilClass]
135
137
  }
136
138
 
137
139
  return false if !request.is_a?(Hash)
@@ -168,7 +170,7 @@ module Jimson
168
170
  rescue ArgumentError
169
171
  raise Server::Error::InvalidParams.new
170
172
  rescue Exception, StandardError => e
171
- raise Server::Error::ApplicationError.new(e)
173
+ raise Server::Error::ApplicationError.new(e, @show_errors)
172
174
  end
173
175
 
174
176
  def dispatch_request(method, params)
@@ -47,8 +47,10 @@ module Jimson
47
47
  end
48
48
 
49
49
  class ApplicationError < Error
50
- def initialize(err)
51
- super(-32099, "Server application error")
50
+ def initialize(err, show_error = false)
51
+ msg = "Server application error"
52
+ msg += ': ' + err.message + ' at ' + err.backtrace.first if show_error
53
+ super(-32099, msg)
52
54
  end
53
55
  end
54
56
 
@@ -0,0 +1,3 @@
1
+ module Jimson
2
+ VERSION = '0.12.0'
3
+ end
data/spec/client_spec.rb CHANGED
@@ -5,8 +5,8 @@ module Jimson
5
5
  BOILERPLATE = {'jsonrpc' => '2.0', 'id' => 1}
6
6
 
7
7
  before(:each) do
8
- @resp_mock = mock('http_response')
9
- ClientHelper.stub!(:make_id).and_return(1)
8
+ @resp_mock = double('http_response')
9
+ ClientHelper.stub(:make_id).and_return(1)
10
10
  end
11
11
 
12
12
  after(:each) do
@@ -36,7 +36,7 @@ module Jimson
36
36
  'id' => 1
37
37
  })
38
38
  response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
39
- RestClient.should_receive(:post).with(SPEC_URL, expected, {:content_type => 'application/json'}).and_return(@resp_mock)
39
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
40
40
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
41
41
  @client[:foo].sum(1, 2, 3).should == 42
42
42
  end
@@ -50,7 +50,7 @@ module Jimson
50
50
  'id' => 1
51
51
  })
52
52
  response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
53
- RestClient.should_receive(:post).with(SPEC_URL, expected, {:content_type => 'application/json'}).and_return(@resp_mock)
53
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
54
54
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
55
55
  @client[:foo][:bar].sum(1, 2, 3).should == 42
56
56
  end
@@ -66,7 +66,7 @@ module Jimson
66
66
  'id' => 1
67
67
  })
68
68
  response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
69
- RestClient.should_receive(:post).with(SPEC_URL, expected, {:content_type => 'application/json'}).and_return(@resp_mock)
69
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
70
70
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
71
71
  @client['foo', 1, 2, 3].should == 42
72
72
  end
@@ -80,7 +80,7 @@ module Jimson
80
80
  'id' => 1
81
81
  })
82
82
  response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
83
- RestClient.should_receive(:post).with(SPEC_URL, expected, {:content_type => 'application/json'}).and_return(@resp_mock)
83
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
84
84
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
85
85
  @client['foo', [1, 2], 3].should == 42
86
86
  end
@@ -100,7 +100,7 @@ module Jimson
100
100
  end
101
101
  it "sends a valid JSON-RPC request and returns the result" do
102
102
  response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
103
- RestClient.should_receive(:post).with(SPEC_URL, @expected, {:content_type => 'application/json'}).and_return(@resp_mock)
103
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: @expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
104
104
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
105
105
  client = Client.new(SPEC_URL)
106
106
  client.foo(1,2,3).should == 42
@@ -108,11 +108,27 @@ module Jimson
108
108
 
109
109
  it "sends a valid JSON-RPC request with custom options" do
110
110
  response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
111
- RestClient.should_receive(:post).with(SPEC_URL, @expected, {:content_type => 'application/json', :timeout => 10000}).and_return(@resp_mock)
111
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: @expected, headers: {:content_type => 'application/json', :timeout => 10000}).and_return(@resp_mock)
112
112
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
113
113
  client = Client.new(SPEC_URL, :timeout => 10000)
114
114
  client.foo(1,2,3).should == 42
115
115
  end
116
+
117
+ it "sends a valid JSON-RPC request with custom content_type" do
118
+ response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
119
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: @expected, headers: {:content_type => 'application/json-rpc', :timeout => 10000}).and_return(@resp_mock)
120
+ @resp_mock.should_receive(:body).at_least(:once).and_return(response)
121
+ client = Client.new(SPEC_URL, :timeout => 10000, :content_type => 'application/json-rpc')
122
+ client.foo(1,2,3).should == 42
123
+ end
124
+
125
+ it "adds RestClient::Request parameters if given" do
126
+ response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
127
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: @expected, headers: {:content_type => 'application/json-rpc', :timeout => 10000}, ssl_ca_file: 'myca.pem').and_return(@resp_mock)
128
+ @resp_mock.should_receive(:body).at_least(:once).and_return(response)
129
+ client = Client.new(SPEC_URL, {:timeout => 10000, :content_type => 'application/json-rpc'}, '', {ssl_ca_file: 'myca.pem'})
130
+ client.foo(1,2,3).should == 42
131
+ end
116
132
  end
117
133
 
118
134
  context "when one of the parameters is an array" do
@@ -124,12 +140,44 @@ module Jimson
124
140
  'id' => 1
125
141
  })
126
142
  response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
127
- RestClient.should_receive(:post).with(SPEC_URL, expected, {:content_type => 'application/json'}).and_return(@resp_mock)
143
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
128
144
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
129
145
  client = Client.new(SPEC_URL)
130
146
  client.foo([1,2],3).should == 42
131
147
  end
132
148
  end
149
+
150
+ context "when one of the parameters is a hash" do
151
+ it "sends a correct JSON-RPC request (array is preserved with hash) and returns the results" do
152
+ expected = MultiJson.encode({
153
+ 'jsonrpc' => '2.0',
154
+ 'method' => 'foo',
155
+ 'params' => [1,{'bar' => 'baz'},3],
156
+ 'id' => 1
157
+ })
158
+ response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
159
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
160
+ @resp_mock.should_receive(:body).at_least(:once).and_return(response)
161
+ client = Client.new(SPEC_URL)
162
+ client.foo(1, {'bar' => 'baz'}, 3).should == 42
163
+ end
164
+ end
165
+
166
+ context "when using named parameters" do
167
+ it "sends a correct JSON-RPC request (named parameters are preserved) and returns the result" do
168
+ expected = MultiJson.encode({
169
+ 'jsonrpc' => '2.0',
170
+ 'method' => 'foo',
171
+ 'params' => {'bar' => 'baz'},
172
+ 'id' => 1
173
+ })
174
+ response = MultiJson.encode(BOILERPLATE.merge({'result' => 42}))
175
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: expected, headers: {:content_type => 'application/json'}).and_return(@resp_mock)
176
+ @resp_mock.should_receive(:body).at_least(:once).and_return(response)
177
+ client = Client.new(SPEC_URL)
178
+ client.foo({'bar' => 'baz'}).should == 42
179
+ end
180
+ end
133
181
  end
134
182
 
135
183
  describe "sending a batch request" do
@@ -138,7 +186,7 @@ module Jimson
138
186
  {"jsonrpc" => "2.0", "method" => "sum", "params" => [1,2,4], "id" => "1"},
139
187
  {"jsonrpc" => "2.0", "method" => "subtract", "params" => [42,23], "id" => "2"},
140
188
  {"jsonrpc" => "2.0", "method" => "foo_get", "params" => [{"name" => "myself"}], "id" => "5"},
141
- {"jsonrpc" => "2.0", "method" => "get_data", "id" => "9"}
189
+ {"jsonrpc" => "2.0", "method" => "get_data", "id" => "9"}
142
190
  ])
143
191
 
144
192
  response = MultiJson.encode([
@@ -148,10 +196,10 @@ module Jimson
148
196
  {"jsonrpc" => "2.0", "result" => ["hello", 5], "id" => "9"}
149
197
  ])
150
198
 
151
- ClientHelper.stub!(:make_id).and_return('1', '2', '5', '9')
152
- RestClient.should_receive(:post).with(SPEC_URL, batch, {:content_type => 'application/json'}).and_return(@resp_mock)
199
+ ClientHelper.stub(:make_id).and_return('1', '2', '5', '9')
200
+ RestClient::Request.should_receive(:execute).with(method: :post, url: SPEC_URL, payload: batch, headers: {:content_type => 'application/json'}, ssl_ca_file: 'myca.pem').and_return(@resp_mock)
153
201
  @resp_mock.should_receive(:body).at_least(:once).and_return(response)
154
- client = Client.new(SPEC_URL)
202
+ client = Client.new(SPEC_URL, {}, '', {ssl_ca_file: 'myca.pem'})
155
203
 
156
204
  sum = subtract = foo = data = nil
157
205
  Jimson::Client.batch(client) do |batch|
@@ -161,14 +209,14 @@ module Jimson
161
209
  data = batch.get_data
162
210
  end
163
211
 
164
- sum.succeeded?.should be_true
165
- sum.is_error?.should be_false
212
+ sum.succeeded?.should be true
213
+ sum.is_error?.should be false
166
214
  sum.result.should == 7
167
215
 
168
216
  subtract.result.should == 19
169
217
 
170
- foo.is_error?.should be_true
171
- foo.succeeded?.should be_false
218
+ foo.is_error?.should be true
219
+ foo.succeeded?.should be false
172
220
  foo.error['code'].should == -32601
173
221
 
174
222
  data.result.should == ['hello', 5]
@@ -179,9 +227,9 @@ module Jimson
179
227
  context "when an error occurs in the Jimson::Client code" do
180
228
  it "tags the raised exception with Jimson::Client::Error" do
181
229
  client_helper = ClientHelper.new(SPEC_URL)
182
- ClientHelper.stub!(:new).and_return(client_helper)
230
+ ClientHelper.stub(:new).and_return(client_helper)
183
231
  client = Client.new(SPEC_URL)
184
- client_helper.stub!(:send_single_request).and_raise "intentional error"
232
+ client_helper.stub(:send_single_request).and_raise "intentional error"
185
233
  lambda { client.foo }.should raise_error(Jimson::Client::Error)
186
234
  end
187
235
  end
data/spec/router_spec.rb CHANGED
@@ -3,7 +3,8 @@ require 'spec_helper'
3
3
  module Jimson
4
4
  describe Router do
5
5
 
6
- let(:router) { Router.new }
6
+ let(:router) { Router.new(opts) }
7
+ let(:opts) { {} }
7
8
 
8
9
  class RouterFooHandler
9
10
  extend Jimson::Handler
@@ -44,7 +45,7 @@ module Jimson
44
45
  end
45
46
 
46
47
  context 'when given nested namespaces' do
47
- it 'takes a block with a DSL to set the root and namespaces' do
48
+ before {
48
49
  router.draw do
49
50
  root RouterFooHandler
50
51
  namespace 'ns1' do
@@ -52,22 +53,43 @@ module Jimson
52
53
  namespace 'ns2', RouterBarHandler
53
54
  end
54
55
  end
55
-
56
- router.handler_for_method('hi').should be_a(RouterFooHandler)
57
- router.handler_for_method('ns1.hi').should be_a(RouterBazHandler)
58
- router.handler_for_method('ns1.ns2.hi').should be_a(RouterBarHandler)
56
+ }
57
+ context 'default ns_sep' do
58
+ it 'takes a block with a DSL to set the root and namespaces' do
59
+ router.handler_for_method('hi').should be_a(RouterFooHandler)
60
+ router.handler_for_method('ns1.hi').should be_a(RouterBazHandler)
61
+ router.handler_for_method('ns1.ns2.hi').should be_a(RouterBarHandler)
62
+ end
63
+ end
64
+ context 'custom ns_sep' do
65
+ let(:opts) { {ns_sep: '::'} }
66
+ it 'takes a block with a DSL to set the root and namespaces' do
67
+ router.handler_for_method('hi').should be_a(RouterFooHandler)
68
+ router.handler_for_method('ns1::hi').should be_a(RouterBazHandler)
69
+ router.handler_for_method('ns1::ns2::hi').should be_a(RouterBarHandler)
70
+ end
59
71
  end
72
+
60
73
  end
61
74
  end
62
75
 
63
76
  describe '#jimson_methods' do
64
- it 'returns an array of namespaced method names from all registered handlers' do
77
+ before {
65
78
  router.draw do
66
79
  root RouterFooHandler
67
80
  namespace 'foo', RouterBarHandler
68
81
  end
69
-
70
- router.jimson_methods.sort.should == ['hi', 'foo.bye'].sort
82
+ }
83
+ context 'default ns_sep' do
84
+ it 'returns an array of namespaced method names from all registered handlers' do
85
+ router.jimson_methods.sort.should == ['hi', 'foo.bye'].sort
86
+ end
87
+ end
88
+ context 'custom ns_sep' do
89
+ let(:opts) { {ns_sep: '::'} }
90
+ it 'returns an array of namespaced method names from all registered handlers' do
91
+ router.jimson_methods.sort.should == ['hi', 'foo::bye'].sort
92
+ end
71
93
  end
72
94
  end
73
95
 
data/spec/server_spec.rb CHANGED
@@ -118,7 +118,7 @@ module Jimson
118
118
  }
119
119
  end
120
120
 
121
- it "handles bignums" do
121
+ it "handles integer" do
122
122
  req = {
123
123
  'jsonrpc' => '2.0',
124
124
  'method' => 'subtract',
@@ -239,23 +239,51 @@ module Jimson
239
239
  end
240
240
 
241
241
  describe "receiving a call for ugly method" do
242
- it "returns only global error without stack trace" do
243
- req = {
244
- 'jsonrpc' => '2.0',
245
- 'method' => 'ugly_method',
246
- 'id' => 1
247
- }
248
- post_json(req)
242
+ context "by default" do
243
+ it "returns only global error without stack trace" do
244
+ req = {
245
+ 'jsonrpc' => '2.0',
246
+ 'method' => 'ugly_method',
247
+ 'id' => 1
248
+ }
249
+ post_json(req)
249
250
 
250
- resp = MultiJson.decode(last_response.body)
251
- resp.should == {
252
- 'jsonrpc' => '2.0',
253
- 'error' => {
254
- 'code' => -32099,
255
- 'message' => 'Server application error'
256
- },
257
- 'id' => 1
258
- }
251
+ resp = MultiJson.decode(last_response.body)
252
+ resp.should == {
253
+ 'jsonrpc' => '2.0',
254
+ 'error' => {
255
+ 'code' => -32099,
256
+ 'message' => 'Server application error'
257
+ },
258
+ 'id' => 1
259
+ }
260
+ end
261
+ end
262
+
263
+ context "with 'show_errors' enabled" do
264
+ it "returns an error name and first line of the stack trace" do
265
+ req = {
266
+ 'jsonrpc' => '2.0',
267
+ 'method' => 'ugly_method',
268
+ 'id' => 1
269
+ }
270
+
271
+ app = Server.new(router, :environment => "production", :show_errors => true)
272
+
273
+ # have to make a new Rack::Test browser since this server is different than the normal one
274
+ browser = Rack::Test::Session.new(Rack::MockSession.new(app))
275
+ browser.post '/', MultiJson.encode(req), {'Content-Type' => 'application/json'}
276
+
277
+ resp = MultiJson.decode(browser.last_response.body)
278
+ resp.should == {
279
+ 'jsonrpc' => '2.0',
280
+ 'error' => {
281
+ 'code' => -32099,
282
+ 'message' => "Server application error: RuntimeError at #{__FILE__}:40:in `ugly_method'"
283
+ },
284
+ 'id' => 1
285
+ }
286
+ end
259
287
  end
260
288
  end
261
289
 
@@ -422,6 +450,17 @@ module Jimson
422
450
  'id' => 1
423
451
  }
424
452
  end
453
+
454
+ context "when opts are given" do
455
+ it "passes the opts to the new server" do
456
+ app = Server.with_routes(:show_errors => true) do
457
+ root TestHandler.new
458
+ namespace 'foo', OtherHandler.new
459
+ end
460
+
461
+ app.show_errors.should be true
462
+ end
463
+ end
425
464
  end
426
465
  end
427
466
  end
metadata CHANGED
@@ -1,134 +1,194 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jimson
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
5
- prerelease:
4
+ version: 0.12.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Chris Kite
9
- autorequire:
8
+ - Gilbert
9
+ - Bodo Tasche
10
+ autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2012-08-17 00:00:00.000000000 Z
13
+ date: 2021-05-05 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: blankslate
16
17
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 2.1.2.3
21
+ version: 3.1.3
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
25
  requirements:
27
- - - ! '>='
26
+ - - ">="
28
27
  - !ruby/object:Gem::Version
29
- version: 2.1.2.3
28
+ version: 3.1.3
30
29
  - !ruby/object:Gem::Dependency
31
30
  name: rest-client
32
31
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
32
  requirements:
35
- - - ! '>='
33
+ - - ">="
36
34
  - !ruby/object:Gem::Version
37
- version: 1.6.3
35
+ version: 1.7.3
38
36
  type: :runtime
39
37
  prerelease: false
40
38
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
39
  requirements:
43
- - - ! '>='
40
+ - - ">="
44
41
  - !ruby/object:Gem::Version
45
- version: 1.6.3
42
+ version: 1.7.3
46
43
  - !ruby/object:Gem::Dependency
47
44
  name: multi_json
48
45
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
46
  requirements:
51
- - - ~>
47
+ - - ">="
52
48
  - !ruby/object:Gem::Version
53
- version: 1.1.0
49
+ version: 1.11.2
54
50
  type: :runtime
55
51
  prerelease: false
56
52
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
53
  requirements:
59
- - - ~>
54
+ - - ">="
60
55
  - !ruby/object:Gem::Version
61
- version: 1.1.0
56
+ version: 1.11.2
62
57
  - !ruby/object:Gem::Dependency
63
58
  name: rack
64
59
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
60
  requirements:
67
- - - ! '>='
61
+ - - ">="
68
62
  - !ruby/object:Gem::Version
69
- version: '1.3'
63
+ version: 1.4.5
70
64
  type: :runtime
71
65
  prerelease: false
72
66
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
67
  requirements:
75
- - - ! '>='
68
+ - - ">="
76
69
  - !ruby/object:Gem::Version
77
- version: '1.3'
78
- description:
79
- email:
70
+ version: 1.4.5
71
+ - !ruby/object:Gem::Dependency
72
+ name: rspec
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '2.14'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 2.14.1
81
+ type: :development
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '2.14'
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 2.14.1
91
+ - !ruby/object:Gem::Dependency
92
+ name: rack-test
93
+ requirement: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ type: :development
99
+ prerelease: false
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ - !ruby/object:Gem::Dependency
106
+ name: rake
107
+ requirement: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ - !ruby/object:Gem::Dependency
120
+ name: rdoc
121
+ requirement: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '4.2'
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: 4.2.2
129
+ type: :development
130
+ prerelease: false
131
+ version_requirements: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '4.2'
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: 4.2.2
139
+ description:
140
+ email:
80
141
  executables: []
81
142
  extensions: []
82
143
  extra_rdoc_files:
83
144
  - README.md
84
145
  files:
85
- - VERSION
146
+ - CHANGELOG.md
86
147
  - LICENSE.txt
87
- - CHANGELOG.rdoc
88
148
  - README.md
89
149
  - Rakefile
150
+ - lib/jimson.rb
151
+ - lib/jimson/client.rb
152
+ - lib/jimson/client/error.rb
153
+ - lib/jimson/handler.rb
90
154
  - lib/jimson/request.rb
91
- - lib/jimson/router.rb
92
155
  - lib/jimson/response.rb
156
+ - lib/jimson/router.rb
93
157
  - lib/jimson/router/map.rb
94
158
  - lib/jimson/server.rb
95
- - lib/jimson/client/error.rb
96
- - lib/jimson/client.rb
97
- - lib/jimson/handler.rb
98
159
  - lib/jimson/server/error.rb
99
- - lib/jimson.rb
100
- - spec/spec_helper.rb
101
- - spec/router_spec.rb
160
+ - lib/jimson/version.rb
102
161
  - spec/client_spec.rb
103
162
  - spec/handler_spec.rb
163
+ - spec/router_spec.rb
104
164
  - spec/server_spec.rb
105
- homepage: http://www.github.com/chriskite/jimson
106
- licenses: []
107
- post_install_message:
165
+ - spec/spec_helper.rb
166
+ homepage: https://github.com/bitboxer/jimson.git
167
+ licenses:
168
+ - MIT
169
+ metadata: {}
170
+ post_install_message:
108
171
  rdoc_options: []
109
172
  require_paths:
110
173
  - lib
111
174
  required_ruby_version: !ruby/object:Gem::Requirement
112
- none: false
113
175
  requirements:
114
- - - ! '>='
176
+ - - ">="
115
177
  - !ruby/object:Gem::Version
116
178
  version: '0'
117
179
  required_rubygems_version: !ruby/object:Gem::Requirement
118
- none: false
119
180
  requirements:
120
- - - ! '>='
181
+ - - ">="
121
182
  - !ruby/object:Gem::Version
122
183
  version: '0'
123
184
  requirements: []
124
- rubyforge_project:
125
- rubygems_version: 1.8.21
126
- signing_key:
127
- specification_version: 3
185
+ rubygems_version: 3.1.2
186
+ signing_key:
187
+ specification_version: 4
128
188
  summary: JSON-RPC 2.0 client and server
129
189
  test_files:
130
- - spec/spec_helper.rb
131
190
  - spec/router_spec.rb
132
191
  - spec/client_spec.rb
133
192
  - spec/handler_spec.rb
193
+ - spec/spec_helper.rb
134
194
  - spec/server_spec.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.8.0