jsonrpc-middleware 0.5.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 +43 -0
- data/CLAUDE.md +2 -113
- data/Dockerfile +144 -0
- data/README.md +10 -17
- data/Rakefile +78 -26
- data/examples/README.md +9 -0
- data/examples/procedures.rb +3 -1
- data/examples/rack/Gemfile.lock +11 -2
- data/examples/rack-echo/Gemfile.lock +11 -2
- data/examples/rails/Gemfile.lock +18 -23
- 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/README.md +38 -3
- data/examples/rails-single-file-routing/config.ru +18 -1
- data/examples/sinatra-classic/Gemfile.lock +11 -3
- data/examples/sinatra-modular/Gemfile.lock +11 -3
- data/lib/jsonrpc/batch_request.rb +9 -12
- data/lib/jsonrpc/batch_response.rb +7 -9
- data/lib/jsonrpc/configuration.rb +43 -4
- data/lib/jsonrpc/error.rb +8 -9
- 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 +15 -13
- data/lib/jsonrpc/notification.rb +8 -9
- data/lib/jsonrpc/parser.rb +22 -19
- 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 +4 -2
- data/lib/jsonrpc/request.rb +12 -84
- data/lib/jsonrpc/response.rb +11 -60
- data/lib/jsonrpc/types.rb +13 -0
- data/lib/jsonrpc/validator.rb +14 -4
- data/lib/jsonrpc/version.rb +1 -1
- data/lib/jsonrpc.rb +5 -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 +61 -9
- data/.claude/commands/document.md +0 -105
- data/.claude/commands/test.md +0 -561
- data/.claude/docs/yard.md +0 -602
- data/.claude/settings.local.json +0 -11
- data/.yardstick.yml +0 -22
data/Rakefile
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'English' # For $CHILD_STATUS
|
|
3
4
|
require 'bundler/audit/task'
|
|
4
5
|
require 'bundler/gem_tasks'
|
|
5
6
|
require 'rspec/core/rake_task'
|
|
6
7
|
require 'rubocop/rake_task'
|
|
7
8
|
require 'yaml'
|
|
9
|
+
require 'yard'
|
|
8
10
|
require 'yard/rake/yardoc_task'
|
|
9
|
-
require 'yard-junk/rake'
|
|
10
|
-
require 'yardstick/rake/measurement'
|
|
11
|
-
require 'yardstick/rake/verify'
|
|
12
|
-
|
|
13
|
-
yardstick_options = YAML.load_file('.yardstick.yml')
|
|
14
11
|
|
|
15
12
|
Bundler::Audit::Task.new
|
|
16
13
|
RSpec::Core::RakeTask.new(:spec)
|
|
17
14
|
RuboCop::RakeTask.new
|
|
18
15
|
YARD::Rake::YardocTask.new
|
|
19
|
-
YardJunk::Rake.define_task
|
|
20
|
-
Yardstick::Rake::Measurement.new(:yardstick_measure, yardstick_options)
|
|
21
|
-
Yardstick::Rake::Verify.new(:verify_measurements, yardstick_options)
|
|
22
16
|
|
|
23
17
|
task default: %i[spec rubocop]
|
|
24
18
|
|
|
25
19
|
# Remove the report on rake clobber
|
|
26
|
-
CLEAN.include('
|
|
20
|
+
CLEAN.include('doc', '.yardoc', 'tmp')
|
|
27
21
|
|
|
28
22
|
# Delete these files and folders when running rake clobber.
|
|
29
23
|
CLOBBER.include('coverage', '.rspec_status')
|
|
@@ -32,11 +26,10 @@ desc 'Run spec with coverage'
|
|
|
32
26
|
task :coverage do
|
|
33
27
|
ENV['COVERAGE'] = 'true'
|
|
34
28
|
Rake::Task['spec'].execute
|
|
35
|
-
`open coverage/index.html`
|
|
36
29
|
end
|
|
37
30
|
|
|
38
31
|
desc 'Test, lint and perform security and documentation audits'
|
|
39
|
-
task qa: %w[spec rubocop yard:
|
|
32
|
+
task qa: %w[spec rubocop yard:lint bundle:audit]
|
|
40
33
|
|
|
41
34
|
namespace :yard do
|
|
42
35
|
desc 'Format YARD documentation'
|
|
@@ -94,59 +87,118 @@ namespace :yard do
|
|
|
94
87
|
puts
|
|
95
88
|
puts 'Done!'
|
|
96
89
|
end
|
|
90
|
+
|
|
91
|
+
desc 'Lint YARD documentation'
|
|
92
|
+
task :lint do
|
|
93
|
+
system 'bundle exec yard-lint lib/'
|
|
94
|
+
end
|
|
97
95
|
end
|
|
98
96
|
|
|
99
97
|
namespace :examples do
|
|
100
98
|
desc 'Run bundle install on all example folders'
|
|
101
99
|
task :bundle_install do
|
|
102
100
|
examples_dir = File.join(Dir.pwd, 'examples')
|
|
103
|
-
|
|
101
|
+
|
|
104
102
|
unless Dir.exist?(examples_dir)
|
|
105
103
|
puts 'Examples directory not found'
|
|
106
104
|
exit 1
|
|
107
105
|
end
|
|
108
|
-
|
|
106
|
+
|
|
109
107
|
example_folders = Dir.glob(File.join(examples_dir, '*')).select { |path| Dir.exist?(path) }
|
|
110
|
-
|
|
108
|
+
|
|
111
109
|
if example_folders.empty?
|
|
112
110
|
puts 'No example folders found'
|
|
113
111
|
return
|
|
114
112
|
end
|
|
115
|
-
|
|
113
|
+
|
|
116
114
|
puts "Found #{example_folders.length} example folders:"
|
|
117
115
|
example_folders.each { |folder| puts " - #{File.basename(folder)}" }
|
|
118
116
|
puts
|
|
119
|
-
|
|
117
|
+
|
|
120
118
|
failed_folders = []
|
|
121
|
-
|
|
119
|
+
|
|
122
120
|
example_folders.each do |folder|
|
|
123
121
|
gemfile_path = File.join(folder, 'Gemfile')
|
|
124
|
-
|
|
122
|
+
|
|
125
123
|
unless File.exist?(gemfile_path)
|
|
126
124
|
puts "Skipping #{File.basename(folder)} - no Gemfile found"
|
|
127
125
|
next
|
|
128
126
|
end
|
|
129
|
-
|
|
127
|
+
|
|
130
128
|
puts "Running bundle install in #{File.basename(folder)}..."
|
|
131
|
-
|
|
129
|
+
|
|
132
130
|
Dir.chdir(folder) do
|
|
133
131
|
system('bundle install')
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
|
|
133
|
+
if $CHILD_STATUS.success?
|
|
134
|
+
puts " ✓ Successfully installed gems in #{File.basename(folder)}"
|
|
135
|
+
else
|
|
136
136
|
failed_folders << File.basename(folder)
|
|
137
137
|
puts " ✗ Failed to bundle install in #{File.basename(folder)}"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
puts
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
if failed_folders.empty?
|
|
145
|
+
puts 'All example folders processed successfully!'
|
|
146
|
+
else
|
|
147
|
+
puts "Failed to process #{failed_folders.length} folders: #{failed_folders.join(", ")}"
|
|
148
|
+
exit 1
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
desc 'Run bundle update on all example folders'
|
|
153
|
+
task :bundle_update do
|
|
154
|
+
examples_dir = File.join(Dir.pwd, 'examples')
|
|
155
|
+
|
|
156
|
+
unless Dir.exist?(examples_dir)
|
|
157
|
+
puts 'Examples directory not found'
|
|
158
|
+
exit 1
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
example_folders = Dir.glob(File.join(examples_dir, '*')).select { |path| Dir.exist?(path) }
|
|
162
|
+
|
|
163
|
+
if example_folders.empty?
|
|
164
|
+
puts 'No example folders found'
|
|
165
|
+
return
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
puts "Found #{example_folders.length} example folders:"
|
|
169
|
+
example_folders.each { |folder| puts " - #{File.basename(folder)}" }
|
|
170
|
+
puts
|
|
171
|
+
|
|
172
|
+
failed_folders = []
|
|
173
|
+
|
|
174
|
+
example_folders.each do |folder|
|
|
175
|
+
gemfile_path = File.join(folder, 'Gemfile')
|
|
176
|
+
|
|
177
|
+
unless File.exist?(gemfile_path)
|
|
178
|
+
puts "Skipping #{File.basename(folder)} - no Gemfile found"
|
|
179
|
+
next
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
puts "Running bundle update in #{File.basename(folder)}..."
|
|
183
|
+
|
|
184
|
+
Dir.chdir(folder) do
|
|
185
|
+
system('bundle update --all')
|
|
186
|
+
|
|
187
|
+
if $CHILD_STATUS.success?
|
|
188
|
+
puts " ✓ Successfully updated gems in #{File.basename(folder)}"
|
|
138
189
|
else
|
|
139
|
-
|
|
190
|
+
failed_folders << File.basename(folder)
|
|
191
|
+
puts " ✗ Failed to bundle update in #{File.basename(folder)}"
|
|
140
192
|
end
|
|
141
193
|
end
|
|
142
|
-
|
|
194
|
+
|
|
143
195
|
puts
|
|
144
196
|
end
|
|
145
|
-
|
|
197
|
+
|
|
146
198
|
if failed_folders.empty?
|
|
147
199
|
puts 'All example folders processed successfully!'
|
|
148
200
|
else
|
|
149
|
-
puts "Failed to process #{failed_folders.length} folders: #{failed_folders.join(
|
|
201
|
+
puts "Failed to process #{failed_folders.length} folders: #{failed_folders.join(", ")}"
|
|
150
202
|
exit 1
|
|
151
203
|
end
|
|
152
204
|
end
|
data/examples/README.md
CHANGED
|
@@ -10,6 +10,7 @@ This directory contains example implementations of JSON-RPC servers using the js
|
|
|
10
10
|
- [**rails**](./rails/) - Calculator server using Rails
|
|
11
11
|
- [**rails-single-file**](./rails-single-file/) - Echo server using Rails with bundler/inline
|
|
12
12
|
- [**rails-single-file-routing**](./rails-single-file-routing/) - Echo server using Rails with method-specific routing
|
|
13
|
+
- [**rails-routing-dsl**](./rails-routing-dsl/) - Smart home control server showcasing Rails JSON-RPC routing DSL
|
|
13
14
|
- [**sinatra-classic**](./sinatra-classic/) - Calculator server using classic Sinatra
|
|
14
15
|
- [**sinatra-modular**](./sinatra-modular/) - Calculator server using modular Sinatra
|
|
15
16
|
|
|
@@ -27,6 +28,14 @@ The echo examples implement:
|
|
|
27
28
|
|
|
28
29
|
- `echo` - Returns the input message
|
|
29
30
|
|
|
31
|
+
The rails-routing-dsl example implements a smart home control API:
|
|
32
|
+
|
|
33
|
+
- `on` / `off` - Control main home automation system
|
|
34
|
+
- `lights.on` / `lights.off` - Control lights
|
|
35
|
+
- `climate.on` / `climate.off` - Control climate system
|
|
36
|
+
- `climate.fan.on` / `climate.fan.off` - Control climate fan
|
|
37
|
+
- Batch request support for multiple operations
|
|
38
|
+
|
|
30
39
|
## Running Examples
|
|
31
40
|
|
|
32
41
|
Each example directory contains its own README with specific instructions. Generally:
|
data/examples/procedures.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
JSONRPC.configure do |config|
|
|
4
|
+
# Logger instance (default: Logger.new($stdout, progname: 'JSONRPC'))
|
|
5
|
+
config.logger = Logger.new($stdout, progname: 'JSONRPC')
|
|
4
6
|
config.log_internal_errors = true # Log internal error backtraces (default: true)
|
|
5
7
|
config.log_request_validation_errors = true # Log JSON-RPC request validation errors (default: false)
|
|
6
8
|
config.render_internal_errors = true # Render detailed internal error information in responses (default: true)
|
|
@@ -14,7 +16,7 @@ JSONRPC.configure do |config|
|
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
rule(:addends) do
|
|
17
|
-
key.failure('must contain at least
|
|
19
|
+
key.failure('must contain at least two addends') if value.size < 2
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
|
data/examples/rack/Gemfile.lock
CHANGED
|
@@ -1,8 +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)
|
|
7
|
+
multi_json (~> 1.20)
|
|
6
8
|
zeitwerk (~> 2.7)
|
|
7
9
|
|
|
8
10
|
GEM
|
|
@@ -32,6 +34,11 @@ GEM
|
|
|
32
34
|
dry-logic (~> 1.5)
|
|
33
35
|
dry-types (~> 1.8)
|
|
34
36
|
zeitwerk (~> 2.6)
|
|
37
|
+
dry-struct (1.8.0)
|
|
38
|
+
dry-core (~> 1.1)
|
|
39
|
+
dry-types (~> 1.8, >= 1.8.2)
|
|
40
|
+
ice_nine (~> 0.11)
|
|
41
|
+
zeitwerk (~> 2.6)
|
|
35
42
|
dry-types (1.8.3)
|
|
36
43
|
bigdecimal (~> 3.0)
|
|
37
44
|
concurrent-ruby (~> 1.0)
|
|
@@ -45,7 +52,9 @@ GEM
|
|
|
45
52
|
dry-initializer (~> 3.2)
|
|
46
53
|
dry-schema (~> 1.14)
|
|
47
54
|
zeitwerk (~> 2.6)
|
|
55
|
+
ice_nine (0.11.2)
|
|
48
56
|
logger (1.7.0)
|
|
57
|
+
multi_json (1.21.1)
|
|
49
58
|
nio4r (2.7.4)
|
|
50
59
|
puma (6.6.0)
|
|
51
60
|
nio4r (~> 2.0)
|
|
@@ -65,4 +74,4 @@ DEPENDENCIES
|
|
|
65
74
|
rackup
|
|
66
75
|
|
|
67
76
|
BUNDLED WITH
|
|
68
|
-
|
|
77
|
+
4.0.8
|
|
@@ -1,8 +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)
|
|
7
|
+
multi_json (~> 1.20)
|
|
6
8
|
zeitwerk (~> 2.7)
|
|
7
9
|
|
|
8
10
|
GEM
|
|
@@ -32,6 +34,11 @@ GEM
|
|
|
32
34
|
dry-logic (~> 1.5)
|
|
33
35
|
dry-types (~> 1.8)
|
|
34
36
|
zeitwerk (~> 2.6)
|
|
37
|
+
dry-struct (1.8.0)
|
|
38
|
+
dry-core (~> 1.1)
|
|
39
|
+
dry-types (~> 1.8, >= 1.8.2)
|
|
40
|
+
ice_nine (~> 0.11)
|
|
41
|
+
zeitwerk (~> 2.6)
|
|
35
42
|
dry-types (1.8.3)
|
|
36
43
|
bigdecimal (~> 3.0)
|
|
37
44
|
concurrent-ruby (~> 1.0)
|
|
@@ -45,7 +52,9 @@ GEM
|
|
|
45
52
|
dry-initializer (~> 3.2)
|
|
46
53
|
dry-schema (~> 1.14)
|
|
47
54
|
zeitwerk (~> 2.6)
|
|
55
|
+
ice_nine (0.11.2)
|
|
48
56
|
logger (1.7.0)
|
|
57
|
+
multi_json (1.21.1)
|
|
49
58
|
nio4r (2.7.4)
|
|
50
59
|
puma (6.6.0)
|
|
51
60
|
nio4r (~> 2.0)
|
|
@@ -65,4 +74,4 @@ DEPENDENCIES
|
|
|
65
74
|
rackup
|
|
66
75
|
|
|
67
76
|
BUNDLED WITH
|
|
68
|
-
|
|
77
|
+
4.0.8
|
data/examples/rails/Gemfile.lock
CHANGED
|
@@ -1,8 +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)
|
|
7
|
+
multi_json (~> 1.20)
|
|
6
8
|
zeitwerk (~> 2.7)
|
|
7
9
|
|
|
8
10
|
GEM
|
|
@@ -113,6 +115,11 @@ GEM
|
|
|
113
115
|
dry-logic (~> 1.5)
|
|
114
116
|
dry-types (~> 1.8)
|
|
115
117
|
zeitwerk (~> 2.6)
|
|
118
|
+
dry-struct (1.8.0)
|
|
119
|
+
dry-core (~> 1.1)
|
|
120
|
+
dry-types (~> 1.8, >= 1.8.2)
|
|
121
|
+
ice_nine (~> 0.11)
|
|
122
|
+
zeitwerk (~> 2.6)
|
|
116
123
|
dry-types (1.8.3)
|
|
117
124
|
bigdecimal (~> 3.0)
|
|
118
125
|
concurrent-ruby (~> 1.0)
|
|
@@ -132,6 +139,7 @@ GEM
|
|
|
132
139
|
activesupport (>= 6.1)
|
|
133
140
|
i18n (1.14.7)
|
|
134
141
|
concurrent-ruby (~> 1.0)
|
|
142
|
+
ice_nine (0.11.2)
|
|
135
143
|
io-console (0.8.1)
|
|
136
144
|
irb (1.15.2)
|
|
137
145
|
pp (>= 0.6.0)
|
|
@@ -148,7 +156,11 @@ GEM
|
|
|
148
156
|
net-smtp
|
|
149
157
|
marcel (1.0.4)
|
|
150
158
|
mini_mime (1.1.5)
|
|
151
|
-
|
|
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)
|
|
152
164
|
net-imap (0.5.9)
|
|
153
165
|
date
|
|
154
166
|
net-protocol
|
|
@@ -159,25 +171,15 @@ GEM
|
|
|
159
171
|
net-smtp (0.5.1)
|
|
160
172
|
net-protocol
|
|
161
173
|
nio4r (2.7.4)
|
|
162
|
-
nokogiri (1.18.8
|
|
163
|
-
|
|
164
|
-
nokogiri (1.18.8-aarch64-linux-musl)
|
|
165
|
-
racc (~> 1.4)
|
|
166
|
-
nokogiri (1.18.8-arm-linux-gnu)
|
|
167
|
-
racc (~> 1.4)
|
|
168
|
-
nokogiri (1.18.8-arm-linux-musl)
|
|
174
|
+
nokogiri (1.18.8)
|
|
175
|
+
mini_portile2 (~> 2.8.2)
|
|
169
176
|
racc (~> 1.4)
|
|
170
177
|
nokogiri (1.18.8-arm64-darwin)
|
|
171
178
|
racc (~> 1.4)
|
|
172
|
-
nokogiri (1.18.8-x86_64-darwin)
|
|
173
|
-
racc (~> 1.4)
|
|
174
|
-
nokogiri (1.18.8-x86_64-linux-gnu)
|
|
175
|
-
racc (~> 1.4)
|
|
176
|
-
nokogiri (1.18.8-x86_64-linux-musl)
|
|
177
|
-
racc (~> 1.4)
|
|
178
179
|
pp (0.6.2)
|
|
179
180
|
prettyprint
|
|
180
181
|
prettyprint (0.2.0)
|
|
182
|
+
prism (1.9.0)
|
|
181
183
|
psych (5.2.6)
|
|
182
184
|
date
|
|
183
185
|
stringio
|
|
@@ -242,14 +244,7 @@ GEM
|
|
|
242
244
|
zeitwerk (2.7.3)
|
|
243
245
|
|
|
244
246
|
PLATFORMS
|
|
245
|
-
aarch64-linux-gnu
|
|
246
|
-
aarch64-linux-musl
|
|
247
|
-
arm-linux-gnu
|
|
248
|
-
arm-linux-musl
|
|
249
247
|
arm64-darwin
|
|
250
|
-
x86_64-darwin
|
|
251
|
-
x86_64-linux-gnu
|
|
252
|
-
x86_64-linux-musl
|
|
253
248
|
|
|
254
249
|
DEPENDENCIES
|
|
255
250
|
debug
|
|
@@ -258,4 +253,4 @@ DEPENDENCIES
|
|
|
258
253
|
rails (~> 8.0.2)
|
|
259
254
|
|
|
260
255
|
BUNDLED WITH
|
|
261
|
-
|
|
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|
|
|
@@ -10,6 +10,10 @@ Uses constraints to route JSON-RPC requests to different Rails controller action
|
|
|
10
10
|
class App < Rails::Application
|
|
11
11
|
# ...
|
|
12
12
|
routes.append do
|
|
13
|
+
# Handle batch requests
|
|
14
|
+
post '/', to: 'jsonrpc#ping_or_echo', constraints: JSONRPC::BatchConstraint.new
|
|
15
|
+
|
|
16
|
+
# Handle individual method requests
|
|
13
17
|
post '/', to: 'jsonrpc#echo', constraints: JSONRPC::MethodConstraint.new('echo')
|
|
14
18
|
post '/', to: 'jsonrpc#ping', constraints: JSONRPC::MethodConstraint.new('ping')
|
|
15
19
|
end
|
|
@@ -25,6 +29,20 @@ class JsonrpcController < ActionController::Base
|
|
|
25
29
|
def ping
|
|
26
30
|
render jsonrpc: 'pong'
|
|
27
31
|
end
|
|
32
|
+
|
|
33
|
+
# POST /
|
|
34
|
+
def ping_or_echo
|
|
35
|
+
results = jsonrpc_batch.process_each do |request_or_notification|
|
|
36
|
+
case request_or_notification.method
|
|
37
|
+
when 'echo'
|
|
38
|
+
request_or_notification.params
|
|
39
|
+
when 'ping'
|
|
40
|
+
'pong'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
render jsonrpc: results
|
|
45
|
+
end
|
|
28
46
|
end
|
|
29
47
|
```
|
|
30
48
|
|
|
@@ -36,18 +54,35 @@ bundle exec rackup
|
|
|
36
54
|
|
|
37
55
|
## API
|
|
38
56
|
|
|
39
|
-
The server implements
|
|
57
|
+
The server implements these procedures:
|
|
40
58
|
|
|
41
59
|
- `echo` - Returns the input message
|
|
42
|
-
- `ping` - Returns
|
|
60
|
+
- `ping` - Returns `'pong'`
|
|
43
61
|
|
|
44
62
|
## Example Requests
|
|
45
63
|
|
|
64
|
+
Echo request:
|
|
46
65
|
```sh
|
|
47
66
|
curl -X POST http://localhost:9292 \
|
|
48
67
|
-H "Content-Type: application/json" \
|
|
49
68
|
-d '{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Hello, World!"}, "id": 1}'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Ping request:
|
|
72
|
+
```sh
|
|
73
|
+
curl -X POST http://localhost:9292 \
|
|
74
|
+
-H "Content-Type: application/json" \
|
|
75
|
+
-d '{"jsonrpc": "2.0", "method": "ping", "params": {}, "id": 2}'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Batch request with multiple methods:
|
|
79
|
+
```sh
|
|
80
|
+
# Batch request with multiple methods
|
|
50
81
|
curl -X POST http://localhost:9292 \
|
|
51
82
|
-H "Content-Type: application/json" \
|
|
52
|
-
-d '
|
|
83
|
+
-d '[
|
|
84
|
+
{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Hello from batch!"}, "id": 1},
|
|
85
|
+
{"jsonrpc": "2.0", "method": "ping", "params": {}, "id": 2},
|
|
86
|
+
{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Another echo"}, "id": 3}
|
|
87
|
+
]'
|
|
53
88
|
```
|
|
@@ -37,13 +37,17 @@ class App < Rails::Application
|
|
|
37
37
|
config.hosts.clear
|
|
38
38
|
|
|
39
39
|
routes.append do
|
|
40
|
+
# Handle batch requests
|
|
41
|
+
post '/', to: 'jsonrpc#ping_or_echo', constraints: JSONRPC::BatchConstraint.new
|
|
42
|
+
|
|
43
|
+
# Handle individual method requests
|
|
40
44
|
post '/', to: 'jsonrpc#echo', constraints: JSONRPC::MethodConstraint.new('echo')
|
|
41
45
|
post '/', to: 'jsonrpc#ping', constraints: JSONRPC::MethodConstraint.new('ping')
|
|
42
46
|
end
|
|
43
47
|
end
|
|
44
48
|
|
|
45
49
|
# Define the JSONRPC controller
|
|
46
|
-
class JsonrpcController <
|
|
50
|
+
class JsonrpcController < ApplicationController
|
|
47
51
|
def echo
|
|
48
52
|
render jsonrpc: jsonrpc_request.params
|
|
49
53
|
end
|
|
@@ -51,6 +55,19 @@ class JsonrpcController < ActionController::Base
|
|
|
51
55
|
def ping
|
|
52
56
|
render jsonrpc: 'pong'
|
|
53
57
|
end
|
|
58
|
+
|
|
59
|
+
def ping_or_echo
|
|
60
|
+
results = jsonrpc_batch.process_each do |request_or_notification|
|
|
61
|
+
case request_or_notification.method
|
|
62
|
+
when 'echo'
|
|
63
|
+
request_or_notification.params
|
|
64
|
+
when 'ping'
|
|
65
|
+
'pong'
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
render jsonrpc: results
|
|
70
|
+
end
|
|
54
71
|
end
|
|
55
72
|
|
|
56
73
|
App.initialize!
|
|
@@ -1,8 +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)
|
|
7
|
+
multi_json (~> 1.20)
|
|
6
8
|
zeitwerk (~> 2.7)
|
|
7
9
|
|
|
8
10
|
GEM
|
|
@@ -33,6 +35,11 @@ GEM
|
|
|
33
35
|
dry-logic (~> 1.5)
|
|
34
36
|
dry-types (~> 1.8)
|
|
35
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)
|
|
36
43
|
dry-types (1.8.3)
|
|
37
44
|
bigdecimal (~> 3.0)
|
|
38
45
|
concurrent-ruby (~> 1.0)
|
|
@@ -46,8 +53,9 @@ GEM
|
|
|
46
53
|
dry-initializer (~> 3.2)
|
|
47
54
|
dry-schema (~> 1.14)
|
|
48
55
|
zeitwerk (~> 2.6)
|
|
56
|
+
ice_nine (0.11.2)
|
|
49
57
|
logger (1.7.0)
|
|
50
|
-
multi_json (1.
|
|
58
|
+
multi_json (1.21.1)
|
|
51
59
|
mustermann (3.0.3)
|
|
52
60
|
ruby2_keywords (~> 0.0.1)
|
|
53
61
|
nio4r (2.7.4)
|
|
@@ -92,4 +100,4 @@ DEPENDENCIES
|
|
|
92
100
|
sinatra-contrib
|
|
93
101
|
|
|
94
102
|
BUNDLED WITH
|
|
95
|
-
|
|
103
|
+
4.0.8
|
|
@@ -1,8 +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)
|
|
7
|
+
multi_json (~> 1.20)
|
|
6
8
|
zeitwerk (~> 2.7)
|
|
7
9
|
|
|
8
10
|
GEM
|
|
@@ -33,6 +35,11 @@ GEM
|
|
|
33
35
|
dry-logic (~> 1.5)
|
|
34
36
|
dry-types (~> 1.8)
|
|
35
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)
|
|
36
43
|
dry-types (1.8.3)
|
|
37
44
|
bigdecimal (~> 3.0)
|
|
38
45
|
concurrent-ruby (~> 1.0)
|
|
@@ -46,8 +53,9 @@ GEM
|
|
|
46
53
|
dry-initializer (~> 3.2)
|
|
47
54
|
dry-schema (~> 1.14)
|
|
48
55
|
zeitwerk (~> 2.6)
|
|
56
|
+
ice_nine (0.11.2)
|
|
49
57
|
logger (1.7.0)
|
|
50
|
-
multi_json (1.
|
|
58
|
+
multi_json (1.21.1)
|
|
51
59
|
mustermann (3.0.3)
|
|
52
60
|
ruby2_keywords (~> 0.0.1)
|
|
53
61
|
nio4r (2.7.4)
|
|
@@ -92,4 +100,4 @@ DEPENDENCIES
|
|
|
92
100
|
sinatra-contrib
|
|
93
101
|
|
|
94
102
|
BUNDLED WITH
|
|
95
|
-
|
|
103
|
+
4.0.8
|