jimson-reloaded 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: 398634f92c8530750c7a6fe8966e2dbb6dec17a3999d5ea97c83b3481f610c0b
4
+ data.tar.gz: dda0d5e556736f80f2e8702510aa5302717dd0708fed75388b15179dd62fea21
5
+ SHA512:
6
+ metadata.gz: ac184436f5551653a2709a3a18826e6e85ee62d26ef842faf45afde95823c5c68fc4b44035124e9273c1317e6e75c394cb8c578b074d3c6c795b9ac0cffb3a11
7
+ data.tar.gz: db750df41bff5e0bc2e0e41160ed358c2f4cf77ea27c5386cba0a21838149a6111ad4ed4cb567e276d146736069f8176736dd3704ed89eea42384f1d87b82ed3
data/CHANGELOG.md ADDED
@@ -0,0 +1,109 @@
1
+ # 0.12.0 /
2
+
3
+ * Unified Bignum and Fixnum to Integer
4
+ * Add ability to specify custom content type
5
+ * Add data returned to invalid response exception
6
+ * Add support for named parameters
7
+ * Add Router :ns_sep option for custom namespace
8
+ * Fix json variable name on invalid json response
9
+ * made it possible to overwrite advanced RestClient values, like ssl_ca_file
10
+
11
+ # 0.11.0 / 2016-03-13
12
+
13
+ * Minor enhancements
14
+
15
+ * Update dependency versions for Ruby 2.*
16
+ * Remove Gemfile.lock
17
+
18
+ # 0.10.0 / 2013-06-28
19
+
20
+ * Minor enhancements
21
+
22
+ * Update dependency versions
23
+
24
+ # 0.9.1 / 2012-09-18
25
+
26
+ * Bug fixes
27
+
28
+ * Allow opts to be passed to Server.with_routes
29
+
30
+ # 0.9.0 / 2012-08-22
31
+
32
+ * Minor enhancements
33
+
34
+ * Add show_errors option to server, which will cause application errors to include the error name and the first line of the backtrace
35
+
36
+ # 0.8.0 / 2012-08-17
37
+
38
+ * Major enhancements
39
+
40
+ * Add namespaced method calls to client (e.g. 'client[:foo].sum(1,2,3) # calls foo.sum')
41
+ * Add Server.with_routes to quickly created a routed server
42
+
43
+ # 0.7.1 / 2012-08-16
44
+
45
+ * Bug fixes
46
+
47
+ * Fix handling of array params in client, which were erroneously being flattened
48
+
49
+ # 0.7.0 / 2012-04-13
50
+
51
+ * Major enhancements
52
+
53
+ * Add namespaced routing
54
+
55
+ * Bug fixes
56
+
57
+ * Fix deprecation warning about RDoc task in Rakefile
58
+
59
+ # 0.6.0 / 2012-03-14
60
+
61
+ * Minor enhancements
62
+
63
+ * Add ability to pass options to Rack and RestClient
64
+
65
+ # 0.5.0 / 2012-03-06
66
+
67
+ * Major enhancements
68
+
69
+ * Switch to MultiJson from json gem
70
+
71
+ * Bug fixes
72
+
73
+ * Allow BigNum in 'id' field of request and response
74
+
75
+ # 0.3.1 / 2011-08-11
76
+
77
+ * Minor enhancements
78
+
79
+ * Refactor the way the server is intantiated/started to work better with config.ru
80
+
81
+ # 0.3.0 / 2011-08-11
82
+
83
+ * Major enhancements
84
+
85
+ * Replace eventmachine-httpserver with rack for more cross-platform goodness
86
+
87
+ # 0.2.3 / 2011-08-01
88
+
89
+ * Bug fixes
90
+
91
+ * Fix argument error in client error handling
92
+
93
+ # 0.2.2 / 2011-07-28
94
+
95
+ * Bug fixes
96
+
97
+ * Fix invalid local variable error in client error handling
98
+
99
+ # 0.2.1 / 2011-07-27
100
+
101
+ * Bug fixes
102
+
103
+ * Fix error in client handling some errors caused by errant 'new' keyword
104
+
105
+ # 0.2.0 / 2011-07-20
106
+
107
+ * Major enhancements
108
+
109
+ * Replace patron with rest-client for JRuby compatibility in the client
data/LICENSE.txt ADDED
@@ -0,0 +1,17 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2
+ of this software and associated documentation files (the "Software"), to deal
3
+ in the Software without restriction, including without limitation the rights
4
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5
+ copies of the Software, and to permit persons to whom the Software is
6
+ furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in
9
+ all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ 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
17
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Jimson-Reloaded
2
+
3
+ This is a fork of [chriskite/jimson](https://github.com/chriskite/jimson). I merged all open PRs of the original unmaintaned gem and will maintain it as `jimson-reloaded`. PRs are welcome 🤗.
4
+
5
+ ### JSON-RPC 2.0 Client and Server for Ruby
6
+
7
+ [![Build Status](https://github.com/railslove/jimson/actions/workflows/ruby.yml/badge.svg?branch=main)](https://github.com/railslove/jimson/actions/workflows/ruby.yml)
8
+
9
+ ## Client: Quick Start
10
+
11
+ ```ruby
12
+ require 'jimson-reloaded'
13
+ client = Jimson::Client.new("http://www.example.com:8999") # the URL for the JSON-RPC 2.0 server to connect to
14
+ result = client.sum(1,2) # call the 'sum' method on the RPC server and save the result '3'
15
+ ```
16
+
17
+ ## Server: Quick Start
18
+
19
+ ```ruby
20
+ require 'jimson-reloaded'
21
+
22
+ class MyHandler
23
+ extend Jimson::Handler
24
+
25
+ def sum(a,b)
26
+ a + b
27
+ end
28
+ end
29
+
30
+ server = Jimson::Server.new(MyHandler.new)
31
+ server.start # serve with webrick on http://0.0.0.0:8999/
32
+ ```
33
+
34
+ ## JSON Engine
35
+
36
+ Jimson uses multi\_json, so you can load the JSON library of your choice in your application and Jimson will use it automatically.
37
+
38
+ For example, require the 'json' gem in your application:
39
+
40
+ ```ruby
41
+ require 'json'
42
+ ```
43
+
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/lib/')
2
+ require 'jimson/version'
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'rspec/core/rake_task'
6
+
7
+ gem 'rubygems-tasks', '~> 0.2'
8
+ require 'rubygems/tasks'
9
+
10
+ Gem::Tasks.new
11
+
12
+ desc "Run all specs"
13
+ RSpec::Core::RakeTask.new(:rspec) do |spec|
14
+ spec.pattern = 'spec/**/*_spec.rb'
15
+ end
16
+
17
+ task :default => :rspec
18
+
19
+ require 'rdoc/task'
20
+
21
+ Rake::RDocTask.new do |rdoc|
22
+ rdoc.rdoc_dir = 'rdoc'
23
+ rdoc.title = "jimson #{Jimson::VERSION}"
24
+ rdoc.rdoc_files.include('README*')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'jimson/handler'
3
+ require 'jimson/router'
4
+ require 'jimson/server'
5
+ require 'jimson/client'
6
+
7
+ module Jimson
8
+ end
@@ -0,0 +1,182 @@
1
+ require 'blankslate'
2
+ require 'multi_json'
3
+ require 'rest-client'
4
+ require 'jimson/request'
5
+ require 'jimson/response'
6
+
7
+ module Jimson
8
+ class ClientHelper
9
+ JSON_RPC_VERSION = '2.0'
10
+
11
+ def self.make_id
12
+ rand(10**12)
13
+ end
14
+
15
+ def initialize(url, opts = {}, namespace = nil, client_opts = {})
16
+ @url = url
17
+ URI.parse(@url) # for the sake of validating the url
18
+ @batch = []
19
+ @opts = opts
20
+ @namespace = namespace
21
+ @opts[:content_type] ||= 'application/json'
22
+ @client_opts = client_opts
23
+ end
24
+
25
+ def process_call(sym, args)
26
+ resp = send_single_request(sym.to_s, args)
27
+
28
+ begin
29
+ data = MultiJson.decode(resp)
30
+ rescue
31
+ raise Client::Error::InvalidJSON.new(resp)
32
+ end
33
+
34
+ return process_single_response(data)
35
+
36
+ rescue Exception, StandardError => e
37
+ e.extend(Client::Error) unless e.is_a?(Client::Error)
38
+ raise e
39
+ end
40
+
41
+ def send_single_request(method, args)
42
+ namespaced_method = @namespace.nil? ? method : "#@namespace#{method}"
43
+ post_data = MultiJson.encode({
44
+ 'jsonrpc' => JSON_RPC_VERSION,
45
+ 'method' => namespaced_method,
46
+ 'params' => args,
47
+ 'id' => self.class.make_id
48
+ })
49
+ resp = RestClient::Request.execute(@client_opts.merge(:method => :post, :url => @url, :payload => post_data, :headers => @opts))
50
+ if resp.nil? || resp.body.nil? || resp.body.empty?
51
+ raise Client::Error::InvalidResponse.new(resp)
52
+ end
53
+
54
+ return resp.body
55
+ end
56
+
57
+ def send_batch_request(batch)
58
+ post_data = MultiJson.encode(batch)
59
+ resp = RestClient::Request.execute(@client_opts.merge(:method => :post, :url => @url, :payload => post_data, :headers => @opts))
60
+ if resp.nil? || resp.body.nil? || resp.body.empty?
61
+ raise Client::Error::InvalidResponse.new(resp)
62
+ end
63
+
64
+ return resp.body
65
+ end
66
+
67
+ def process_batch_response(responses)
68
+ responses.each do |resp|
69
+ saved_response = @batch.map { |r| r[1] }.select { |r| r.id == resp['id'] }.first
70
+ raise Client::Error::InvalidResponse.new if saved_response.nil?
71
+ saved_response.populate!(resp)
72
+ end
73
+ end
74
+
75
+ def process_single_response(data)
76
+ raise Client::Error::InvalidResponse.new(data) if !valid_response?(data)
77
+
78
+ if !!data['error']
79
+ code = data['error']['code']
80
+ msg = data['error']['message']
81
+ raise Client::Error::ServerError.new(code, msg)
82
+ end
83
+
84
+ return data['result']
85
+ end
86
+
87
+ def valid_response?(data)
88
+ return false if !data.is_a?(Hash)
89
+
90
+ return false if data['jsonrpc'] != JSON_RPC_VERSION
91
+
92
+ return false if !data.has_key?('id')
93
+
94
+ return false if data.has_key?('error') && data.has_key?('result')
95
+
96
+ if data.has_key?('error')
97
+ if !data['error'].is_a?(Hash) || !data['error'].has_key?('code') || !data['error'].has_key?('message')
98
+ return false
99
+ end
100
+
101
+ if !data['error']['code'].is_a?(Integer) || !data['error']['message'].is_a?(String)
102
+ return false
103
+ end
104
+ end
105
+
106
+ return true
107
+
108
+ rescue
109
+ return false
110
+ end
111
+
112
+ def push_batch_request(request)
113
+ request.id = self.class.make_id
114
+ response = Response.new(request.id)
115
+ @batch << [request, response]
116
+ return response
117
+ end
118
+
119
+ def send_batch
120
+ batch = @batch.map(&:first) # get the requests
121
+ response = send_batch_request(batch)
122
+
123
+ begin
124
+ responses = MultiJson.decode(response)
125
+ rescue
126
+ raise Client::Error::InvalidJSON.new(response)
127
+ end
128
+
129
+ process_batch_response(responses)
130
+ @batch = []
131
+ end
132
+
133
+ end
134
+
135
+ class BatchClient < BlankSlate
136
+
137
+ def initialize(helper)
138
+ @helper = helper
139
+ end
140
+
141
+ def method_missing(sym, *args, &block)
142
+ request = Jimson::Request.new(sym.to_s, args)
143
+ @helper.push_batch_request(request)
144
+ end
145
+
146
+ end
147
+
148
+ class Client < BlankSlate
149
+ reveal :instance_variable_get
150
+ reveal :inspect
151
+ reveal :to_s
152
+
153
+ def self.batch(client)
154
+ helper = client.instance_variable_get(:@helper)
155
+ batch_client = BatchClient.new(helper)
156
+ yield batch_client
157
+ helper.send_batch
158
+ end
159
+
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)
163
+ end
164
+
165
+ def method_missing(sym, *args, &block)
166
+ args = args.first if args.size == 1 && args.first.is_a?(Hash)
167
+ @helper.process_call(sym, args)
168
+ end
169
+
170
+ def [](method, *args)
171
+ if method.is_a?(Symbol)
172
+ # namespace requested
173
+ new_ns = @namespace.nil? ? "#{method}." : "#@namespace#{method}."
174
+ return Client.new(@url, @opts, new_ns)
175
+ end
176
+ @helper.process_call(method, args)
177
+ end
178
+
179
+ end
180
+ end
181
+
182
+ require 'jimson/client/error'
@@ -0,0 +1,23 @@
1
+ module Jimson
2
+ class Client
3
+ module Error
4
+ class InvalidResponse < StandardError
5
+ def initialize(response = nil)
6
+ super("Invalid or empty response from server:\n#{response.inspect}")
7
+ end
8
+ end
9
+
10
+ class InvalidJSON < StandardError
11
+ def initialize(json)
12
+ super("Couldn't parse JSON string received from server:\n#{json}")
13
+ end
14
+ end
15
+
16
+ class ServerError < StandardError
17
+ def initialize(code, message)
18
+ super("Server error #{code}: #{message}")
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module Jimson
2
+ module Handler
3
+
4
+ def jimson_default_methods
5
+ self.instance_methods.map(&:to_s) - Object.methods.map(&:to_s)
6
+ end
7
+
8
+ def jimson_expose(*methods)
9
+ @jimson_exposed_methods ||= []
10
+ @jimson_exposed_methods += methods.map(&:to_s)
11
+ end
12
+
13
+ def jimson_exclude(*methods)
14
+ @jimson_excluded_methods ||= []
15
+ @jimson_excluded_methods += methods.map(&:to_s)
16
+ end
17
+
18
+ def jimson_exposed_methods
19
+ @jimson_exposed_methods ||= []
20
+ @jimson_excluded_methods ||= []
21
+ (jimson_default_methods - @jimson_excluded_methods + @jimson_exposed_methods).sort
22
+ end
23
+
24
+ end
25
+ end