jsonrpc-rails 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/README.md +2 -2
- data/lib/jsonrpc-rails.rb +1 -3
- data/lib/jsonrpc_rails/middleware/validator.rb +43 -30
- data/lib/jsonrpc_rails/railtie.rb +2 -2
- data/lib/jsonrpc_rails/version.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c7eaabe38b79dd41bac2752a456d5278e6cc780c3d2ebbe0493c349ff24ee10
|
4
|
+
data.tar.gz: 51797ce9c50cd5e51b248f8a4376880f7ffcf19245daa8ae2ef1a4b9d5d17cdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a55b1b369ff4d277b3351c6632a858bd00244cd0799108fbeaf4e64ba2e5b39c4687be0f1855e96df90343541e8ac0ab137684cad4f7af7394a75612b367395
|
7
|
+
data.tar.gz: 9883f5c131ab3437cde5410f82a21f072824a045e1680ad27d81ef1f4d10d471149a7db639c18d8e2d194586979919224c4e921bae263236023d71934d2a6cc5
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ It integrates into Rails, allowing you to render JSON-RPC responses and validate
|
|
10
10
|
- **Rails Integration:** Easily integrate JSON-RPC 2.0 support via a Rails Railtie.
|
11
11
|
- **Custom Renderer:** Render responses with `render jsonrpc:`, automatically wrapping data in the JSON-RPC 2.0 envelope.
|
12
12
|
- **Error Handling:** Built-in support for both success and error responses according to the JSON-RPC 2.0 specification.
|
13
|
-
- **Request Validation:** Includes middleware (`
|
13
|
+
- **Request Validation:** Includes middleware (`JSONRPC_Rails::Middleware::Validator`) to strictly validate incoming JSON-RPC 2.0 requests (single and batch) against the specification structure.
|
14
14
|
- **Rails 8+ Compatibility:** Designed specifically for Rails 8 and later versions.
|
15
15
|
|
16
16
|
## Installation
|
@@ -81,7 +81,7 @@ You can override the default `message` or add `data` for either method by provid
|
|
81
81
|
|
82
82
|
### Handling Requests
|
83
83
|
|
84
|
-
The gem automatically inserts `
|
84
|
+
The gem automatically inserts `JSONRPC_Rails::Middleware::Validator` into your application's middleware stack. This middleware performs the following actions for incoming **POST** requests with `Content-Type: application/json`:
|
85
85
|
|
86
86
|
1. **Parses** the JSON body. Returns a JSON-RPC `Parse error (-32700)` if parsing fails.
|
87
87
|
2. **Validates** the structure against the JSON-RPC 2.0 specification (single or batch). It performs strict validation, ensuring `jsonrpc: "2.0"`, a string `method`, optional `params` (array/object), optional `id` (string/number/null), and **no extraneous keys**. Returns a JSON-RPC `Invalid Request (-32600)` error if validation fails. **Note:** For batch requests, if *any* individual request within the batch is structurally invalid, the entire batch is rejected with a single `Invalid Request (-32600)` error.
|
data/lib/jsonrpc-rails.rb
CHANGED
@@ -7,7 +7,5 @@ require_relative "json_rpc/request"
|
|
7
7
|
require_relative "json_rpc/response"
|
8
8
|
require_relative "json_rpc/notification"
|
9
9
|
|
10
|
-
|
11
|
-
module JSON_RPC_Rails
|
12
|
-
# You might add gem-level configuration or methods here if needed later.
|
10
|
+
module JSONRPC_Rails
|
13
11
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "json"
|
4
|
+
require "active_support/json"
|
4
5
|
|
5
|
-
module
|
6
|
+
module JSONRPC_Rails
|
6
7
|
module Middleware
|
7
8
|
# Rack middleware to strictly validate incoming JSON-RPC 2.0 requests.
|
8
9
|
# It checks for correct Content-Type, parses JSON, and validates the structure
|
@@ -17,40 +18,54 @@ module JSON_RPC_Rails
|
|
17
18
|
# Other valid JSON payloads (e.g., strings, numbers, booleans, null) are passed through.
|
18
19
|
class Validator
|
19
20
|
CONTENT_TYPE = "application/json"
|
20
|
-
ENV_PAYLOAD_KEY = "jsonrpc.payload"
|
21
|
+
ENV_PAYLOAD_KEY = :"jsonrpc.payload"
|
21
22
|
|
22
23
|
def initialize(app)
|
23
24
|
@app = app
|
24
25
|
end
|
25
26
|
|
26
27
|
def call(env)
|
27
|
-
request = Rack::Request.new(env)
|
28
|
-
|
29
28
|
# Only process POST requests with the correct Content-Type
|
30
|
-
|
31
|
-
|
32
|
-
end
|
29
|
+
return @app.call(env) unless env["REQUEST_METHOD"] == "POST" &&
|
30
|
+
env["CONTENT_TYPE"]&.start_with?(CONTENT_TYPE)
|
33
31
|
|
34
32
|
# Read and parse the request body
|
35
|
-
|
36
|
-
|
33
|
+
# Safely read and rewind
|
34
|
+
body = env["rack.input"].read
|
35
|
+
env["rack.input"].rewind
|
37
36
|
payload = parse_json(body)
|
38
37
|
|
39
38
|
# Handle JSON parsing errors
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
# If parsing fails (returns nil), pass through
|
40
|
+
return @app.call(env) unless payload
|
41
|
+
|
42
|
+
# Determine if we should proceed with strict validation based on payload type and content
|
43
|
+
should_validate = false
|
44
|
+
is_batch = false
|
45
|
+
|
46
|
+
case payload
|
47
|
+
when Hash
|
48
|
+
# Validate single Hash only if 'jsonrpc' key is present
|
49
|
+
should_validate = payload.key?("jsonrpc")
|
50
|
+
is_batch = false
|
51
|
+
when Array
|
52
|
+
# Validate Array only if ALL elements are Hashes AND at least one has 'jsonrpc' key
|
53
|
+
all_hashes = payload.all? { |el| el.is_a?(Hash) }
|
54
|
+
any_jsonrpc = payload.any? { |el| el.is_a?(Hash) && el.key?("jsonrpc") }
|
55
|
+
if all_hashes && any_jsonrpc
|
56
|
+
should_validate = true
|
57
|
+
is_batch = true
|
58
|
+
end
|
59
|
+
# Note: Empty arrays or arrays not meeting the criteria will pass through
|
46
60
|
end
|
47
61
|
|
48
|
-
#
|
49
|
-
|
50
|
-
|
62
|
+
# If conditions for validation are not met, pass through
|
63
|
+
return @app.call(env) unless should_validate
|
64
|
+
|
65
|
+
# --- Proceed with strict validation ---
|
51
66
|
validation_result, _ = is_batch ? validate_batch(payload) : validate_single(payload)
|
52
67
|
|
53
|
-
# If validation failed, return the
|
68
|
+
# If strict validation failed (e.g., wrong version, missing method, invalid batch element), return the error
|
54
69
|
return validation_result unless validation_result == :valid
|
55
70
|
|
56
71
|
# Store the validated payload (original structure) in env for the controller
|
@@ -62,14 +77,13 @@ module JSON_RPC_Rails
|
|
62
77
|
|
63
78
|
private
|
64
79
|
|
65
|
-
#
|
66
|
-
|
67
|
-
# Parses the JSON body string. Returns parsed data or nil on failure.
|
80
|
+
# Parses the JSON body string using ActiveSupport::JSON. Returns parsed data or nil on failure.
|
68
81
|
def parse_json(body)
|
69
82
|
return nil if body.nil? || body.strip.empty?
|
70
83
|
|
71
|
-
JSON.
|
72
|
-
rescue JSON
|
84
|
+
ActiveSupport::JSON.decode(body)
|
85
|
+
rescue ActiveSupport::JSON.parse_error
|
86
|
+
# Return nil if parsing fails, allowing the request to pass through
|
73
87
|
nil
|
74
88
|
end
|
75
89
|
|
@@ -92,8 +106,8 @@ module JSON_RPC_Rails
|
|
92
106
|
return false
|
93
107
|
end
|
94
108
|
|
95
|
-
# Optional 'id' must be a String, Number (Integer
|
96
|
-
if obj.key?("id") && ![ String, Integer,
|
109
|
+
# Optional 'id' must be a String, Number (Integer), or Null if present
|
110
|
+
if obj.key?("id") && ![ String, Integer, NilClass ].include?(obj["id"].class)
|
97
111
|
return false
|
98
112
|
end
|
99
113
|
|
@@ -152,11 +166,10 @@ module JSON_RPC_Rails
|
|
152
166
|
JSON_RPC::JsonRpcError.new(error_type)
|
153
167
|
end
|
154
168
|
|
155
|
-
response_body =
|
156
|
-
|
169
|
+
response_body = JSON_RPC::Response.new(
|
170
|
+
id: nil, # Middleware errors have null id
|
157
171
|
error: error_obj.to_h,
|
158
|
-
|
159
|
-
}.to_json
|
172
|
+
).to_json
|
160
173
|
|
161
174
|
[
|
162
175
|
status,
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require_relative "middleware/validator"
|
2
2
|
|
3
|
-
module
|
3
|
+
module JSONRPC_Rails
|
4
4
|
# Use Rails::Railtie to integrate with the Rails application
|
5
5
|
class Railtie < Rails::Railtie
|
6
6
|
# Insert the JSON-RPC Validator middleware early in the stack.
|
7
7
|
# Inserting before Rack::Sendfile, which is typically present early in the stack.
|
8
8
|
initializer "jsonrpc-rails.add_validator_middleware" do |app|
|
9
|
-
app.middleware.use
|
9
|
+
app.middleware.use JSONRPC_Rails::Middleware::Validator
|
10
10
|
end
|
11
11
|
|
12
12
|
initializer "jsonrpc-rails.add_renderers" do
|
@@ -1,3 +1,3 @@
|
|
1
|
-
module
|
2
|
-
VERSION = "0.
|
1
|
+
module JSONRPC_Rails
|
2
|
+
VERSION = "0.2.0"
|
3
3
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsonrpc-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: railties
|
@@ -65,7 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: '0'
|
67
67
|
requirements: []
|
68
|
-
rubygems_version: 3.6.
|
68
|
+
rubygems_version: 3.6.7
|
69
69
|
specification_version: 4
|
70
70
|
summary: A Railtie-based gem that brings JSON-RPC 2.0 support to your Rails application.
|
71
71
|
test_files: []
|