jsonrpc-middleware 0.6.0 → 0.7.0
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.
- checksums.yaml +4 -4
- data/.aiignore +6 -1
- data/.claude/agents/entire-search.md +25 -0
- data/.claude/agents/rbs-specialist.md +89 -0
- data/.claude/settings.json +84 -0
- data/.devcontainer/devcontainer.json +17 -0
- data/.dockerignore +16 -0
- data/.entire/.gitignore +5 -0
- data/.entire/settings.json +4 -0
- data/.rubocop.yml +26 -1
- data/.tool-versions +1 -1
- data/.yard-lint.yml +283 -0
- data/AGENTS.md +142 -0
- data/CHANGELOG.md +19 -0
- data/CLAUDE.md +2 -113
- data/Dockerfile +144 -0
- data/README.md +9 -17
- data/Rakefile +62 -11
- data/examples/procedures.rb +3 -1
- data/examples/rack/Gemfile.lock +4 -4
- data/examples/rack-echo/Gemfile.lock +4 -4
- data/examples/rails/Gemfile.lock +12 -5
- data/examples/rails/config/initializers/jsonrpc.rb +1 -1
- data/examples/rails-routing-dsl/config.ru +5 -5
- data/examples/rails-single-file/config.ru +1 -1
- data/examples/rails-single-file-routing/config.ru +1 -1
- data/examples/sinatra-classic/Gemfile.lock +11 -4
- data/examples/sinatra-modular/Gemfile.lock +11 -4
- data/lib/jsonrpc/batch_request.rb +8 -11
- data/lib/jsonrpc/batch_response.rb +6 -8
- data/lib/jsonrpc/configuration.rb +30 -4
- data/lib/jsonrpc/error.rb +7 -8
- data/lib/jsonrpc/errors/internal_error.rb +2 -0
- data/lib/jsonrpc/errors/invalid_params_error.rb +2 -0
- data/lib/jsonrpc/errors/invalid_request_error.rb +2 -0
- data/lib/jsonrpc/errors/method_not_found_error.rb +2 -0
- data/lib/jsonrpc/errors/parse_error.rb +2 -0
- data/lib/jsonrpc/helpers.rb +6 -0
- data/lib/jsonrpc/middleware.rb +12 -11
- data/lib/jsonrpc/notification.rb +7 -8
- data/lib/jsonrpc/parser.rb +13 -12
- data/lib/jsonrpc/railtie/batch_constraint.rb +1 -0
- data/lib/jsonrpc/railtie/mapper_extension.rb +2 -2
- data/lib/jsonrpc/railtie/method_constraint.rb +9 -0
- data/lib/jsonrpc/railtie/routes_dsl.rb +10 -15
- data/lib/jsonrpc/railtie.rb +2 -0
- data/lib/jsonrpc/response.rb +2 -2
- data/lib/jsonrpc/types.rb +1 -1
- data/lib/jsonrpc/validator.rb +14 -4
- data/lib/jsonrpc/version.rb +1 -1
- data/lib/jsonrpc.rb +3 -0
- data/rbs_collection.lock.yaml +476 -0
- data/rbs_collection.yaml +21 -0
- data/sig/jsonrpc/batch_request.rbs +17 -0
- data/sig/jsonrpc/batch_response.rbs +17 -0
- data/sig/jsonrpc/configuration.rbs +18 -0
- data/sig/jsonrpc/error.rbs +17 -0
- data/sig/jsonrpc/errors/internal_error.rbs +5 -0
- data/sig/jsonrpc/errors/invalid_params_error.rbs +5 -0
- data/sig/jsonrpc/errors/invalid_request_error.rbs +5 -0
- data/sig/jsonrpc/errors/method_not_found_error.rbs +5 -0
- data/sig/jsonrpc/errors/parse_error.rbs +5 -0
- data/sig/jsonrpc/middleware.rbs +20 -3
- data/sig/jsonrpc/notification.rbs +15 -0
- data/sig/jsonrpc/parser.rbs +7 -1
- data/sig/jsonrpc/request.rbs +18 -0
- data/sig/jsonrpc/response.rbs +19 -0
- data/sig/jsonrpc/validator.rbs +8 -0
- data/sig/jsonrpc.rbs +3 -156
- data/sig/multi_json.rbs +17 -0
- data/sig/type_definitions.rbs +11 -0
- data/sig/zeitwerk.rbs +10 -0
- metadata +34 -12
- data/.claude/commands/document.md +0 -105
- data/.claude/commands/gemfile/update.md +0 -52
- data/.claude/commands/test.md +0 -561
- data/.claude/docs/yard.md +0 -602
- data/.claude/settings.local.json +0 -15
- data/.yardstick.yml +0 -22
data/examples/rails/Gemfile.lock
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ../..
|
|
3
3
|
specs:
|
|
4
|
-
jsonrpc-middleware (0.
|
|
4
|
+
jsonrpc-middleware (0.6.0)
|
|
5
5
|
dry-struct (~> 1.8)
|
|
6
6
|
dry-validation (~> 1.11)
|
|
7
|
-
multi_json (~> 1.
|
|
7
|
+
multi_json (~> 1.20)
|
|
8
8
|
zeitwerk (~> 2.7)
|
|
9
9
|
|
|
10
10
|
GEM
|
|
@@ -156,8 +156,11 @@ GEM
|
|
|
156
156
|
net-smtp
|
|
157
157
|
marcel (1.0.4)
|
|
158
158
|
mini_mime (1.1.5)
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
mini_portile2 (2.8.9)
|
|
160
|
+
minitest (6.0.2)
|
|
161
|
+
drb (~> 2.0)
|
|
162
|
+
prism (~> 1.5)
|
|
163
|
+
multi_json (1.21.1)
|
|
161
164
|
net-imap (0.5.9)
|
|
162
165
|
date
|
|
163
166
|
net-protocol
|
|
@@ -168,11 +171,15 @@ GEM
|
|
|
168
171
|
net-smtp (0.5.1)
|
|
169
172
|
net-protocol
|
|
170
173
|
nio4r (2.7.4)
|
|
174
|
+
nokogiri (1.18.8)
|
|
175
|
+
mini_portile2 (~> 2.8.2)
|
|
176
|
+
racc (~> 1.4)
|
|
171
177
|
nokogiri (1.18.8-arm64-darwin)
|
|
172
178
|
racc (~> 1.4)
|
|
173
179
|
pp (0.6.2)
|
|
174
180
|
prettyprint
|
|
175
181
|
prettyprint (0.2.0)
|
|
182
|
+
prism (1.9.0)
|
|
176
183
|
psych (5.2.6)
|
|
177
184
|
date
|
|
178
185
|
stringio
|
|
@@ -246,4 +253,4 @@ DEPENDENCIES
|
|
|
246
253
|
rails (~> 8.0.2)
|
|
247
254
|
|
|
248
255
|
BUNDLED WITH
|
|
249
|
-
|
|
256
|
+
4.0.8
|
|
@@ -65,7 +65,7 @@ class App < Rails::Application
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# Controller for main system operations
|
|
68
|
-
class MainController <
|
|
68
|
+
class MainController < ApplicationController
|
|
69
69
|
def on
|
|
70
70
|
render jsonrpc: { device: 'main_system', status: 'on' }
|
|
71
71
|
end
|
|
@@ -76,7 +76,7 @@ class MainController < ActionController::Base
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Controller for lights operations
|
|
79
|
-
class LightsController <
|
|
79
|
+
class LightsController < ApplicationController
|
|
80
80
|
def on
|
|
81
81
|
render jsonrpc: { device: 'lights', status: 'on' }
|
|
82
82
|
end
|
|
@@ -87,7 +87,7 @@ class LightsController < ActionController::Base
|
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
# Controller for climate operations
|
|
90
|
-
class ClimateController <
|
|
90
|
+
class ClimateController < ApplicationController
|
|
91
91
|
def on
|
|
92
92
|
render jsonrpc: { device: 'climate_system', status: 'on' }
|
|
93
93
|
end
|
|
@@ -98,7 +98,7 @@ class ClimateController < ActionController::Base
|
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
# Controller for climate fan operations
|
|
101
|
-
class FanController <
|
|
101
|
+
class FanController < ApplicationController
|
|
102
102
|
def on
|
|
103
103
|
render jsonrpc: { device: 'fan', status: 'on' }
|
|
104
104
|
end
|
|
@@ -109,7 +109,7 @@ class FanController < ActionController::Base
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
# Controller for batch operations
|
|
112
|
-
class BatchController <
|
|
112
|
+
class BatchController < ApplicationController
|
|
113
113
|
def handle
|
|
114
114
|
# Process each request in the batch and collect results
|
|
115
115
|
results = jsonrpc_batch.process_each do |request_or_notification|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ../..
|
|
3
3
|
specs:
|
|
4
|
-
jsonrpc-middleware (0.
|
|
4
|
+
jsonrpc-middleware (0.6.0)
|
|
5
|
+
dry-struct (~> 1.8)
|
|
5
6
|
dry-validation (~> 1.11)
|
|
6
|
-
multi_json (~> 1.
|
|
7
|
+
multi_json (~> 1.20)
|
|
7
8
|
zeitwerk (~> 2.7)
|
|
8
9
|
|
|
9
10
|
GEM
|
|
@@ -34,6 +35,11 @@ GEM
|
|
|
34
35
|
dry-logic (~> 1.5)
|
|
35
36
|
dry-types (~> 1.8)
|
|
36
37
|
zeitwerk (~> 2.6)
|
|
38
|
+
dry-struct (1.8.0)
|
|
39
|
+
dry-core (~> 1.1)
|
|
40
|
+
dry-types (~> 1.8, >= 1.8.2)
|
|
41
|
+
ice_nine (~> 0.11)
|
|
42
|
+
zeitwerk (~> 2.6)
|
|
37
43
|
dry-types (1.8.3)
|
|
38
44
|
bigdecimal (~> 3.0)
|
|
39
45
|
concurrent-ruby (~> 1.0)
|
|
@@ -47,8 +53,9 @@ GEM
|
|
|
47
53
|
dry-initializer (~> 3.2)
|
|
48
54
|
dry-schema (~> 1.14)
|
|
49
55
|
zeitwerk (~> 2.6)
|
|
56
|
+
ice_nine (0.11.2)
|
|
50
57
|
logger (1.7.0)
|
|
51
|
-
multi_json (1.
|
|
58
|
+
multi_json (1.21.1)
|
|
52
59
|
mustermann (3.0.3)
|
|
53
60
|
ruby2_keywords (~> 0.0.1)
|
|
54
61
|
nio4r (2.7.4)
|
|
@@ -93,4 +100,4 @@ DEPENDENCIES
|
|
|
93
100
|
sinatra-contrib
|
|
94
101
|
|
|
95
102
|
BUNDLED WITH
|
|
96
|
-
|
|
103
|
+
4.0.8
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ../..
|
|
3
3
|
specs:
|
|
4
|
-
jsonrpc-middleware (0.
|
|
4
|
+
jsonrpc-middleware (0.6.0)
|
|
5
|
+
dry-struct (~> 1.8)
|
|
5
6
|
dry-validation (~> 1.11)
|
|
6
|
-
multi_json (~> 1.
|
|
7
|
+
multi_json (~> 1.20)
|
|
7
8
|
zeitwerk (~> 2.7)
|
|
8
9
|
|
|
9
10
|
GEM
|
|
@@ -34,6 +35,11 @@ GEM
|
|
|
34
35
|
dry-logic (~> 1.5)
|
|
35
36
|
dry-types (~> 1.8)
|
|
36
37
|
zeitwerk (~> 2.6)
|
|
38
|
+
dry-struct (1.8.0)
|
|
39
|
+
dry-core (~> 1.1)
|
|
40
|
+
dry-types (~> 1.8, >= 1.8.2)
|
|
41
|
+
ice_nine (~> 0.11)
|
|
42
|
+
zeitwerk (~> 2.6)
|
|
37
43
|
dry-types (1.8.3)
|
|
38
44
|
bigdecimal (~> 3.0)
|
|
39
45
|
concurrent-ruby (~> 1.0)
|
|
@@ -47,8 +53,9 @@ GEM
|
|
|
47
53
|
dry-initializer (~> 3.2)
|
|
48
54
|
dry-schema (~> 1.14)
|
|
49
55
|
zeitwerk (~> 2.6)
|
|
56
|
+
ice_nine (0.11.2)
|
|
50
57
|
logger (1.7.0)
|
|
51
|
-
multi_json (1.
|
|
58
|
+
multi_json (1.21.1)
|
|
52
59
|
mustermann (3.0.3)
|
|
53
60
|
ruby2_keywords (~> 0.0.1)
|
|
54
61
|
nio4r (2.7.4)
|
|
@@ -93,4 +100,4 @@ DEPENDENCIES
|
|
|
93
100
|
sinatra-contrib
|
|
94
101
|
|
|
95
102
|
BUNDLED WITH
|
|
96
|
-
|
|
103
|
+
4.0.8
|
|
@@ -6,6 +6,8 @@ module JSONRPC
|
|
|
6
6
|
# A batch request is an Array filled with Request objects to send several requests at once.
|
|
7
7
|
# The Server should respond with an Array containing the corresponding Response objects.
|
|
8
8
|
#
|
|
9
|
+
# @api public
|
|
10
|
+
#
|
|
9
11
|
# @example Create a batch request with multiple requests
|
|
10
12
|
# batch = JSONRPC::BatchRequest.new([
|
|
11
13
|
# JSONRPC::Request.new(method: "sum", params: [1, 2, 4], id: "1"),
|
|
@@ -39,14 +41,13 @@ module JSONRPC
|
|
|
39
41
|
# ]
|
|
40
42
|
# batch = JSONRPC::BatchRequest.new(requests)
|
|
41
43
|
#
|
|
42
|
-
# @param requests [Array<JSONRPC::Request, JSONRPC::Notification, JSONRPC::Error>] an array of request objects
|
|
43
|
-
# or errors
|
|
44
44
|
# @raise [ArgumentError] if requests is not an Array
|
|
45
|
-
#
|
|
46
45
|
# @raise [ArgumentError] if requests is empty
|
|
47
|
-
#
|
|
48
46
|
# @raise [ArgumentError] if any request is not a valid Request, Notification, or Error
|
|
49
47
|
#
|
|
48
|
+
# @param requests [Array<JSONRPC::Request, JSONRPC::Notification, JSONRPC::Error>] an array of request objects
|
|
49
|
+
# or errors
|
|
50
|
+
#
|
|
50
51
|
def initialize(requests)
|
|
51
52
|
validate_requests(requests)
|
|
52
53
|
@requests = requests
|
|
@@ -109,9 +110,7 @@ module JSONRPC
|
|
|
109
110
|
#
|
|
110
111
|
# @return [Integer] the number of requests in the batch
|
|
111
112
|
#
|
|
112
|
-
def size
|
|
113
|
-
requests.size
|
|
114
|
-
end
|
|
113
|
+
def size = requests.size
|
|
115
114
|
|
|
116
115
|
# Alias for size method providing Array-like interface
|
|
117
116
|
#
|
|
@@ -162,14 +161,12 @@ module JSONRPC
|
|
|
162
161
|
#
|
|
163
162
|
# @api private
|
|
164
163
|
#
|
|
165
|
-
# @param requests [Array] the array of requests
|
|
166
|
-
#
|
|
167
164
|
# @raise [ArgumentError] if requests is not an Array
|
|
168
|
-
#
|
|
169
165
|
# @raise [ArgumentError] if requests is empty
|
|
170
|
-
#
|
|
171
166
|
# @raise [ArgumentError] if any request is not a valid Request, Notification, or Error
|
|
172
167
|
#
|
|
168
|
+
# @param requests [Array] the array of requests
|
|
169
|
+
#
|
|
173
170
|
# @return [void]
|
|
174
171
|
#
|
|
175
172
|
def validate_requests(requests)
|
|
@@ -7,6 +7,8 @@ module JSONRPC
|
|
|
7
7
|
# a Batch Request. The Server should respond with one Response for each Request
|
|
8
8
|
# (except for Notifications which don't receive responses).
|
|
9
9
|
#
|
|
10
|
+
# @api public
|
|
11
|
+
#
|
|
10
12
|
# @example Create a batch response
|
|
11
13
|
# batch = JSONRPC::BatchResponse.new([
|
|
12
14
|
# JSONRPC::Response.new(result: 7, id: "1"),
|
|
@@ -39,14 +41,12 @@ module JSONRPC
|
|
|
39
41
|
# ]
|
|
40
42
|
# batch = JSONRPC::BatchResponse.new(responses)
|
|
41
43
|
#
|
|
42
|
-
# @param responses [Array<JSONRPC::Response>] an array of response objects
|
|
43
|
-
#
|
|
44
44
|
# @raise [ArgumentError] if responses is not an Array
|
|
45
|
-
#
|
|
46
45
|
# @raise [ArgumentError] if responses is empty
|
|
47
|
-
#
|
|
48
46
|
# @raise [ArgumentError] if any response is not a valid Response
|
|
49
47
|
#
|
|
48
|
+
# @param responses [Array<JSONRPC::Response>] an array of response objects
|
|
49
|
+
#
|
|
50
50
|
def initialize(responses)
|
|
51
51
|
validate_responses(responses)
|
|
52
52
|
@responses = responses
|
|
@@ -119,14 +119,12 @@ module JSONRPC
|
|
|
119
119
|
#
|
|
120
120
|
# @api private
|
|
121
121
|
#
|
|
122
|
-
# @param responses [Array] the array of responses
|
|
123
|
-
#
|
|
124
122
|
# @raise [ArgumentError] if responses is not an Array
|
|
125
|
-
#
|
|
126
123
|
# @raise [ArgumentError] if responses is empty
|
|
127
|
-
#
|
|
128
124
|
# @raise [ArgumentError] if any response is not a valid Response
|
|
129
125
|
#
|
|
126
|
+
# @param responses [Array] the array of responses
|
|
127
|
+
#
|
|
130
128
|
# @return [void]
|
|
131
129
|
#
|
|
132
130
|
def validate_responses(responses)
|
|
@@ -20,32 +20,52 @@ module JSONRPC
|
|
|
20
20
|
#
|
|
21
21
|
# @api public
|
|
22
22
|
#
|
|
23
|
-
# @!
|
|
23
|
+
# @!attribute [r] allow_positional_arguments
|
|
24
24
|
# Indicates if the procedure accepts positional arguments
|
|
25
|
+
#
|
|
25
26
|
# @api public
|
|
26
27
|
#
|
|
27
28
|
# @example
|
|
28
29
|
# procedure.allow_positional_arguments # => true
|
|
30
|
+
#
|
|
29
31
|
# @return [Boolean] whether the procedure accepts positional arguments
|
|
30
32
|
#
|
|
31
|
-
# @!
|
|
33
|
+
# @!attribute [r] contract
|
|
32
34
|
# The validation contract for procedure parameters
|
|
35
|
+
#
|
|
33
36
|
# @api public
|
|
34
37
|
#
|
|
35
38
|
# @example
|
|
36
39
|
# procedure.contract # => #<Dry::Validation::Contract...>
|
|
40
|
+
#
|
|
37
41
|
# @return [Dry::Validation::Contract] the validation contract for procedure parameters
|
|
38
42
|
#
|
|
39
|
-
# @!
|
|
43
|
+
# @!attribute [r] parameter_name
|
|
40
44
|
# The name of the first parameter in the contract schema
|
|
45
|
+
#
|
|
41
46
|
# @api public
|
|
42
47
|
#
|
|
43
48
|
# @example
|
|
44
49
|
# procedure.parameter_name # => :numbers
|
|
50
|
+
#
|
|
45
51
|
# @return [Symbol, nil] the name of the first parameter in the contract schema
|
|
46
52
|
#
|
|
47
53
|
Procedure = Data.define(:allow_positional_arguments, :contract, :parameter_name)
|
|
48
54
|
|
|
55
|
+
# The logger instance used for error and diagnostic output
|
|
56
|
+
#
|
|
57
|
+
# @api public
|
|
58
|
+
#
|
|
59
|
+
# @example Using the default logger
|
|
60
|
+
# config.logger # => #<Logger:...>
|
|
61
|
+
#
|
|
62
|
+
# @example Setting a custom logger
|
|
63
|
+
# config.logger = Logger.new('log/jsonrpc.log')
|
|
64
|
+
#
|
|
65
|
+
# @return [Logger] the logger instance
|
|
66
|
+
#
|
|
67
|
+
attr_accessor :logger
|
|
68
|
+
|
|
49
69
|
# Whether to log detailed internal error information in the terminal
|
|
50
70
|
#
|
|
51
71
|
# @api public
|
|
@@ -108,6 +128,8 @@ module JSONRPC
|
|
|
108
128
|
# @example
|
|
109
129
|
# config.json_adapter = :oj
|
|
110
130
|
#
|
|
131
|
+
# @param adapter [Symbol, nil] the JSON adapter to use
|
|
132
|
+
#
|
|
111
133
|
# @return [Symbol, nil] the JSON adapter to use
|
|
112
134
|
#
|
|
113
135
|
def json_adapter=(adapter)
|
|
@@ -127,6 +149,7 @@ module JSONRPC
|
|
|
127
149
|
# render_internal_errors: true
|
|
128
150
|
# )
|
|
129
151
|
#
|
|
152
|
+
# @param logger [Logger] the logger instance for error and diagnostic output
|
|
130
153
|
# @param log_internal_errors [Boolean] whether to log detailed internal error information in the terminal
|
|
131
154
|
# @param log_request_validation_errors [Boolean] whether to log validation errors during JSON-RPC request processing
|
|
132
155
|
# @param rescue_internal_errors [Boolean] whether internal errors should be rescued and converted to JSON-RPC errors
|
|
@@ -136,6 +159,7 @@ module JSONRPC
|
|
|
136
159
|
# @return [Configuration] a new configuration instance
|
|
137
160
|
#
|
|
138
161
|
def initialize(
|
|
162
|
+
logger: Logger.new($stdout, progname: 'JSONRPC'),
|
|
139
163
|
log_internal_errors: true,
|
|
140
164
|
log_request_validation_errors: false,
|
|
141
165
|
rescue_internal_errors: true,
|
|
@@ -143,6 +167,7 @@ module JSONRPC
|
|
|
143
167
|
validate_procedure_signatures: true
|
|
144
168
|
)
|
|
145
169
|
@procedures = {}
|
|
170
|
+
@logger = logger
|
|
146
171
|
@log_internal_errors = log_internal_errors
|
|
147
172
|
@log_request_validation_errors = log_request_validation_errors
|
|
148
173
|
@rescue_internal_errors = rescue_internal_errors
|
|
@@ -180,8 +205,9 @@ module JSONRPC
|
|
|
180
205
|
#
|
|
181
206
|
# @param method_name [String, Symbol] the name of the procedure
|
|
182
207
|
# @param allow_positional_arguments [Boolean] whether the procedure accepts positional arguments
|
|
208
|
+
# @param block [Proc, nil] an optional block that defines the validation contract using Dry::Validation DSL
|
|
183
209
|
#
|
|
184
|
-
# @yield
|
|
210
|
+
# @yield A block that defines the validation contract using Dry::Validation DSL
|
|
185
211
|
#
|
|
186
212
|
# @return [Procedure] the registered procedure
|
|
187
213
|
#
|
data/lib/jsonrpc/error.rb
CHANGED
|
@@ -82,15 +82,14 @@ module JSONRPC
|
|
|
82
82
|
# @example Create an error with additional data
|
|
83
83
|
# error = JSONRPC::Error.new("Invalid params", code: -32602, data: { "field" => "missing" })
|
|
84
84
|
#
|
|
85
|
+
# @raise [ArgumentError] if code is not an Integer
|
|
86
|
+
# @raise [ArgumentError] if message is not a String
|
|
87
|
+
#
|
|
85
88
|
# @param message [String] short description of the error
|
|
86
89
|
# @param code [Integer] a number indicating the error type
|
|
87
90
|
# @param data [Hash, Array, String, Number, Boolean, nil] additional error information
|
|
88
91
|
# @param request_id [String, Integer, nil] the request identifier
|
|
89
92
|
#
|
|
90
|
-
# @raise [ArgumentError] if code is not an Integer
|
|
91
|
-
#
|
|
92
|
-
# @raise [ArgumentError] if message is not a String
|
|
93
|
-
#
|
|
94
93
|
def initialize(message, code:, data: nil, request_id: nil)
|
|
95
94
|
super(message)
|
|
96
95
|
|
|
@@ -150,10 +149,10 @@ module JSONRPC
|
|
|
150
149
|
#
|
|
151
150
|
# @api private
|
|
152
151
|
#
|
|
153
|
-
# @param code [Integer] the error code
|
|
154
|
-
#
|
|
155
152
|
# @raise [ArgumentError] if code is not an Integer
|
|
156
153
|
#
|
|
154
|
+
# @param code [Integer] the error code
|
|
155
|
+
#
|
|
157
156
|
# @return [void]
|
|
158
157
|
#
|
|
159
158
|
def validate_code(code)
|
|
@@ -164,10 +163,10 @@ module JSONRPC
|
|
|
164
163
|
#
|
|
165
164
|
# @api private
|
|
166
165
|
#
|
|
167
|
-
# @param message [String] the error message
|
|
168
|
-
#
|
|
169
166
|
# @raise [ArgumentError] if message is not a String
|
|
170
167
|
#
|
|
168
|
+
# @param message [String] the error message
|
|
169
|
+
#
|
|
171
170
|
# @return [void]
|
|
172
171
|
#
|
|
173
172
|
def validate_message(message)
|
|
@@ -6,6 +6,8 @@ module JSONRPC
|
|
|
6
6
|
# Raised when invalid JSON was received by the server.
|
|
7
7
|
# An error occurred on the server while parsing the JSON text.
|
|
8
8
|
#
|
|
9
|
+
# @api public
|
|
10
|
+
#
|
|
9
11
|
# @example Create a parse error
|
|
10
12
|
# error = JSONRPC::ParseError.new(data: { details: "Unexpected end of input" })
|
|
11
13
|
#
|
data/lib/jsonrpc/helpers.rb
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module JSONRPC
|
|
4
4
|
# Framework-agnostic helpers for JSON-RPC
|
|
5
|
+
#
|
|
6
|
+
# @api public
|
|
7
|
+
#
|
|
5
8
|
module Helpers
|
|
6
9
|
# Extends the including class with ClassMethods when module is included
|
|
7
10
|
#
|
|
@@ -21,6 +24,9 @@ module JSONRPC
|
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
# Class methods for registering JSON-RPC procedure handlers
|
|
27
|
+
#
|
|
28
|
+
# @api public
|
|
29
|
+
#
|
|
24
30
|
module ClassMethods
|
|
25
31
|
# Registers a JSON-RPC procedure with the given method name
|
|
26
32
|
#
|
data/lib/jsonrpc/middleware.rb
CHANGED
|
@@ -41,13 +41,15 @@ module JSONRPC
|
|
|
41
41
|
# @option options [String] :path ('/') The path to handle JSON-RPC requests on
|
|
42
42
|
# @option options [Boolean] :rescue_internal_errors (nil) Override config rescue_internal_errors
|
|
43
43
|
# @option options [Boolean] :log_internal_errors (true) Override config log_internal_errors
|
|
44
|
+
# @option options [Logger] :logger (nil) Override config logger
|
|
44
45
|
#
|
|
45
46
|
def initialize(app, options = {})
|
|
46
47
|
@app = app
|
|
47
|
-
@parser = Parser.new
|
|
48
|
-
@validator = Validator.new
|
|
49
48
|
@path = options.fetch(:path, DEFAULT_PATH)
|
|
50
49
|
@config = JSONRPC.configuration
|
|
50
|
+
@logger = options.fetch(:logger, @config.logger)
|
|
51
|
+
@parser = Parser.new
|
|
52
|
+
@validator = Validator.new(logger: @logger)
|
|
51
53
|
@log_internal_errors = options.fetch(:log_internal_errors, @config.log_internal_errors)
|
|
52
54
|
@rescue_internal_errors = options.fetch(:rescue_internal_errors, @config.rescue_internal_errors)
|
|
53
55
|
end
|
|
@@ -89,10 +91,10 @@ module JSONRPC
|
|
|
89
91
|
#
|
|
90
92
|
# @api private
|
|
91
93
|
#
|
|
92
|
-
# @return [Array] Rack response tuple
|
|
93
|
-
#
|
|
94
94
|
# @raise [StandardError] Catches all errors and converts to Internal Error response
|
|
95
95
|
#
|
|
96
|
+
# @return [Array] Rack response tuple
|
|
97
|
+
#
|
|
96
98
|
def handle_jsonrpc_request
|
|
97
99
|
parsed_request = parse_request
|
|
98
100
|
return parsed_request if parsed_request.is_a?(Array) # Early return for parse errors
|
|
@@ -122,12 +124,11 @@ module JSONRPC
|
|
|
122
124
|
#
|
|
123
125
|
# @api private
|
|
124
126
|
#
|
|
125
|
-
# @return [Request, Notification, BatchRequest, Array] Parsed request or error response
|
|
126
|
-
#
|
|
127
127
|
# @raise [ParseError] When JSON parsing fails
|
|
128
|
-
#
|
|
129
128
|
# @raise [InvalidRequestError] When request structure is invalid
|
|
130
129
|
#
|
|
130
|
+
# @return [Request, Notification, BatchRequest, Array] Parsed request or error response
|
|
131
|
+
#
|
|
131
132
|
def parse_request
|
|
132
133
|
body = read_request_body
|
|
133
134
|
parsed = @parser.parse(body)
|
|
@@ -259,7 +260,7 @@ module JSONRPC
|
|
|
259
260
|
# @return [Array<Request, Notification>] Array of valid requests
|
|
260
261
|
#
|
|
261
262
|
def collect_valid_requests(batch_request)
|
|
262
|
-
batch_request.requests.
|
|
263
|
+
batch_request.requests.grep_v(Error)
|
|
263
264
|
end
|
|
264
265
|
|
|
265
266
|
# Builds ordered array of responses maintaining request order for batch processing
|
|
@@ -378,7 +379,7 @@ module JSONRPC
|
|
|
378
379
|
body_content
|
|
379
380
|
end
|
|
380
381
|
|
|
381
|
-
# Logs internal errors
|
|
382
|
+
# Logs internal errors with full backtrace using the configured logger
|
|
382
383
|
#
|
|
383
384
|
# @api private
|
|
384
385
|
#
|
|
@@ -390,8 +391,8 @@ module JSONRPC
|
|
|
390
391
|
# @return [void]
|
|
391
392
|
#
|
|
392
393
|
def log_internal_error(error)
|
|
393
|
-
|
|
394
|
-
|
|
394
|
+
@logger.error("Internal error: #{error.message}")
|
|
395
|
+
@logger.error(error.backtrace.join("\n"))
|
|
395
396
|
end
|
|
396
397
|
end
|
|
397
398
|
end
|
data/lib/jsonrpc/notification.rb
CHANGED
|
@@ -62,13 +62,12 @@ module JSONRPC
|
|
|
62
62
|
# @example Create a notification with named parameters
|
|
63
63
|
# JSONRPC::Notification.new(method: "log", params: { level: "info", message: "Hello" })
|
|
64
64
|
#
|
|
65
|
-
# @param method [String] the name of the method to be invoked
|
|
66
|
-
# @param params [Hash, Array, nil] the parameters to be used during method invocation
|
|
67
|
-
#
|
|
68
65
|
# @raise [ArgumentError] if method is not a String or is reserved
|
|
69
|
-
#
|
|
70
66
|
# @raise [ArgumentError] if params is not a Hash, Array, or nil
|
|
71
67
|
#
|
|
68
|
+
# @param method [String] the name of the method to be invoked
|
|
69
|
+
# @param params [Hash, Array, nil] the parameters to be used during method invocation
|
|
70
|
+
#
|
|
72
71
|
def initialize(method:, params: nil)
|
|
73
72
|
@jsonrpc = '2.0'
|
|
74
73
|
|
|
@@ -117,10 +116,10 @@ module JSONRPC
|
|
|
117
116
|
#
|
|
118
117
|
# @api private
|
|
119
118
|
#
|
|
120
|
-
# @param method [String] the method name
|
|
121
|
-
#
|
|
122
119
|
# @raise [ArgumentError] if method is not a String or is reserved
|
|
123
120
|
#
|
|
121
|
+
# @param method [String] the method name
|
|
122
|
+
#
|
|
124
123
|
# @return [void]
|
|
125
124
|
#
|
|
126
125
|
def validate_method(method)
|
|
@@ -135,10 +134,10 @@ module JSONRPC
|
|
|
135
134
|
#
|
|
136
135
|
# @api private
|
|
137
136
|
#
|
|
138
|
-
# @param params [Hash, Array, nil] the parameters
|
|
139
|
-
#
|
|
140
137
|
# @raise [ArgumentError] if params is not a Hash, Array, or nil
|
|
141
138
|
#
|
|
139
|
+
# @param params [Hash, Array, nil] the parameters
|
|
140
|
+
#
|
|
142
141
|
# @return [void]
|
|
143
142
|
#
|
|
144
143
|
def validate_params(params)
|