jrpc 2.1.0 → 2.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/CHANGELOG.md +18 -1
- data/Gemfile +3 -4
- data/README.md +9 -2
- data/lib/jrpc/errors.rb +19 -12
- data/lib/jrpc/message.rb +11 -7
- data/lib/jrpc/transport/test.rb +6 -4
- data/lib/jrpc/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84a616f81dad776fc7efea4d4e8fd778a3e2d5b42568118f0206f44f9b4e1b10
|
|
4
|
+
data.tar.gz: b8e8a2d8468d5e713e9015faccea22370775b99e476f17b4962cc0ebdc504d35
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a58ecaa54dcaafae9871d5c7264e03adc57946859b75b72112a79bc7595df81495e5a4910fe69da28b66bf1b82c0cdb3026a5ccc0ea4f6786e81c50fea030413
|
|
7
|
+
data.tar.gz: abc7911d9cc8ffac7481decc11e01fc7524b1ce800c65c5bf7652c3567adad66ceedae7c63353f6f160a123957528254434807e58911dbaa61c221e3ee30727f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
###
|
|
3
|
+
### 2.2.0
|
|
4
|
+
|
|
5
|
+
**New**
|
|
6
|
+
|
|
7
|
+
* `JRPC::Errors::ServerError#data` — the JSON-RPC `error.data` member is now carried
|
|
8
|
+
onto the raised exception instead of being dropped. `Message.error_to_exception`
|
|
9
|
+
reads `error['data']` and passes it to every `ServerError` subclass built from a peer
|
|
10
|
+
error object, verbatim and untyped (String, Hash, Array, … — whatever the peer sent),
|
|
11
|
+
`nil` when omitted. It is the only machine-readable detail an error object carries
|
|
12
|
+
beyond `code`, and servers use it to say *which* param was invalid or *which* id
|
|
13
|
+
conflicted. `MalformedResponseError` is raised locally rather than mapped from a peer
|
|
14
|
+
error object, so its `data` is always `nil`.
|
|
15
|
+
`JRPC::Transport::Test` emits a `data` member when a handler raises an error that
|
|
16
|
+
carries one, so the round trip is testable. Backwards compatible: on those classes
|
|
17
|
+
`data:` is a keyword with a `nil` default, and the wire frame is unchanged when there
|
|
18
|
+
is no data — the member is omitted, never emitted as `null`.
|
|
19
|
+
|
|
20
|
+
### 2.1.0
|
|
4
21
|
|
|
5
22
|
**New**
|
|
6
23
|
|
data/Gemfile
CHANGED
|
@@ -5,16 +5,15 @@ source 'https://rubygems.org'
|
|
|
5
5
|
# Specify your gem's dependencies in jrpc.gemspec
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
|
-
gem 'bundler'
|
|
9
8
|
gem 'rake', '~> 13.0'
|
|
10
9
|
gem 'rspec', '~> 3.0'
|
|
11
10
|
|
|
12
11
|
# Provides a real Fiber.scheduler for the fiber-caller specs (SharedClient §9.8).
|
|
13
12
|
gem 'async', '~> 2.0'
|
|
14
13
|
|
|
15
|
-
gem 'rubocop', '~> 1.
|
|
16
|
-
gem 'rubocop-performance'
|
|
17
|
-
gem 'rubocop-rspec'
|
|
14
|
+
gem 'rubocop', '~> 1.90.0'
|
|
15
|
+
gem 'rubocop-performance', '~> 1.27.0'
|
|
16
|
+
gem 'rubocop-rspec', '~> 3.10.2'
|
|
18
17
|
gem 'rubocop-rake', '~> 0.7.1'
|
|
19
18
|
|
|
20
19
|
gem 'simplecov', '~> 0.22', require: false
|
data/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://rubygems.org/gems/jrpc)
|
|
4
4
|
[](https://github.com/didww/jrpc/actions/workflows/ci.yml)
|
|
5
5
|
|
|
6
|
-
A JSON-RPC
|
|
6
|
+
A JSON-RPC v2 client for Ruby, over TCP, with netstring framing.
|
|
7
7
|
|
|
8
8
|
JRPC ships two clients with sharp, separate responsibilities:
|
|
9
9
|
|
|
@@ -133,6 +133,7 @@ Errors::Error (RuntimeError)
|
|
|
133
133
|
├── Errors::Timeout # message TTL elapsed, or SimpleClient read/write/connect timeout
|
|
134
134
|
└── Errors::ServerError # peer returned an error, or the response was unusable
|
|
135
135
|
attr_reader :code # nil for malformed responses
|
|
136
|
+
attr_reader :data # the error object's `data` member, nil when absent
|
|
136
137
|
├── Errors::ParseError # -32700
|
|
137
138
|
├── Errors::InvalidRequest # -32600
|
|
138
139
|
├── Errors::MethodNotFound # -32601
|
|
@@ -145,11 +146,17 @@ Errors::Error (RuntimeError)
|
|
|
145
146
|
|
|
146
147
|
`MalformedResponseError` is a `ServerError`, not a `ClientError`: a malformed response is the peer's fault.
|
|
147
148
|
|
|
149
|
+
`#data` carries the error object's optional `data` member through untouched — a String,
|
|
150
|
+
Hash, Array or number, whatever the peer sent, and `nil` when it sent none. It is where a
|
|
151
|
+
server says *which* param was invalid or *which* id conflicted, so log it alongside the
|
|
152
|
+
code. `MalformedResponseError` is raised locally rather than built from a peer error
|
|
153
|
+
object, so its `data` is always `nil`.
|
|
154
|
+
|
|
148
155
|
```ruby
|
|
149
156
|
begin
|
|
150
157
|
client.request(:do_thing, [1, 2])
|
|
151
158
|
rescue JRPC::Errors::ServerError => e
|
|
152
|
-
warn "rpc error #{e.code}: #{e.message}"
|
|
159
|
+
warn "rpc error #{e.code}: #{e.message} #{e.data.inspect}"
|
|
153
160
|
rescue JRPC::Errors::Timeout
|
|
154
161
|
warn "timed out"
|
|
155
162
|
rescue JRPC::Errors::ConnectionError => e
|
data/lib/jrpc/errors.rb
CHANGED
|
@@ -11,15 +11,22 @@ module JRPC
|
|
|
11
11
|
|
|
12
12
|
class Timeout < Error; end
|
|
13
13
|
|
|
14
|
+
# A JSON-RPC error object the peer sent back, carrying its `code` and its optional
|
|
15
|
+
# `data` member verbatim. Per the spec `data` is "a primitive or structured value"
|
|
16
|
+
# defined by the server, so it arrives as whatever JSON.parse produced — String,
|
|
17
|
+
# Hash, Array, Numeric — or nil when the peer omitted it.
|
|
14
18
|
class ServerError < Error
|
|
15
|
-
attr_reader :code
|
|
19
|
+
attr_reader :code, :data
|
|
16
20
|
|
|
17
|
-
def initialize(message, code: nil)
|
|
21
|
+
def initialize(message, code: nil, data: nil)
|
|
18
22
|
@code = code
|
|
23
|
+
@data = data
|
|
19
24
|
super(message)
|
|
20
25
|
end
|
|
21
26
|
end
|
|
22
27
|
|
|
28
|
+
# Raised locally when a frame is unparseable or violates the envelope rules, so it
|
|
29
|
+
# never corresponds to a peer error object: no code, no data.
|
|
23
30
|
class MalformedResponseError < ServerError
|
|
24
31
|
def initialize(message)
|
|
25
32
|
super(message, code: nil)
|
|
@@ -27,32 +34,32 @@ module JRPC
|
|
|
27
34
|
end
|
|
28
35
|
|
|
29
36
|
class ParseError < ServerError
|
|
30
|
-
def initialize(message)
|
|
31
|
-
super(message, code: -32_700)
|
|
37
|
+
def initialize(message, data: nil)
|
|
38
|
+
super(message, code: -32_700, data: data)
|
|
32
39
|
end
|
|
33
40
|
end
|
|
34
41
|
|
|
35
42
|
class InvalidRequest < ServerError
|
|
36
|
-
def initialize(message)
|
|
37
|
-
super(message, code: -32_600)
|
|
43
|
+
def initialize(message, data: nil)
|
|
44
|
+
super(message, code: -32_600, data: data)
|
|
38
45
|
end
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
class MethodNotFound < ServerError
|
|
42
|
-
def initialize(message)
|
|
43
|
-
super(message, code: -32_601)
|
|
49
|
+
def initialize(message, data: nil)
|
|
50
|
+
super(message, code: -32_601, data: data)
|
|
44
51
|
end
|
|
45
52
|
end
|
|
46
53
|
|
|
47
54
|
class InvalidParams < ServerError
|
|
48
|
-
def initialize(message)
|
|
49
|
-
super(message, code: -32_602)
|
|
55
|
+
def initialize(message, data: nil)
|
|
56
|
+
super(message, code: -32_602, data: data)
|
|
50
57
|
end
|
|
51
58
|
end
|
|
52
59
|
|
|
53
60
|
class InternalError < ServerError
|
|
54
|
-
def initialize(message)
|
|
55
|
-
super(message, code: -32_603)
|
|
61
|
+
def initialize(message, data: nil)
|
|
62
|
+
super(message, code: -32_603, data: data)
|
|
56
63
|
end
|
|
57
64
|
end
|
|
58
65
|
|
data/lib/jrpc/message.rb
CHANGED
|
@@ -49,17 +49,21 @@ module JRPC
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
# `error.data` is optional per the spec and is passed through untouched: servers use
|
|
53
|
+
# it to say *which* param was invalid, *which* id conflicted, and so on — the only
|
|
54
|
+
# machine-readable detail an error object carries beyond the code.
|
|
52
55
|
def self.error_to_exception(error_hash)
|
|
53
56
|
code = error_hash['code']
|
|
54
57
|
message = error_hash['message']
|
|
58
|
+
data = error_hash['data']
|
|
55
59
|
case code
|
|
56
|
-
when -32_700 then Errors::ParseError.new(message)
|
|
57
|
-
when -32_600 then Errors::InvalidRequest.new(message)
|
|
58
|
-
when -32_601 then Errors::MethodNotFound.new(message)
|
|
59
|
-
when -32_602 then Errors::InvalidParams.new(message)
|
|
60
|
-
when -32_603 then Errors::InternalError.new(message)
|
|
61
|
-
when -32_099..-32_000 then Errors::InternalServerError.new(message, code: code)
|
|
62
|
-
else Errors::UnknownError.new(message, code: code)
|
|
60
|
+
when -32_700 then Errors::ParseError.new(message, data: data)
|
|
61
|
+
when -32_600 then Errors::InvalidRequest.new(message, data: data)
|
|
62
|
+
when -32_601 then Errors::MethodNotFound.new(message, data: data)
|
|
63
|
+
when -32_602 then Errors::InvalidParams.new(message, data: data)
|
|
64
|
+
when -32_603 then Errors::InternalError.new(message, data: data)
|
|
65
|
+
when -32_099..-32_000 then Errors::InternalServerError.new(message, code: code, data: data)
|
|
66
|
+
else Errors::UnknownError.new(message, code: code, data: data)
|
|
63
67
|
end
|
|
64
68
|
end
|
|
65
69
|
|
data/lib/jrpc/transport/test.rb
CHANGED
|
@@ -282,12 +282,14 @@ module JRPC
|
|
|
282
282
|
JSON.generate({ 'jsonrpc' => JRPC::JSON_RPC_VERSION, 'id' => id, 'result' => result })
|
|
283
283
|
end
|
|
284
284
|
|
|
285
|
+
# `data` is emitted only when the raised error carries one, so a handler that
|
|
286
|
+
# ignores it produces the same frame as before.
|
|
285
287
|
def error_response(id, error)
|
|
286
288
|
code = error.respond_to?(:code) && error.code.is_a?(Integer) ? error.code : -32_000
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
)
|
|
289
|
+
data = error.respond_to?(:data) ? error.data : nil
|
|
290
|
+
err = { 'code' => code, 'message' => error.message }
|
|
291
|
+
err['data'] = data unless data.nil?
|
|
292
|
+
JSON.generate({ 'jsonrpc' => JRPC::JSON_RPC_VERSION, 'id' => id, 'error' => err })
|
|
291
293
|
end
|
|
292
294
|
|
|
293
295
|
def enqueue(entry)
|
data/lib/jrpc/version.rb
CHANGED