jsonrpc-middleware 0.3.0 → 0.5.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.
data/README.md CHANGED
@@ -1,12 +1,23 @@
1
- # JSONRPC::Middleware
1
+ <p align="center">
2
+ <a href="https://jsonrpc-middleware.com" target="_blank">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="./.github/images/logo-dark.svg">
5
+ <source media="(prefers-color-scheme: light)" srcset="./.github/images/logo-light.svg">
6
+ <img alt="JSON-RPC Middleware Logo" src="./.github/images/logo-light.svg" width="600" height="120" style="max-width: 100%;">
7
+ </picture>
8
+ </a>
9
+ </p>
10
+
11
+ <div align="center">
2
12
 
3
13
  [![Gem Version](https://badge.fury.io/rb/jsonrpc-middleware.svg)](https://badge.fury.io/rb/jsonrpc-middleware)
4
14
  ![Build](https://github.com/wilsonsilva/jsonrpc-middleware/actions/workflows/main.yml/badge.svg)
5
15
  [![Maintainability](https://qlty.sh/badges/a275de81-94e3-45af-9469-523aa5345871/maintainability.svg)](https://qlty.sh/gh/wilsonsilva/projects/jsonrpc-middleware)
6
16
  [![Code Coverage](https://qlty.sh/badges/a275de81-94e3-45af-9469-523aa5345871/test_coverage.svg)](https://qlty.sh/gh/wilsonsilva/projects/jsonrpc-middleware)
7
17
 
8
- A Ruby implementation of the JSON-RPC protocol, enabling standardized communication between systems via remote procedure
9
- calls encoded in JSON.
18
+ </div>
19
+
20
+ A Rack middleware implementing the JSON-RPC 2.0 protocol that integrates easily with all Rack-based applications (Rails, Sinatra, Hanami, etc).
10
21
 
11
22
  ## Table of contents
12
23
 
@@ -26,10 +37,29 @@ calls encoded in JSON.
26
37
  - **Spec-compliant**: Fully implements the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification)
27
38
  - **Rack middleware integration**: Seamlessly integrates with Rack applications (Rails, Sinatra, Hanami, etc)
28
39
  - **Support for all request types**: Handles single requests, notifications, and batch requests
40
+ - **Rails routing DSL**: Elegant routing DSL for Rails applications with support for namespaces and batch handling
29
41
  - **Error handling**: Comprehensive error handling with standard JSON-RPC error responses
30
42
  - **Request validation**: Define request parameter specifications and validations
31
43
  - **Helpers**: Convenient helper methods to simplify request and response processing
32
44
 
45
+ ## 🏗️ Architecture
46
+
47
+ The gem integrates seamlessly into your Rack-based application:
48
+
49
+ ```mermaid
50
+ block-beta
51
+ columns 4
52
+
53
+ App["Your app"]:4
54
+ Rails:1 Sinatra:1 RackApp["Other Rack-compatible framework"]:2
55
+ Middleware["JSON-RPC Middleware"]:4
56
+ Rack["Rack"]:4
57
+ HTTP["HTTP"]:4
58
+
59
+ classDef middlewareStyle fill:#ff6b6b,stroke:#d63031,stroke-width:2px,color:#fff
60
+ class Middleware middlewareStyle
61
+ ```
62
+
33
63
  ## 📦 Installation
34
64
 
35
65
  Install the gem and add to the application's Gemfile by executing:
@@ -78,31 +108,26 @@ class App
78
108
  @env = env
79
109
 
80
110
  if jsonrpc_request?
81
- result = handle_single(jsonrpc_request)
82
- jsonrpc_response(result)
111
+ sum = add(jsonrpc_request.params)
112
+ jsonrpc_response(sum)
83
113
  elsif jsonrpc_notification?
84
- handle_single(jsonrpc_notification)
114
+ add(jsonrpc_notification.params)
85
115
  jsonrpc_notification_response
86
116
  else
87
- responses = handle_batch(jsonrpc_batch)
88
- jsonrpc_batch_response(responses)
117
+ results = add_in_batches(jsonrpc_batch)
118
+ jsonrpc_batch_response(results)
89
119
  end
90
120
  end
91
121
 
92
122
  private
93
123
 
94
- def handle_single(request_or_notification)
95
- params = request_or_notification.params
96
-
124
+ def add(params)
97
125
  addends = params.is_a?(Array) ? params : params['addends'] # Handle positional and named arguments
98
126
  addends.sum
99
127
  end
100
128
 
101
- def handle_batch(batch)
102
- batch.flat_map do |request_or_notification|
103
- result = handle_single(request_or_notification)
104
- JSONRPC::Response.new(id: request_or_notification.id, result:) if request_or_notification.is_a?(JSONRPC::Request)
105
- end.compact
129
+ def add_in_batches(batch)
130
+ batch.process_each { |request_or_notification| add(request_or_notification.params) }
106
131
  end
107
132
  end
108
133
 
@@ -110,9 +135,14 @@ use JSONRPC::Middleware
110
135
  run App.new
111
136
  ```
112
137
 
113
- This will give you a fully-featured JSON-RPC server.
138
+ This will give you a fully-featured JSON-RPC server, capable of:
139
+ - Handling JSON-RPC requests, notifications __and batches__
140
+ - Validating the allowed JSON-RPC methods (e.g. allow only `add`)
141
+ - Validating the JSON-RPC method parameters (e.g. allow only non-empty arrays of numbers)
142
+ - Accept positional and named parameters (`params: [5, 5]`, `params: { addends: [5, 5] }`)
143
+ - Respond successfully or erroneously, according to the specification
114
144
 
115
- For more advanced setups, check the [examples](https://github.com/wilsonsilva/jsonrpc-middleware/blob/main/examples/README.md).
145
+ For more advanced setups, or other frameworks such as Rails or Sinatra, check the [examples](https://github.com/wilsonsilva/jsonrpc-middleware/blob/main/examples/README.md).
116
146
 
117
147
  ## 📚 Documentation
118
148
 
@@ -145,6 +175,7 @@ rake bundle:audit:update # Updates the bundler-audit vulnerability database
145
175
  rake clean # Remove any temporary products
146
176
  rake clobber # Remove any generated files
147
177
  rake coverage # Run spec with coverage
178
+ rake examples:bundle_install # Run bundle install on all example folders (useful after updating the gem version)
148
179
  rake install # Build and install jsonrpc-middleware.gem into system gems
149
180
  rake install:local # Build and install jsonrpc-middleware.gem into system gems without network access
150
181
  rake qa # Test, lint and perform security and documentation audits
data/Rakefile CHANGED
@@ -14,9 +14,7 @@ yardstick_options = YAML.load_file('.yardstick.yml')
14
14
 
15
15
  Bundler::Audit::Task.new
16
16
  RSpec::Core::RakeTask.new(:spec)
17
- RuboCop::RakeTask.new do |task|
18
- task.requires << 'rubocop-yard'
19
- end
17
+ RuboCop::RakeTask.new
20
18
  YARD::Rake::YardocTask.new
21
19
  YardJunk::Rake.define_task
22
20
  Yardstick::Rake::Measurement.new(:yardstick_measure, yardstick_options)
@@ -97,3 +95,59 @@ namespace :yard do
97
95
  puts 'Done!'
98
96
  end
99
97
  end
98
+
99
+ namespace :examples do
100
+ desc 'Run bundle install on all example folders'
101
+ task :bundle_install do
102
+ examples_dir = File.join(Dir.pwd, 'examples')
103
+
104
+ unless Dir.exist?(examples_dir)
105
+ puts 'Examples directory not found'
106
+ exit 1
107
+ end
108
+
109
+ example_folders = Dir.glob(File.join(examples_dir, '*')).select { |path| Dir.exist?(path) }
110
+
111
+ if example_folders.empty?
112
+ puts 'No example folders found'
113
+ return
114
+ end
115
+
116
+ puts "Found #{example_folders.length} example folders:"
117
+ example_folders.each { |folder| puts " - #{File.basename(folder)}" }
118
+ puts
119
+
120
+ failed_folders = []
121
+
122
+ example_folders.each do |folder|
123
+ gemfile_path = File.join(folder, 'Gemfile')
124
+
125
+ unless File.exist?(gemfile_path)
126
+ puts "Skipping #{File.basename(folder)} - no Gemfile found"
127
+ next
128
+ end
129
+
130
+ puts "Running bundle install in #{File.basename(folder)}..."
131
+
132
+ Dir.chdir(folder) do
133
+ system('bundle install')
134
+
135
+ unless $?.success?
136
+ failed_folders << File.basename(folder)
137
+ puts " ✗ Failed to bundle install in #{File.basename(folder)}"
138
+ else
139
+ puts " ✓ Successfully installed gems in #{File.basename(folder)}"
140
+ end
141
+ end
142
+
143
+ puts
144
+ end
145
+
146
+ if failed_folders.empty?
147
+ puts 'All example folders processed successfully!'
148
+ else
149
+ puts "Failed to process #{failed_folders.length} folders: #{failed_folders.join(', ')}"
150
+ exit 1
151
+ end
152
+ end
153
+ end
@@ -52,9 +52,5 @@ JSONRPC.configure do |config|
52
52
  end
53
53
 
54
54
  # Used only to test internal server errors
55
- procedure(:explode) do
56
- params do
57
- # No params
58
- end
59
- end
55
+ procedure(:explode)
60
56
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- jsonrpc-middleware (0.2.0)
4
+ jsonrpc-middleware (0.4.0)
5
5
  dry-validation (~> 1.11)
6
6
  zeitwerk (~> 2.7)
7
7
 
data/examples/rack/app.rb CHANGED
@@ -40,9 +40,6 @@ class App
40
40
  end
41
41
 
42
42
  def handle_batch(batch)
43
- batch.flat_map do |request_or_notification|
44
- result = handle_single(request_or_notification)
45
- JSONRPC::Response.new(id: request_or_notification.id, result:) if request_or_notification.is_a?(JSONRPC::Request)
46
- end.compact
43
+ batch.process_each { |request_or_notification| handle_single(request_or_notification) }
47
44
  end
48
45
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- jsonrpc-middleware (0.2.0)
4
+ jsonrpc-middleware (0.4.0)
5
5
  dry-validation (~> 1.11)
6
6
  zeitwerk (~> 2.7)
7
7
 
@@ -27,10 +27,7 @@ class App
27
27
  end
28
28
 
29
29
  def handle_batch(batch)
30
- batch.flat_map do |request_or_notification|
31
- result = handle_single(request_or_notification)
32
- JSONRPC::Response.new(id: request_or_notification.id, result:) if request_or_notification.is_a?(JSONRPC::Request)
33
- end.compact
30
+ batch.process_each { |request_or_notification| handle_single(request_or_notification) }
34
31
  end
35
32
  end
36
33
 
@@ -43,10 +43,7 @@ class App
43
43
  def handle_single(request_or_notification) = request_or_notification.params
44
44
 
45
45
  def handle_batch(batch)
46
- batch.flat_map do |request_or_notification|
47
- result = handle_single(request_or_notification)
48
- JSONRPC::Response.new(id: request_or_notification.id, result:) if request_or_notification.is_a?(JSONRPC::Request)
49
- end.compact
46
+ batch.process_each { |request_or_notification| handle_single(request_or_notification) }
50
47
  end
51
48
  end
52
49
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- jsonrpc-middleware (0.2.0)
4
+ jsonrpc-middleware (0.4.0)
5
5
  dry-validation (~> 1.11)
6
6
  zeitwerk (~> 2.7)
7
7
 
@@ -36,9 +36,6 @@ class JsonrpcController < ApplicationController
36
36
  end
37
37
 
38
38
  def handle_batch(batch)
39
- batch.flat_map do |request_or_notification|
40
- result = handle_single(request_or_notification)
41
- JSONRPC::Response.new(id: request_or_notification.id, result:) if request_or_notification.is_a?(JSONRPC::Request)
42
- end.compact
39
+ batch.process_each { |request_or_notification| handle_single(request_or_notification) }
43
40
  end
44
41
  end
@@ -54,9 +54,5 @@ require_relative '../../../procedures'
54
54
  # end
55
55
  #
56
56
  # # Used only to test internal server errors
57
- # procedure(:explode) do
58
- # params do
59
- # # No params
60
- # end
61
- # end
57
+ # procedure(:explode)
62
58
  # end
@@ -0,0 +1,199 @@
1
+ # Rails JSON-RPC Routing DSL
2
+
3
+ Demonstrates using the Rails routing DSL extension to route JSON-RPC methods to different controller actions for a
4
+ smart home control system.
5
+
6
+ ## Highlights
7
+
8
+ Uses the `jsonrpc` routing DSL to map JSON-RPC methods to Rails controller actions with clean, readable syntax:
9
+
10
+ ```ruby
11
+ class App < Rails::Application
12
+ # ...
13
+ routes.append do
14
+ jsonrpc '/' do
15
+ # Handle batch requests with a dedicated controller
16
+ batch to: 'batch#handle'
17
+
18
+ method 'on', to: 'main#on'
19
+ method 'off', to: 'main#off'
20
+
21
+ namespace 'lights' do
22
+ method 'on', to: 'lights#on' # becomes lights.on
23
+ method 'off', to: 'lights#off' # becomes lights.off
24
+ end
25
+
26
+ namespace 'climate' do
27
+ method 'on', to: 'climate#on' # becomes climate.on
28
+ method 'off', to: 'climate#off' # becomes climate.off
29
+
30
+ namespace 'fan' do
31
+ method 'on', to: 'fan#on' # becomes climate.fan.on
32
+ method 'off', to: 'fan#off' # becomes climate.fan.off
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ class MainController < ActionController::Base
40
+ def on
41
+ render jsonrpc: { device: 'main_system', status: 'on' }
42
+ end
43
+
44
+ def off
45
+ render jsonrpc: { device: 'main_system', status: 'off' }
46
+ end
47
+ end
48
+
49
+ class LightsController < ActionController::Base
50
+ def on
51
+ render jsonrpc: { device: 'lights', status: 'on' }
52
+ end
53
+
54
+ def off
55
+ render jsonrpc: { device: 'lights', status: 'off' }
56
+ end
57
+ end
58
+
59
+ class ClimateController < ActionController::Base
60
+ def on
61
+ render jsonrpc: { device: 'climate_system', status: 'on' }
62
+ end
63
+
64
+ def off
65
+ render jsonrpc: { device: 'climate_system', status: 'off' }
66
+ end
67
+ end
68
+
69
+ class FanController < ActionController::Base
70
+ def on
71
+ render jsonrpc: { device: 'fan', status: 'on' }
72
+ end
73
+
74
+ def off
75
+ render jsonrpc: { device: 'fan', status: 'off' }
76
+ end
77
+ end
78
+
79
+ class BatchController < ActionController::Base
80
+ def handle
81
+ # Process each request in the batch and collect results
82
+ results = jsonrpc_batch.process_each do |request_or_notification|
83
+ case request_or_notification.method
84
+ when 'on'
85
+ { device: 'main_system', status: 'on' }
86
+ when 'off'
87
+ { device: 'main_system', status: 'off' }
88
+ when 'lights.on'
89
+ { device: 'lights', status: 'on' }
90
+ when 'lights.off'
91
+ { device: 'lights', status: 'off' }
92
+ # ... handle other methods
93
+ end
94
+ end
95
+
96
+ render jsonrpc: results
97
+ end
98
+ end
99
+ ```
100
+
101
+ ## Running
102
+
103
+ ```sh
104
+ bundle exec rackup
105
+ ```
106
+
107
+ ## API
108
+
109
+ The server implements smart home controls with these procedures:
110
+
111
+ **Root Methods:**
112
+ - `on` - Turn home automation system on
113
+ - `off` - Turn home automation system off
114
+
115
+ **Lights Namespace:**
116
+ - `lights.on` - Turn lights on
117
+ - `lights.off` - Turn lights off
118
+
119
+ **Climate Namespace:**
120
+ - `climate.on` - Turn climate system on
121
+ - `climate.off` - Turn climate system off
122
+
123
+ **Climate Fan Namespace:**
124
+ - `climate.fan.on` - Turn fan on
125
+ - `climate.fan.off` - Turn fan off
126
+
127
+ **Batch Processing:**
128
+ - Batch requests are automatically routed to the `BatchController#handle` action
129
+ - The controller uses `jsonrpc_batch.process_each` to handle each request in the batch
130
+ - Responses are collected and returned as an array
131
+
132
+ ## Example Requests
133
+
134
+ Turn on the home automation system:
135
+ ```sh
136
+ curl -X POST http://localhost:9292 \
137
+ -H "Content-Type: application/json" \
138
+ -d '{"jsonrpc": "2.0", "method": "on", "params": {}, "id": 1}'
139
+ ```
140
+
141
+ Turn off the home automation system:
142
+ ```sh
143
+ curl -X POST http://localhost:9292 \
144
+ -H "Content-Type: application/json" \
145
+ -d '{"jsonrpc": "2.0", "method": "off", "params": {}, "id": 2}'
146
+ ```
147
+
148
+ Turn on lights:
149
+ ```sh
150
+ curl -X POST http://localhost:9292 \
151
+ -H "Content-Type: application/json" \
152
+ -d '{"jsonrpc": "2.0", "method": "lights.on", "params": {}, "id": 3}'
153
+ ```
154
+
155
+ Turn off the lights:
156
+ ```sh
157
+ curl -X POST http://localhost:9292 \
158
+ -H "Content-Type: application/json" \
159
+ -d '{"jsonrpc": "2.0", "method": "lights.off", "params": {}, "id": 4}'
160
+ ```
161
+
162
+ Turn on the climate system:
163
+ ```sh
164
+ curl -X POST http://localhost:9292 \
165
+ -H "Content-Type: application/json" \
166
+ -d '{"jsonrpc": "2.0", "method": "climate.on", "params": {}, "id": 5}'
167
+ ```
168
+
169
+ Turn off the climate system:
170
+ ```sh
171
+ curl -X POST http://localhost:9292 \
172
+ -H "Content-Type: application/json" \
173
+ -d '{"jsonrpc": "2.0", "method": "climate.off", "params": {}, "id": 6}'
174
+ ```
175
+
176
+ Turn on fan:
177
+ ```sh
178
+ curl -X POST http://localhost:9292 \
179
+ -H "Content-Type: application/json" \
180
+ -d '{"jsonrpc": "2.0", "method": "climate.fan.on", "params": {}, "id": 7}'
181
+ ```
182
+
183
+ Turn off fan:
184
+ ```sh
185
+ curl -X POST http://localhost:9292 \
186
+ -H "Content-Type: application/json" \
187
+ -d '{"jsonrpc": "2.0", "method": "climate.fan.off", "params": {}, "id": 8}'
188
+ ```
189
+
190
+ Batch request for evening routine:
191
+ ```sh
192
+ curl -X POST http://localhost:9292 \
193
+ -H "Content-Type: application/json" \
194
+ -d '[
195
+ {"jsonrpc": "2.0", "method": "off", "params": {}, "id": 9},
196
+ {"jsonrpc": "2.0", "method": "lights.off", "params": {}, "id": 10},
197
+ {"jsonrpc": "2.0", "method": "climate.off", "params": {}, "id": 11}
198
+ ]'
199
+ ```
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile(true) do
6
+ source 'https://rubygems.org'
7
+
8
+ gem 'rails', '~> 8.0.2'
9
+ gem 'puma', '~> 6.6.0'
10
+ gem 'jsonrpc-middleware', path: '../../', require: 'jsonrpc'
11
+ end
12
+
13
+ require 'rails'
14
+ require 'action_controller/railtie'
15
+
16
+ JSONRPC.configure do |config|
17
+ config.rescue_internal_errors = true # set to +false+ if you want to raise JSONRPC::InternalError manually
18
+
19
+ # Define the allowed JSON-RPC methods. Calls to methods absent from this list will return a method not found error.
20
+ procedure 'on'
21
+ procedure 'off'
22
+ procedure 'lights.on'
23
+ procedure 'lights.off'
24
+ procedure 'climate.on'
25
+ procedure 'climate.off'
26
+ procedure 'climate.fan.on'
27
+ procedure 'climate.fan.off'
28
+ end
29
+
30
+ # Define the application
31
+ class App < Rails::Application
32
+ config.root = __dir__
33
+ config.cache_classes = true
34
+ config.eager_load = true
35
+ config.active_support.deprecation = :stderr
36
+ config.consider_all_requests_local = true
37
+ config.active_support.to_time_preserves_timezone = :zone
38
+ config.logger = nil
39
+ config.hosts.clear
40
+
41
+ routes.append do
42
+ jsonrpc '/' do
43
+ # Handle batch requests with a dedicated controller
44
+ batch to: 'batch#handle'
45
+
46
+ method :on, to: 'main#on'
47
+ method :off, to: 'main#off'
48
+
49
+ namespace 'lights' do
50
+ method :on, to: 'lights#on' # becomes lights.on
51
+ method :off, to: 'lights#off' # becomes lights.off
52
+ end
53
+
54
+ namespace 'climate' do
55
+ method :on, to: 'climate#on' # becomes climate.on
56
+ method :off, to: 'climate#off' # becomes climate.off
57
+
58
+ namespace 'fan' do
59
+ method :on, to: 'fan#on' # becomes climate.fan.on
60
+ method :off, to: 'fan#off' # becomes climate.fan.off
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ # Controller for main system operations
68
+ class MainController < ActionController::Base
69
+ def on
70
+ render jsonrpc: { device: 'main_system', status: 'on' }
71
+ end
72
+
73
+ def off
74
+ render jsonrpc: { device: 'main_system', status: 'off' }
75
+ end
76
+ end
77
+
78
+ # Controller for lights operations
79
+ class LightsController < ActionController::Base
80
+ def on
81
+ render jsonrpc: { device: 'lights', status: 'on' }
82
+ end
83
+
84
+ def off
85
+ render jsonrpc: { device: 'lights', status: 'off' }
86
+ end
87
+ end
88
+
89
+ # Controller for climate operations
90
+ class ClimateController < ActionController::Base
91
+ def on
92
+ render jsonrpc: { device: 'climate_system', status: 'on' }
93
+ end
94
+
95
+ def off
96
+ render jsonrpc: { device: 'climate_system', status: 'off' }
97
+ end
98
+ end
99
+
100
+ # Controller for climate fan operations
101
+ class FanController < ActionController::Base
102
+ def on
103
+ render jsonrpc: { device: 'fan', status: 'on' }
104
+ end
105
+
106
+ def off
107
+ render jsonrpc: { device: 'fan', status: 'off' }
108
+ end
109
+ end
110
+
111
+ # Controller for batch operations
112
+ class BatchController < ActionController::Base
113
+ def handle
114
+ # Process each request in the batch and collect results
115
+ results = jsonrpc_batch.process_each do |request_or_notification|
116
+ result = case request_or_notification.method
117
+ when 'on'
118
+ { device: 'main_system', status: 'on' }
119
+ when 'off'
120
+ { device: 'main_system', status: 'off' }
121
+ when 'lights.on'
122
+ { device: 'lights', status: 'on' }
123
+ when 'lights.off'
124
+ { device: 'lights', status: 'off' }
125
+ when 'climate.on'
126
+ { device: 'climate_system', status: 'on' }
127
+ when 'climate.off'
128
+ { device: 'climate_system', status: 'off' }
129
+ when 'climate.fan.on'
130
+ { device: 'fan', status: 'on' }
131
+ when 'climate.fan.off'
132
+ { device: 'fan', status: 'off' }
133
+ else
134
+ { error: 'Unknown method', method: request_or_notification.method }
135
+ end
136
+
137
+ result
138
+ end
139
+
140
+ render jsonrpc: results
141
+ end
142
+ end
143
+
144
+ App.initialize!
145
+
146
+ run App
@@ -59,10 +59,7 @@ class JsonrpcController < ActionController::Base
59
59
  def handle_single(request_or_notification) = request_or_notification.params
60
60
 
61
61
  def handle_batch(batch)
62
- batch.flat_map do |request_or_notification|
63
- result = handle_single(request_or_notification)
64
- JSONRPC::Response.new(id: request_or_notification.id, result:) if request_or_notification.is_a?(JSONRPC::Request)
65
- end.compact
62
+ batch.process_each { |request_or_notification| handle_single(request_or_notification) }
66
63
  end
67
64
  end
68
65
 
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  class JsonrpcController < ActionController::Base
19
19
  # POST /
20
- def echoc
20
+ def echo
21
21
  render jsonrpc: jsonrpc_request.params
22
22
  end
23
23
 
@@ -22,11 +22,7 @@ JSONRPC.configure do |config|
22
22
  end
23
23
  end
24
24
 
25
- procedure(:ping) do
26
- params do
27
- # no params
28
- end
29
- end
25
+ procedure(:ping)
30
26
  end
31
27
 
32
28
  # Define the application
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- jsonrpc-middleware (0.2.0)
4
+ jsonrpc-middleware (0.4.0)
5
5
  dry-validation (~> 1.11)
6
6
  zeitwerk (~> 2.7)
7
7