jsonrpc2 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/test.yml +26 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +42 -0
- data/Dockerfile +8 -0
- data/README.markdown +36 -56
- data/bin/run-example +7 -0
- data/bin/setup +3 -0
- data/bin/test +7 -0
- data/example/config.ru +27 -25
- data/{bin → exe}/jsonrpc2 +0 -0
- data/jsonrpc2.gemspec +15 -3
- data/lib/jsonrpc2/html.rb +3 -3
- data/lib/jsonrpc2/interface.rb +319 -289
- data/lib/jsonrpc2/textile.rb +5 -5
- data/lib/jsonrpc2/types.rb +14 -10
- data/lib/jsonrpc2/version.rb +1 -1
- data/spec/lib/interface_spec.rb +208 -0
- data/spec/spec_helper.rb +94 -0
- metadata +133 -39
data/lib/jsonrpc2/textile.rb
CHANGED
@@ -8,11 +8,11 @@ module JSONRPC2
|
|
8
8
|
return nil if @about.nil? or @about.empty?
|
9
9
|
str = ""
|
10
10
|
|
11
|
-
|
11
|
+
if @title
|
12
12
|
str << "h1. #{@title}\n"
|
13
13
|
else
|
14
14
|
str << "h1. #{name}\n"
|
15
|
-
|
15
|
+
end
|
16
16
|
|
17
17
|
if @introduction
|
18
18
|
str << "\nh2. Introduction\n\n#{@introduction}\n"
|
@@ -41,7 +41,7 @@ module JSONRPC2
|
|
41
41
|
if section[:summary]
|
42
42
|
str << "\n#{section[:summary]}\n"
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
str += to_textile_group(section).to_s
|
46
46
|
end
|
47
47
|
|
@@ -70,7 +70,7 @@ module JSONRPC2
|
|
70
70
|
|
71
71
|
if res = info[:returns]
|
72
72
|
str << "\n\nh5. Result\n"
|
73
|
-
str << "\n* @#{res[:type]}@"
|
73
|
+
str << "\n* @#{res[:type]}@"
|
74
74
|
str << " - #{res[:desc]}" if res[:desc]
|
75
75
|
str << "\n"
|
76
76
|
else
|
@@ -128,7 +128,7 @@ module JSONRPC2
|
|
128
128
|
return nil if list.empty?
|
129
129
|
|
130
130
|
str = ''
|
131
|
-
|
131
|
+
|
132
132
|
list.sort_by { |info| info[:index] }.each do |info|
|
133
133
|
str << method_to_textile(info)
|
134
134
|
end
|
data/lib/jsonrpc2/types.rb
CHANGED
@@ -16,6 +16,9 @@ module JSONRPC2
|
|
16
16
|
# * Value (or Any or void) - Any value of any type
|
17
17
|
# * CustomType - A defined custom object type
|
18
18
|
module Types
|
19
|
+
class InvalidParamsError < ArgumentError; end
|
20
|
+
class InvalidResultError < RuntimeError; end
|
21
|
+
|
19
22
|
module_function
|
20
23
|
DateTimeRegex = %r"([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"
|
21
24
|
DateRegex = %r'\A\d{4}-\d{2}-\d{2}\z'
|
@@ -76,7 +79,7 @@ module JSONRPC2
|
|
76
79
|
end
|
77
80
|
|
78
81
|
# Checks that param hash is valid for API call
|
79
|
-
#
|
82
|
+
#
|
80
83
|
# @param [Interface] interface API class
|
81
84
|
# @param [String] method Method name
|
82
85
|
# @param [Hash] data params hash to check
|
@@ -92,23 +95,23 @@ module JSONRPC2
|
|
92
95
|
return true
|
93
96
|
end
|
94
97
|
|
95
|
-
raise "Params should not be nil" if data.nil?
|
98
|
+
raise InvalidParamsError, "Params should not be nil" if data.nil?
|
96
99
|
|
97
100
|
extra_keys = data.keys - param_names
|
98
101
|
unless extra_keys.empty?
|
99
|
-
raise "Extra parameters #{extra_keys.inspect} for #{method}."
|
102
|
+
raise InvalidParamsError, "Extra parameters #{extra_keys.inspect} for #{method}."
|
100
103
|
end
|
101
104
|
|
102
105
|
params.each do |param|
|
103
106
|
if data.has_key?(param[:name])
|
104
107
|
value = data[param[:name].to_s]
|
105
108
|
unless valid?(interface, param[:type], value)
|
106
|
-
raise "'#{param[:name]}' should be of type #{param[:type]}, was #{value.class.name}"
|
109
|
+
raise InvalidParamsError, "'#{param[:name]}' should be of type #{param[:type]}, was #{value.class.name}"
|
107
110
|
end
|
108
111
|
elsif ! param[:required]
|
109
112
|
next true
|
110
113
|
else
|
111
|
-
raise "Missing parameter: '#{param[:name]}' of type #{param[:type]} for #{method}"
|
114
|
+
raise InvalidParamsError, "Missing parameter: '#{param[:name]}' of type #{param[:type]} for #{method}"
|
112
115
|
end
|
113
116
|
end
|
114
117
|
end
|
@@ -122,11 +125,12 @@ module JSONRPC2
|
|
122
125
|
def valid_result?(interface, method, value)
|
123
126
|
about = interface.about[method.to_s]
|
124
127
|
return true if about.nil? # Undefined
|
125
|
-
if about[:returns].nil?
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
128
|
+
return value.nil? if about[:returns].nil?
|
129
|
+
return true if valid?(interface, about[:returns][:type], value)
|
130
|
+
|
131
|
+
raise InvalidResultError, <<~MSG.chomp
|
132
|
+
Invalid return type: should have been #{about[:returns][:type]}, was #{value.class.name}
|
133
|
+
MSG
|
130
134
|
end
|
131
135
|
end
|
132
136
|
|
data/lib/jsonrpc2/version.rb
CHANGED
@@ -0,0 +1,208 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'base64'
|
5
|
+
require 'logger'
|
6
|
+
require 'jsonrpc2/interface'
|
7
|
+
require 'jsonrpc2/auth'
|
8
|
+
|
9
|
+
RSpec.describe JSONRPC2::Interface do
|
10
|
+
let(:instance) { rpc_api_class.new(initialization_params) }
|
11
|
+
let(:basic_auth_credentials) { 'user:valid_password' }
|
12
|
+
let(:initialization_params) { { 'HTTP_AUTHORIZATION' => "Basic #{Base64.encode64(basic_auth_credentials)}" } }
|
13
|
+
let(:rpc_api_class) do
|
14
|
+
Class.new(described_class) do
|
15
|
+
auth_with JSONRPC2::BasicAuth.new('user' => 'valid_password')
|
16
|
+
|
17
|
+
param 'name', 'String', 'name'
|
18
|
+
result 'String', 'A tailored greeting'
|
19
|
+
def hello
|
20
|
+
raise 'He-Must-Not-Be-Named' if params['name'] == 'Voldemort'
|
21
|
+
return 42 if params['name'] == 'Marvin'
|
22
|
+
|
23
|
+
"Hello, #{params['name']}!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#rack_dispatch' do
|
29
|
+
subject(:dispatch_result) { instance.rack_dispatch(rpc_request_data) }
|
30
|
+
|
31
|
+
let(:rpc_request_data) { { 'id' => 123, 'method' => 'hello', 'jsonrpc' => '2.0' } }
|
32
|
+
let(:response_status) { dispatch_result[0] }
|
33
|
+
let(:response_body) { dispatch_result[2][0] }
|
34
|
+
let(:parsed_response_body) { JSON.parse(response_body, symbolize_names: true) }
|
35
|
+
|
36
|
+
context 'with empty input' do
|
37
|
+
let(:rpc_request_data) { {} }
|
38
|
+
|
39
|
+
it 'returns the "Invalid request" error' do
|
40
|
+
expect(parsed_response_body[:error]).to eq(
|
41
|
+
code: -32600,
|
42
|
+
message: 'Invalid request',
|
43
|
+
data: nil
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with invalid credentials' do
|
49
|
+
let(:basic_auth_credentials) { 'user:invalid_password' }
|
50
|
+
it 'returns the authorization error' do
|
51
|
+
expect(response_status).to eq(401)
|
52
|
+
expect(response_body).to include('Authentication Required')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with no params' do
|
57
|
+
it 'returns the "Params should not be nil" error' do
|
58
|
+
expect(parsed_response_body[:error]).to eq(
|
59
|
+
code: -32602,
|
60
|
+
message: 'Invalid params - Params should not be nil',
|
61
|
+
data: {}
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with a missing param' do
|
67
|
+
let(:rpc_request_data) { super().merge('params' => {}) }
|
68
|
+
|
69
|
+
it 'returns a helpful param error' do
|
70
|
+
expect(parsed_response_body[:error]).to eq(
|
71
|
+
code: -32602,
|
72
|
+
message: 'Invalid params - Missing parameter: \'name\' of type String for hello',
|
73
|
+
data: {}
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with a mismatched type of param' do
|
79
|
+
let(:rpc_request_data) { super().merge('params' => { 'name' => true }) }
|
80
|
+
|
81
|
+
it 'returns the helpful param error' do
|
82
|
+
expect(parsed_response_body[:error]).to eq(
|
83
|
+
code: -32602,
|
84
|
+
message: 'Invalid params - \'name\' should be of type String, was TrueClass',
|
85
|
+
data: {}
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'with a valid param' do
|
91
|
+
let(:rpc_request_data) { super().merge('params' => params) }
|
92
|
+
let(:params) { { 'name' => 'Geoff' } }
|
93
|
+
|
94
|
+
it 'returns the valid response' do
|
95
|
+
expect(parsed_response_body[:result]).to eq('Hello, Geoff!')
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'with an extra param' do
|
99
|
+
let(:params) { super().merge('extra' => 'I should not be here') }
|
100
|
+
|
101
|
+
it 'returns the helpful param error' do
|
102
|
+
expect(parsed_response_body[:error]).to eq(
|
103
|
+
code: -32602,
|
104
|
+
message: 'Invalid params - Extra parameters ["extra"] for hello.',
|
105
|
+
data: {}
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'with an invalid result type' do
|
111
|
+
let(:params) { { 'name' => 'Marvin' } }
|
112
|
+
|
113
|
+
it 'informs about the server error' do
|
114
|
+
expect(parsed_response_body[:error]).to match(
|
115
|
+
code: -32000,
|
116
|
+
message: 'An error occurred. Check logs for details',
|
117
|
+
data: {}
|
118
|
+
)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'with a correctly configured before_validation hook' do
|
123
|
+
before do
|
124
|
+
rpc_api_class.class_eval do
|
125
|
+
attr_reader :test_before_validation_data
|
126
|
+
|
127
|
+
def before_validation(method:, id:, params:)
|
128
|
+
@test_before_validation_data = {
|
129
|
+
method: method,
|
130
|
+
id: id,
|
131
|
+
params: params
|
132
|
+
}
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'invokes the hook' do
|
138
|
+
dispatch_result
|
139
|
+
|
140
|
+
expect(instance.test_before_validation_data[:method]).to eq('hello')
|
141
|
+
expect(instance.test_before_validation_data[:id]).to eq(123)
|
142
|
+
expect(instance.test_before_validation_data[:params]).to eq({ 'name' => 'Geoff' })
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'with an unhandled server error' do
|
148
|
+
let(:rpc_request_data) { super().merge('params' => { 'name' => 'Voldemort' }) }
|
149
|
+
|
150
|
+
it 'informs about the server error' do
|
151
|
+
expect(parsed_response_body[:error]).to match(
|
152
|
+
code: -32000,
|
153
|
+
message: 'An error occurred. Check logs for details',
|
154
|
+
data: {}
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'with a correctly configured error hook' do
|
159
|
+
before do
|
160
|
+
rpc_api_class.class_eval do
|
161
|
+
attr_reader :test_error_data
|
162
|
+
|
163
|
+
def on_server_error(request_id:, error:)
|
164
|
+
@test_error_data = {
|
165
|
+
request_id: request_id,
|
166
|
+
error: error
|
167
|
+
}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'invokes the hook' do
|
173
|
+
dispatch_result
|
174
|
+
|
175
|
+
expect(instance.test_error_data[:error].message).to eq('He-Must-Not-Be-Named')
|
176
|
+
expect(instance.test_error_data[:request_id]).to eq(nil) # Request_id is generated higher in the stack
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'with error hook raising an error' do
|
181
|
+
let(:initialization_params) { super().merge('rack.logger' => rack_logger) }
|
182
|
+
let(:rack_logger) { instance_double(::Logger, :rack_logger, info: nil, error: nil) }
|
183
|
+
|
184
|
+
before do
|
185
|
+
rpc_api_class.class_eval do
|
186
|
+
def on_server_error(request_id:, error:)
|
187
|
+
raise "Whoops, my bad!"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'informs about the server error' do
|
193
|
+
expect(parsed_response_body[:error]).to match(
|
194
|
+
code: -32000,
|
195
|
+
message: 'An error occurred. Check logs for details',
|
196
|
+
data: {}
|
197
|
+
)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'logs the error' do
|
201
|
+
expect(rack_logger).to receive(:error).with(/Whoops, my bad!/)
|
202
|
+
|
203
|
+
dispatch_result
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause
|
4
|
+
# this file to always be loaded, without a need to explicitly require it in any
|
5
|
+
# files.
|
6
|
+
#
|
7
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
8
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
9
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
10
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
11
|
+
# a separate helper file that requires the additional dependencies and performs
|
12
|
+
# the additional setup, and require it from the spec files that actually need
|
13
|
+
# it.
|
14
|
+
#
|
15
|
+
# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
16
|
+
RSpec.configure do |config|
|
17
|
+
# rspec-expectations config goes here. You can use an alternate
|
18
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
19
|
+
# assertions if you prefer.
|
20
|
+
config.expect_with :rspec do |expectations|
|
21
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
22
|
+
# and `failure_message` of custom matchers include text for helper methods
|
23
|
+
# defined using `chain`, e.g.:
|
24
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
25
|
+
# # => "be bigger than 2 and smaller than 4"
|
26
|
+
# ...rather than:
|
27
|
+
# # => "be bigger than 2"
|
28
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
29
|
+
end
|
30
|
+
|
31
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
32
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
33
|
+
config.mock_with :rspec do |mocks|
|
34
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
35
|
+
# a real object. This is generally recommended, and will default to
|
36
|
+
# `true` in RSpec 4.
|
37
|
+
mocks.verify_partial_doubles = true
|
38
|
+
end
|
39
|
+
|
40
|
+
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
|
41
|
+
# have no way to turn it off -- the option exists only for backwards
|
42
|
+
# compatibility in RSpec 3). It causes shared context metadata to be
|
43
|
+
# inherited by the metadata hash of host groups and examples, rather than
|
44
|
+
# triggering implicit auto-inclusion in groups with matching metadata.
|
45
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
46
|
+
|
47
|
+
# This allows you to limit a spec run to individual examples or groups
|
48
|
+
# you care about by tagging them with `:focus` metadata. When nothing
|
49
|
+
# is tagged with `:focus`, all examples get run. RSpec also provides
|
50
|
+
# aliases for `it`, `describe`, and `context` that include `:focus`
|
51
|
+
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
|
52
|
+
config.filter_run_when_matching :focus
|
53
|
+
|
54
|
+
# Allows RSpec to persist some state between runs in order to support
|
55
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
56
|
+
# you configure your source control system to ignore this file.
|
57
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
58
|
+
|
59
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
60
|
+
# recommended. For more details, see:
|
61
|
+
# https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode
|
62
|
+
config.disable_monkey_patching!
|
63
|
+
|
64
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
65
|
+
# be too noisy due to issues in dependencies.
|
66
|
+
config.warnings = true
|
67
|
+
|
68
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
69
|
+
# file, and it's useful to allow more verbose output when running an
|
70
|
+
# individual spec file.
|
71
|
+
if config.files_to_run.one?
|
72
|
+
# Use the documentation formatter for detailed output,
|
73
|
+
# unless a formatter has already been configured
|
74
|
+
# (e.g. via a command-line flag).
|
75
|
+
config.default_formatter = "doc"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Print the 10 slowest examples and example groups at the
|
79
|
+
# end of the spec run, to help surface which specs are running
|
80
|
+
# particularly slow.
|
81
|
+
# config.profile_examples = 10
|
82
|
+
|
83
|
+
# Run specs in random order to surface order dependencies. If you find an
|
84
|
+
# order dependency and want to debug it, you can fix the order by providing
|
85
|
+
# the seed, which is printed after each run.
|
86
|
+
# --seed 1234
|
87
|
+
config.order = :random
|
88
|
+
|
89
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
90
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
91
|
+
# test failures related to randomization by passing the same `--seed` value
|
92
|
+
# as the one that triggered the failure.
|
93
|
+
Kernel.srand config.seed
|
94
|
+
end
|
metadata
CHANGED
@@ -1,85 +1,164 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonrpc2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Geoff Youngs
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: RedCloth
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: thor
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: puma
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry-byebug
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: |+
|
126
|
+
== Description
|
127
|
+
|
128
|
+
A Rack compatible JSON-RPC2 server domain specific language (DSL) - allows JSONRPC APIs to be
|
129
|
+
defined as mountable Rack applications with inline documentation, authentication and type checking.
|
130
|
+
|
131
|
+
e.g.
|
132
|
+
|
133
|
+
class Calculator < JSONRPC2::Interface
|
134
|
+
title "JSON-RPC2 Calculator"
|
135
|
+
introduction "This interface allows basic maths calculations via JSON-RPC2"
|
136
|
+
auth_with JSONRPC2::BasicAuth.new({'user' => 'secretword'})
|
137
|
+
|
138
|
+
section 'Simple Ops' do
|
139
|
+
desc 'Multiply two numbers'
|
140
|
+
param 'a', 'Number', 'a'
|
141
|
+
param 'b', 'Number', 'b'
|
142
|
+
result 'Number', 'a * b'
|
143
|
+
def mul args
|
144
|
+
args['a'] * args['b']
|
145
|
+
end
|
146
|
+
|
147
|
+
desc 'Add numbers'
|
148
|
+
example "Calculate 1 + 1 = 2", :params => { 'a' => 1, 'b' => 1}, :result => 2
|
149
|
+
|
150
|
+
param 'a', 'Number', 'First number'
|
151
|
+
param 'b', 'Number', 'Second number'
|
152
|
+
optional 'c', 'Number', 'Third number'
|
153
|
+
result 'Number', 'a + b + c'
|
154
|
+
def sum args
|
155
|
+
val = args['a'] + args['b']
|
156
|
+
val += args['c'] if args['c']
|
157
|
+
val
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
83
162
|
email:
|
84
163
|
- git@intersect-uk.co.uk
|
85
164
|
executables:
|
@@ -87,12 +166,19 @@ executables:
|
|
87
166
|
extensions: []
|
88
167
|
extra_rdoc_files: []
|
89
168
|
files:
|
90
|
-
- .
|
169
|
+
- ".github/workflows/test.yml"
|
170
|
+
- ".gitignore"
|
171
|
+
- ".rspec"
|
172
|
+
- CHANGELOG.md
|
173
|
+
- Dockerfile
|
91
174
|
- Gemfile
|
92
175
|
- README.markdown
|
93
176
|
- Rakefile
|
94
|
-
- bin/
|
177
|
+
- bin/run-example
|
178
|
+
- bin/setup
|
179
|
+
- bin/test
|
95
180
|
- example/config.ru
|
181
|
+
- exe/jsonrpc2
|
96
182
|
- jsonrpc2.gemspec
|
97
183
|
- lib/assets/css/bootstrap.css
|
98
184
|
- lib/assets/css/bootstrap.min.css
|
@@ -110,28 +196,36 @@ files:
|
|
110
196
|
- lib/jsonrpc2/textile.rb
|
111
197
|
- lib/jsonrpc2/types.rb
|
112
198
|
- lib/jsonrpc2/version.rb
|
199
|
+
- spec/lib/interface_spec.rb
|
200
|
+
- spec/spec_helper.rb
|
113
201
|
- test/test_types.rb
|
114
|
-
homepage: http://github.com/
|
202
|
+
homepage: http://github.com/livelink/jsonrpc2
|
115
203
|
licenses: []
|
116
|
-
metadata:
|
117
|
-
|
204
|
+
metadata:
|
205
|
+
bug_tracker_uri: https://github.com/livelink/jsonrpc2/issues
|
206
|
+
changelog_uri: https://github.com/livelink/jsonrpc2/blob/master/CHANGELOG.md
|
207
|
+
documentation_uri: https://github.com/livelink/jsonrpc2#inline-documentation
|
208
|
+
post_install_message:
|
118
209
|
rdoc_options: []
|
119
210
|
require_paths:
|
120
211
|
- lib
|
121
212
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
213
|
requirements:
|
123
|
-
- -
|
214
|
+
- - ">="
|
124
215
|
- !ruby/object:Gem::Version
|
125
216
|
version: '0'
|
126
217
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
218
|
requirements:
|
128
|
-
- -
|
219
|
+
- - ">="
|
129
220
|
- !ruby/object:Gem::Version
|
130
221
|
version: '0'
|
131
222
|
requirements: []
|
132
|
-
|
133
|
-
|
134
|
-
signing_key:
|
223
|
+
rubygems_version: 3.1.4
|
224
|
+
signing_key:
|
135
225
|
specification_version: 4
|
136
226
|
summary: JSON-RPC2 server DSL
|
137
|
-
test_files:
|
227
|
+
test_files:
|
228
|
+
- spec/lib/interface_spec.rb
|
229
|
+
- spec/spec_helper.rb
|
230
|
+
- test/test_types.rb
|
231
|
+
...
|