jsonrpc-middleware 0.1.0 → 0.2.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/.aiexclude +4 -0
- data/.claude/commands/document.md +105 -0
- data/.claude/docs/yard.md +602 -0
- data/.claude/settings.local.json +2 -1
- data/.env.example +5 -0
- data/CHANGELOG.md +22 -2
- data/CLAUDE.md +114 -0
- data/README.md +42 -102
- data/Rakefile +59 -1
- data/examples/README.md +37 -0
- data/examples/procedures.rb +6 -1
- data/examples/rack/README.md +26 -1
- data/examples/rack/app.rb +1 -1
- data/examples/rack-echo/README.md +23 -1
- data/examples/rack-single-file/README.md +37 -0
- data/examples/rack-single-file/config.ru +54 -0
- data/examples/rails/.gitignore +21 -0
- data/examples/rails/.ruby-version +1 -0
- data/examples/rails/Gemfile +15 -0
- data/examples/rails/Gemfile.lock +261 -0
- data/examples/rails/README.md +32 -0
- data/examples/rails/Rakefile +8 -0
- data/examples/rails/app/controllers/application_controller.rb +4 -0
- data/examples/rails/app/controllers/jsonrpc_controller.rb +44 -0
- data/examples/rails/bin/dev +4 -0
- data/examples/rails/bin/rails +6 -0
- data/examples/rails/bin/rake +6 -0
- data/examples/rails/bin/setup +28 -0
- data/examples/rails/config/application.rb +47 -0
- data/examples/rails/config/boot.rb +5 -0
- data/examples/rails/config/credentials.yml.enc +1 -0
- data/examples/rails/config/environment.rb +7 -0
- data/examples/rails/config/environments/development.rb +42 -0
- data/examples/rails/config/environments/production.rb +60 -0
- data/examples/rails/config/environments/test.rb +44 -0
- data/examples/rails/config/initializers/cors.rb +18 -0
- data/examples/rails/config/initializers/filter_parameter_logging.rb +10 -0
- data/examples/rails/config/initializers/inflections.rb +18 -0
- data/examples/rails/config/initializers/jsonrpc.rb +62 -0
- data/examples/rails/config/locales/en.yml +31 -0
- data/examples/rails/config/puma.rb +40 -0
- data/examples/rails/config/routes.rb +14 -0
- data/examples/rails/config.ru +8 -0
- data/examples/rails/public/robots.txt +1 -0
- data/examples/rails-single-file/config.ru +71 -0
- data/examples/sinatra-classic/Gemfile +9 -0
- data/examples/sinatra-classic/Gemfile.lock +95 -0
- data/examples/sinatra-classic/README.md +32 -0
- data/examples/sinatra-classic/app.rb +54 -0
- data/examples/sinatra-classic/config.ru +6 -0
- data/examples/sinatra-modular/Gemfile +9 -0
- data/examples/sinatra-modular/Gemfile.lock +95 -0
- data/examples/sinatra-modular/README.md +32 -0
- data/examples/sinatra-modular/app.rb +57 -0
- data/examples/sinatra-modular/config.ru +6 -0
- data/lib/jsonrpc/batch_request.rb +67 -2
- data/lib/jsonrpc/batch_response.rb +56 -0
- data/lib/jsonrpc/configuration.rb +156 -14
- data/lib/jsonrpc/error.rb +83 -2
- data/lib/jsonrpc/errors/internal_error.rb +14 -2
- data/lib/jsonrpc/errors/invalid_params_error.rb +13 -1
- data/lib/jsonrpc/errors/invalid_request_error.rb +8 -0
- data/lib/jsonrpc/errors/method_not_found_error.rb +8 -0
- data/lib/jsonrpc/errors/parse_error.rb +8 -0
- data/lib/jsonrpc/helpers.rb +212 -21
- data/lib/jsonrpc/middleware.rb +211 -5
- data/lib/jsonrpc/notification.rb +58 -0
- data/lib/jsonrpc/parser.rb +30 -0
- data/lib/jsonrpc/railtie.rb +57 -0
- data/lib/jsonrpc/request.rb +68 -1
- data/lib/jsonrpc/response.rb +76 -0
- data/lib/jsonrpc/validator.rb +67 -6
- data/lib/jsonrpc/version.rb +11 -1
- data/lib/jsonrpc.rb +53 -1
- metadata +49 -1
data/lib/jsonrpc/request.rb
CHANGED
@@ -3,40 +3,76 @@
|
|
3
3
|
module JSONRPC
|
4
4
|
# A JSON-RPC 2.0 Request object
|
5
5
|
#
|
6
|
+
# @api public
|
7
|
+
#
|
8
|
+
# Represents a call to a specific method with optional parameters and an identifier.
|
9
|
+
#
|
6
10
|
# @example Create a request with positional parameters
|
7
11
|
# request = JSONRPC::Request.new(method: "subtract", params: [42, 23], id: 1)
|
8
12
|
#
|
9
13
|
# @example Create a request with named parameters
|
10
|
-
# request = JSONRPC::Request.new(method: "subtract", params: {minuend: 42, subtrahend: 23}, id: 3)
|
14
|
+
# request = JSONRPC::Request.new(method: "subtract", params: { minuend: 42, subtrahend: 23 }, id: 3)
|
11
15
|
#
|
12
16
|
class Request
|
13
17
|
# JSON-RPC protocol version
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# request.jsonrpc # => "2.0"
|
23
|
+
#
|
14
24
|
# @return [String]
|
15
25
|
#
|
16
26
|
attr_reader :jsonrpc
|
17
27
|
|
18
28
|
# The method name to invoke
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# request.method # => "subtract"
|
34
|
+
#
|
19
35
|
# @return [String]
|
20
36
|
#
|
21
37
|
attr_reader :method
|
22
38
|
|
23
39
|
# Parameters to pass to the method
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# request.params # => { "minuend": 42, "subtrahend": 23 }
|
45
|
+
#
|
24
46
|
# @return [Hash, Array, nil]
|
25
47
|
#
|
26
48
|
attr_reader :params
|
27
49
|
|
28
50
|
# The request identifier
|
51
|
+
#
|
52
|
+
# @api public
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# request.id # => 1
|
56
|
+
#
|
29
57
|
# @return [String, Integer, nil]
|
30
58
|
#
|
31
59
|
attr_reader :id
|
32
60
|
|
33
61
|
# Creates a new JSON-RPC 2.0 Request object
|
34
62
|
#
|
63
|
+
# @api public
|
64
|
+
#
|
65
|
+
# @example Create a request with positional parameters
|
66
|
+
# JSONRPC::Request.new(method: "subtract", params: [42, 23], id: 1)
|
67
|
+
#
|
35
68
|
# @param method [String] the name of the method to be invoked
|
36
69
|
# @param params [Hash, Array, nil] the parameters to be used during method invocation
|
37
70
|
# @param id [String, Integer, nil] the request identifier
|
71
|
+
#
|
38
72
|
# @raise [ArgumentError] if method is not a String or is reserved
|
73
|
+
#
|
39
74
|
# @raise [ArgumentError] if params is not a Hash, Array, or nil
|
75
|
+
#
|
40
76
|
# @raise [ArgumentError] if id is not a String, Integer, or nil
|
41
77
|
#
|
42
78
|
def initialize(method:, id:, params: nil)
|
@@ -53,6 +89,12 @@ module JSONRPC
|
|
53
89
|
|
54
90
|
# Converts the request to a JSON-compatible Hash
|
55
91
|
#
|
92
|
+
# @api public
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# request.to_h
|
96
|
+
# # => { jsonrpc: "2.0", method: "subtract", params: [42, 23], id: 1 }
|
97
|
+
#
|
56
98
|
# @return [Hash] the request as a JSON-compatible Hash
|
57
99
|
#
|
58
100
|
def to_h
|
@@ -66,6 +108,16 @@ module JSONRPC
|
|
66
108
|
hash
|
67
109
|
end
|
68
110
|
|
111
|
+
# Converts the request to a JSON string
|
112
|
+
#
|
113
|
+
# @api public
|
114
|
+
#
|
115
|
+
# @example
|
116
|
+
# request.to_json
|
117
|
+
# # => '{"jsonrpc":"2.0","method":"subtract","params":[42,23],"id":1}'
|
118
|
+
#
|
119
|
+
# @return [String] the request as a JSON string
|
120
|
+
#
|
69
121
|
def to_json(*)
|
70
122
|
to_h.to_json(*)
|
71
123
|
end
|
@@ -74,9 +126,14 @@ module JSONRPC
|
|
74
126
|
|
75
127
|
# Validates that the method name meets JSON-RPC 2.0 requirements
|
76
128
|
#
|
129
|
+
# @api private
|
130
|
+
#
|
77
131
|
# @param method [String] the method name
|
132
|
+
#
|
78
133
|
# @raise [ArgumentError] if method is not a String or is reserved
|
79
134
|
#
|
135
|
+
# @return [void]
|
136
|
+
#
|
80
137
|
def validate_method(method)
|
81
138
|
raise ArgumentError, 'Method must be a String' unless method.is_a?(String)
|
82
139
|
|
@@ -87,9 +144,14 @@ module JSONRPC
|
|
87
144
|
|
88
145
|
# Validates that the params is a valid structure according to JSON-RPC 2.0
|
89
146
|
#
|
147
|
+
# @api private
|
148
|
+
#
|
90
149
|
# @param params [Hash, Array, nil] the parameters
|
150
|
+
#
|
91
151
|
# @raise [ArgumentError] if params is not a Hash, Array, or nil
|
92
152
|
#
|
153
|
+
# @return [void]
|
154
|
+
#
|
93
155
|
def validate_params(params)
|
94
156
|
return if params.nil?
|
95
157
|
|
@@ -100,9 +162,14 @@ module JSONRPC
|
|
100
162
|
|
101
163
|
# Validates that the id meets JSON-RPC 2.0 requirements
|
102
164
|
#
|
165
|
+
# @api private
|
166
|
+
#
|
103
167
|
# @param id [String, Integer, nil] the request identifier
|
168
|
+
#
|
104
169
|
# @raise [ArgumentError] if id is not a String, Integer, or nil
|
105
170
|
#
|
171
|
+
# @return [void]
|
172
|
+
#
|
106
173
|
def validate_id(id)
|
107
174
|
return if id.nil?
|
108
175
|
|
data/lib/jsonrpc/response.rb
CHANGED
@@ -3,6 +3,11 @@
|
|
3
3
|
module JSONRPC
|
4
4
|
# A JSON-RPC 2.0 Response object
|
5
5
|
#
|
6
|
+
# @api public
|
7
|
+
#
|
8
|
+
# Represents the outcome of a method invocation, either containing a result for
|
9
|
+
# successful calls or an error for failed ones. This follows the JSON-RPC 2.0 specification.
|
10
|
+
#
|
6
11
|
# When a rpc call is made, the Server must reply with a Response, except for notifications.
|
7
12
|
# A Response object can contain either a result (for success) or an error (for failure),
|
8
13
|
# but never both.
|
@@ -16,32 +21,68 @@ module JSONRPC
|
|
16
21
|
#
|
17
22
|
class Response
|
18
23
|
# JSON-RPC protocol version
|
24
|
+
#
|
25
|
+
# @api public
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# response.jsonrpc # => "2.0"
|
29
|
+
#
|
19
30
|
# @return [String]
|
20
31
|
#
|
21
32
|
attr_reader :jsonrpc
|
22
33
|
|
23
34
|
# The result of the method invocation (for success)
|
35
|
+
#
|
36
|
+
# @api public
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# response.result # => 42
|
40
|
+
#
|
24
41
|
# @return [Object, nil]
|
25
42
|
#
|
26
43
|
attr_reader :result
|
27
44
|
|
28
45
|
# The error object (for failure)
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# response.error # => #<JSONRPC::Error...>
|
51
|
+
#
|
29
52
|
# @return [JSONRPC::Error, nil]
|
30
53
|
#
|
31
54
|
attr_reader :error
|
32
55
|
|
33
56
|
# The request identifier
|
57
|
+
#
|
58
|
+
# @api public
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# response.id # => 1
|
62
|
+
#
|
34
63
|
# @return [String, Integer, nil]
|
35
64
|
#
|
36
65
|
attr_reader :id
|
37
66
|
|
38
67
|
# Creates a new JSON-RPC 2.0 Response object
|
39
68
|
#
|
69
|
+
# @api public
|
70
|
+
#
|
71
|
+
# @example Create a successful response
|
72
|
+
# JSONRPC::Response.new(id: 1, result: 42)
|
73
|
+
#
|
74
|
+
# @example Create an error response
|
75
|
+
# error = JSONRPC::Error.new("Method not found", code: -32601)
|
76
|
+
# JSONRPC::Response.new(id: 1, error: error)
|
77
|
+
#
|
40
78
|
# @param result [Object, nil] the result of the method invocation (for success)
|
41
79
|
# @param error [JSONRPC::Error, nil] the error object (for failure)
|
42
80
|
# @param id [String, Integer, nil] the request identifier
|
81
|
+
#
|
43
82
|
# @raise [ArgumentError] if both result and error are present or both are nil
|
83
|
+
#
|
44
84
|
# @raise [ArgumentError] if error is present but not a JSONRPC::Error
|
85
|
+
#
|
45
86
|
# @raise [ArgumentError] if id is not a String, Integer, or nil
|
46
87
|
#
|
47
88
|
def initialize(id:, result: nil, error: nil)
|
@@ -57,6 +98,11 @@ module JSONRPC
|
|
57
98
|
|
58
99
|
# Checks if the response is successful
|
59
100
|
#
|
101
|
+
# @api public
|
102
|
+
#
|
103
|
+
# @example
|
104
|
+
# response.success? # => true
|
105
|
+
#
|
60
106
|
# @return [Boolean] true if the response contains a result, false if it contains an error
|
61
107
|
#
|
62
108
|
def success?
|
@@ -65,6 +111,11 @@ module JSONRPC
|
|
65
111
|
|
66
112
|
# Checks if the response is an error
|
67
113
|
#
|
114
|
+
# @api public
|
115
|
+
#
|
116
|
+
# @example
|
117
|
+
# response.error? # => false
|
118
|
+
#
|
68
119
|
# @return [Boolean] true if the response contains an error, false if it contains a result
|
69
120
|
#
|
70
121
|
def error?
|
@@ -73,6 +124,11 @@ module JSONRPC
|
|
73
124
|
|
74
125
|
# Converts the response to a JSON-compatible Hash
|
75
126
|
#
|
127
|
+
# @api public
|
128
|
+
#
|
129
|
+
# @example
|
130
|
+
# response.to_h # => { jsonrpc: "2.0", result: 42, id: 1 }
|
131
|
+
#
|
76
132
|
# @return [Hash] the response as a JSON-compatible Hash
|
77
133
|
#
|
78
134
|
def to_h
|
@@ -90,6 +146,15 @@ module JSONRPC
|
|
90
146
|
hash
|
91
147
|
end
|
92
148
|
|
149
|
+
# Converts the response to a JSON string
|
150
|
+
#
|
151
|
+
# @api public
|
152
|
+
#
|
153
|
+
# @example
|
154
|
+
# response.to_json # => '{"jsonrpc":"2.0","result":42,"id":1}'
|
155
|
+
#
|
156
|
+
# @return [String] the response as a JSON string
|
157
|
+
#
|
93
158
|
def to_json(*)
|
94
159
|
to_h.to_json(*)
|
95
160
|
end
|
@@ -98,11 +163,17 @@ module JSONRPC
|
|
98
163
|
|
99
164
|
# Validates that exactly one of result or error is present
|
100
165
|
#
|
166
|
+
# @api private
|
167
|
+
#
|
101
168
|
# @param result [Object, nil] the result
|
102
169
|
# @param error [JSONRPC::Error, nil] the error
|
170
|
+
#
|
103
171
|
# @raise [ArgumentError] if both result and error are present or both are nil
|
172
|
+
#
|
104
173
|
# @raise [ArgumentError] if error is present but not a JSONRPC::Error
|
105
174
|
#
|
175
|
+
# @return [void]
|
176
|
+
#
|
106
177
|
def validate_result_and_error(result, error)
|
107
178
|
raise ArgumentError, 'Either result or error must be present' if result.nil? && error.nil?
|
108
179
|
|
@@ -115,9 +186,14 @@ module JSONRPC
|
|
115
186
|
|
116
187
|
# Validates that the id meets JSON-RPC 2.0 requirements
|
117
188
|
#
|
189
|
+
# @api private
|
190
|
+
#
|
118
191
|
# @param id [String, Integer, nil] the request identifier
|
192
|
+
#
|
119
193
|
# @raise [ArgumentError] if id is not a String, Integer, or nil
|
120
194
|
#
|
195
|
+
# @return [void]
|
196
|
+
#
|
121
197
|
def validate_id(id)
|
122
198
|
return if id.nil?
|
123
199
|
|
data/lib/jsonrpc/validator.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JSONRPC
|
4
|
-
# Validates JSON-RPC 2.0 requests and
|
4
|
+
# Validates JSON-RPC 2.0 requests, notifications and batches
|
5
|
+
#
|
6
|
+
# @api public
|
7
|
+
#
|
8
|
+
# The Validator handles parameter validation for JSON-RPC requests by checking
|
9
|
+
# method signatures against registered procedure definitions using Dry::Validation contracts.
|
10
|
+
#
|
11
|
+
# @example Validate a single request
|
12
|
+
# validator = JSONRPC::Validator.new
|
13
|
+
# error = validator.validate(request)
|
14
|
+
#
|
5
15
|
class Validator
|
6
|
-
# Validates a single request, notification or a batch
|
16
|
+
# Validates a single request, notification or a batch
|
7
17
|
#
|
8
|
-
# @
|
18
|
+
# @api public
|
9
19
|
#
|
10
20
|
# @example Validate a single request
|
11
21
|
# validator = JSONRPC::Validator.new
|
@@ -15,7 +25,9 @@ module JSONRPC
|
|
15
25
|
# validator = JSONRPC::Validator.new
|
16
26
|
# errors = validator.validate(batch)
|
17
27
|
#
|
18
|
-
# @
|
28
|
+
# @param batch_or_request [JSONRPC::BatchRequest, JSONRPC::Request, JSONRPC::Notification] the object to validate
|
29
|
+
#
|
30
|
+
# @return [JSONRPC::Error, Array<JSONRPC::Error>, nil] error(s) if validation fails, nil if successful
|
19
31
|
#
|
20
32
|
def validate(batch_or_request)
|
21
33
|
case batch_or_request
|
@@ -28,6 +40,14 @@ module JSONRPC
|
|
28
40
|
|
29
41
|
private
|
30
42
|
|
43
|
+
# Validates a batch of requests/notifications
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
#
|
47
|
+
# @param batch [BatchRequest] the batch to validate
|
48
|
+
#
|
49
|
+
# @return [Array<Error>, nil] array of errors or nil if all valid
|
50
|
+
#
|
31
51
|
def validate_batch_params(batch)
|
32
52
|
errors = batch.map { |req| validate_request_params(req) }
|
33
53
|
|
@@ -36,7 +56,14 @@ module JSONRPC
|
|
36
56
|
errors.any? ? errors : nil
|
37
57
|
end
|
38
58
|
|
39
|
-
#
|
59
|
+
# Validates a single request or notification
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
#
|
63
|
+
# @param request_or_notification [Request, Notification] the request to validate
|
64
|
+
#
|
65
|
+
# @return [Error, nil] error if validation fails, nil if successful
|
66
|
+
#
|
40
67
|
def validate_request_params(request_or_notification)
|
41
68
|
config = JSONRPC.configuration
|
42
69
|
|
@@ -72,7 +99,7 @@ module JSONRPC
|
|
72
99
|
|
73
100
|
nil
|
74
101
|
rescue StandardError => e
|
75
|
-
if
|
102
|
+
if JSONRPC.configuration.log_request_validation_errors
|
76
103
|
puts "Validation error: #{e.message}"
|
77
104
|
puts e.backtrace.join("\n")
|
78
105
|
end
|
@@ -80,6 +107,15 @@ module JSONRPC
|
|
80
107
|
InternalError.new(request_id: extract_request_id(request_or_notification))
|
81
108
|
end
|
82
109
|
|
110
|
+
# Prepares parameters for validation based on procedure configuration
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
#
|
114
|
+
# @param request [Request, Notification] the request
|
115
|
+
# @param procedure [Configuration::Procedure] the procedure configuration
|
116
|
+
#
|
117
|
+
# @return [Hash, InvalidParamsError] prepared params or error
|
118
|
+
#
|
83
119
|
def prepare_params_for_validation(request, procedure)
|
84
120
|
if procedure.allow_positional_arguments
|
85
121
|
handle_positional_arguments(request, procedure)
|
@@ -88,6 +124,15 @@ module JSONRPC
|
|
88
124
|
end
|
89
125
|
end
|
90
126
|
|
127
|
+
# Handles validation for procedures that allow positional arguments
|
128
|
+
#
|
129
|
+
# @api private
|
130
|
+
#
|
131
|
+
# @param request_or_notification [Request, Notification] the request
|
132
|
+
# @param procedure [Configuration::Procedure] the procedure configuration
|
133
|
+
#
|
134
|
+
# @return [Hash, InvalidParamsError] prepared params or error
|
135
|
+
#
|
91
136
|
def handle_positional_arguments(request_or_notification, procedure)
|
92
137
|
case request_or_notification.params
|
93
138
|
when Array
|
@@ -112,6 +157,14 @@ module JSONRPC
|
|
112
157
|
end
|
113
158
|
end
|
114
159
|
|
160
|
+
# Handles validation for procedures that only accept named arguments
|
161
|
+
#
|
162
|
+
# @api private
|
163
|
+
#
|
164
|
+
# @param request_or_notification [Request, Notification] the request
|
165
|
+
#
|
166
|
+
# @return [Hash, InvalidParamsError] prepared params or error
|
167
|
+
#
|
115
168
|
def handle_named_arguments(request_or_notification)
|
116
169
|
case request_or_notification.params
|
117
170
|
when Hash
|
@@ -128,6 +181,14 @@ module JSONRPC
|
|
128
181
|
end
|
129
182
|
end
|
130
183
|
|
184
|
+
# Extracts the request ID from a request or notification
|
185
|
+
#
|
186
|
+
# @api private
|
187
|
+
#
|
188
|
+
# @param request_or_notification [Request, Notification] the request
|
189
|
+
#
|
190
|
+
# @return [String, Integer, nil] the request ID or nil for notifications
|
191
|
+
#
|
131
192
|
def extract_request_id(request_or_notification)
|
132
193
|
case request_or_notification
|
133
194
|
when Request
|
data/lib/jsonrpc/version.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Encapsulates all the gem's logic for JSON-RPC 2.0 protocol handling
|
4
|
+
#
|
5
|
+
# @api public
|
6
|
+
#
|
3
7
|
module JSONRPC
|
4
|
-
|
8
|
+
# The version of the gem
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
#
|
12
|
+
# @return [String] The current version number
|
13
|
+
#
|
14
|
+
VERSION = '0.2.0'
|
5
15
|
end
|
data/lib/jsonrpc.rb
CHANGED
@@ -5,12 +5,60 @@ require 'dry-validation'
|
|
5
5
|
|
6
6
|
Dry::Validation.load_extensions(:predicates_as_macros)
|
7
7
|
|
8
|
-
#
|
8
|
+
# JSON-RPC 2.0 middleware implementation for Ruby
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
#
|
12
|
+
# This module provides a complete implementation of the JSON-RPC 2.0 specification
|
13
|
+
# as Rack middleware. It handles parsing, validation, and error handling for
|
14
|
+
# JSON-RPC requests, notifications, and batch operations.
|
15
|
+
#
|
16
|
+
# @example Basic configuration
|
17
|
+
# JSONRPC.configure do
|
18
|
+
# procedure('add') do
|
19
|
+
# params do
|
20
|
+
# required(:a).value(:integer)
|
21
|
+
# required(:b).value(:integer)
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @example Using the middleware
|
27
|
+
# use JSONRPC::Middleware, path: '/api/v1/rpc'
|
28
|
+
#
|
9
29
|
module JSONRPC
|
30
|
+
# Configures the JSON-RPC middleware with procedure definitions
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
#
|
34
|
+
# @example Configure procedures
|
35
|
+
# JSONRPC.configure do
|
36
|
+
# procedure('subtract') do
|
37
|
+
# params do
|
38
|
+
# required(:minuend).value(:integer)
|
39
|
+
# required(:subtrahend).value(:integer)
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# @yield Block containing procedure definitions using the Configuration DSL
|
45
|
+
#
|
46
|
+
# @return [void]
|
47
|
+
#
|
10
48
|
def self.configure(&)
|
11
49
|
Configuration.instance.instance_eval(&)
|
12
50
|
end
|
13
51
|
|
52
|
+
# Returns the current JSON-RPC configuration instance
|
53
|
+
#
|
54
|
+
# @api public
|
55
|
+
#
|
56
|
+
# @example Access configuration
|
57
|
+
# config = JSONRPC.configuration
|
58
|
+
# config.procedure?('add') # => true/false
|
59
|
+
#
|
60
|
+
# @return [Configuration] The singleton configuration instance
|
61
|
+
#
|
14
62
|
def self.configuration
|
15
63
|
Configuration.instance
|
16
64
|
end
|
@@ -20,6 +68,10 @@ loader = Zeitwerk::Loader.for_gem
|
|
20
68
|
loader.log! if ENV['DEBUG_ZEITWERK'] == 'true'
|
21
69
|
loader.enable_reloading
|
22
70
|
loader.collapse("#{__dir__}/jsonrpc/errors")
|
71
|
+
loader.ignore("#{__dir__}/jsonrpc/railtie.rb")
|
23
72
|
loader.inflector.inflect('jsonrpc' => 'JSONRPC')
|
24
73
|
loader.setup
|
25
74
|
loader.eager_load
|
75
|
+
|
76
|
+
# Only load Rails integration if Rails is available
|
77
|
+
require_relative 'jsonrpc/railtie' if defined?(Rails)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonrpc-middleware
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wilson Silva
|
@@ -45,14 +45,19 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
+
- ".aiexclude"
|
49
|
+
- ".claude/commands/document.md"
|
50
|
+
- ".claude/docs/yard.md"
|
48
51
|
- ".claude/settings.local.json"
|
49
52
|
- ".editorconfig"
|
53
|
+
- ".env.example"
|
50
54
|
- ".overcommit.yml"
|
51
55
|
- ".rspec"
|
52
56
|
- ".rubocop.yml"
|
53
57
|
- ".tool-versions"
|
54
58
|
- ".yardstick.yml"
|
55
59
|
- CHANGELOG.md
|
60
|
+
- CLAUDE.md
|
56
61
|
- CODE_OF_CONDUCT.md
|
57
62
|
- Guardfile
|
58
63
|
- LICENSE.txt
|
@@ -60,17 +65,59 @@ files:
|
|
60
65
|
- Rakefile
|
61
66
|
- Steepfile
|
62
67
|
- docs/JSON-RPC-2.0-Specification.md
|
68
|
+
- examples/README.md
|
63
69
|
- examples/procedures.rb
|
64
70
|
- examples/rack-echo/Gemfile
|
65
71
|
- examples/rack-echo/Gemfile.lock
|
66
72
|
- examples/rack-echo/README.md
|
67
73
|
- examples/rack-echo/app.rb
|
68
74
|
- examples/rack-echo/config.ru
|
75
|
+
- examples/rack-single-file/README.md
|
76
|
+
- examples/rack-single-file/config.ru
|
69
77
|
- examples/rack/Gemfile
|
70
78
|
- examples/rack/Gemfile.lock
|
71
79
|
- examples/rack/README.md
|
72
80
|
- examples/rack/app.rb
|
73
81
|
- examples/rack/config.ru
|
82
|
+
- examples/rails-single-file/config.ru
|
83
|
+
- examples/rails/.gitignore
|
84
|
+
- examples/rails/.ruby-version
|
85
|
+
- examples/rails/Gemfile
|
86
|
+
- examples/rails/Gemfile.lock
|
87
|
+
- examples/rails/README.md
|
88
|
+
- examples/rails/Rakefile
|
89
|
+
- examples/rails/app/controllers/application_controller.rb
|
90
|
+
- examples/rails/app/controllers/jsonrpc_controller.rb
|
91
|
+
- examples/rails/bin/dev
|
92
|
+
- examples/rails/bin/rails
|
93
|
+
- examples/rails/bin/rake
|
94
|
+
- examples/rails/bin/setup
|
95
|
+
- examples/rails/config.ru
|
96
|
+
- examples/rails/config/application.rb
|
97
|
+
- examples/rails/config/boot.rb
|
98
|
+
- examples/rails/config/credentials.yml.enc
|
99
|
+
- examples/rails/config/environment.rb
|
100
|
+
- examples/rails/config/environments/development.rb
|
101
|
+
- examples/rails/config/environments/production.rb
|
102
|
+
- examples/rails/config/environments/test.rb
|
103
|
+
- examples/rails/config/initializers/cors.rb
|
104
|
+
- examples/rails/config/initializers/filter_parameter_logging.rb
|
105
|
+
- examples/rails/config/initializers/inflections.rb
|
106
|
+
- examples/rails/config/initializers/jsonrpc.rb
|
107
|
+
- examples/rails/config/locales/en.yml
|
108
|
+
- examples/rails/config/puma.rb
|
109
|
+
- examples/rails/config/routes.rb
|
110
|
+
- examples/rails/public/robots.txt
|
111
|
+
- examples/sinatra-classic/Gemfile
|
112
|
+
- examples/sinatra-classic/Gemfile.lock
|
113
|
+
- examples/sinatra-classic/README.md
|
114
|
+
- examples/sinatra-classic/app.rb
|
115
|
+
- examples/sinatra-classic/config.ru
|
116
|
+
- examples/sinatra-modular/Gemfile
|
117
|
+
- examples/sinatra-modular/Gemfile.lock
|
118
|
+
- examples/sinatra-modular/README.md
|
119
|
+
- examples/sinatra-modular/app.rb
|
120
|
+
- examples/sinatra-modular/config.ru
|
74
121
|
- lib/jsonrpc.rb
|
75
122
|
- lib/jsonrpc/batch_request.rb
|
76
123
|
- lib/jsonrpc/batch_response.rb
|
@@ -85,6 +132,7 @@ files:
|
|
85
132
|
- lib/jsonrpc/middleware.rb
|
86
133
|
- lib/jsonrpc/notification.rb
|
87
134
|
- lib/jsonrpc/parser.rb
|
135
|
+
- lib/jsonrpc/railtie.rb
|
88
136
|
- lib/jsonrpc/request.rb
|
89
137
|
- lib/jsonrpc/response.rb
|
90
138
|
- lib/jsonrpc/validator.rb
|