twirp 1.10.0 → 1.13.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 +8 -6
- data/lib/twirp/client.rb +8 -5
- data/lib/twirp/client_json.rb +2 -2
- data/lib/twirp/client_resp.rb +3 -1
- data/lib/twirp/service.rb +5 -5
- data/lib/twirp/version.rb +1 -1
- data/test/client_json_test.rb +3 -0
- data/test/client_test.rb +19 -0
- data/test/fake_services.rb +5 -16
- data/test/service_test.rb +20 -20
- data/twirp.gemspec +4 -3
- metadata +28 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78baa75e1f8c6d2009bb678de8263824d4bb691c8bb862dd8c3969e93f9a711e
|
4
|
+
data.tar.gz: a6d86c07b49e7ec371cee190942b1286d91208b2d45104a64f67c430207fa3a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f9f81587e713fd88ab7a2a7fd815b317e271d3a58a76692a4f6828be15076d7ba9682a984001e3fb82aa20dfa74dc14f2f01fc5a53d34e3470b9192793d6005
|
7
|
+
data.tar.gz: 1004bb764ef0e9572aee60b0b84f337cda920ed45d7cd03655c5d47c6299c3864e33737e44010ef2905cebe5095d4a89bd51e9c5517545b0966e9b8854c92055
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Twirp-Ruby
|
2
2
|
|
3
|
-
[](https://github.com/arthurnn/twirp-ruby/actions/workflows/tests.yml)
|
4
4
|
|
5
|
-
[Twirp is a protocol](https://
|
5
|
+
[Twirp is a protocol](https://twitchtv.github.io/twirp/docs/spec_v5.html) for routing and serialization of services defined in a [.proto file](https://developers.google.com/protocol-buffers/docs/proto3), allowing easy implementation of RPC services with auto-generated clients in different languages.
|
6
6
|
|
7
7
|
The [canonical implementation](https://github.com/twitchtv/twirp) is in Golang. The Twirp-Ruby project is the official implementation in Ruby for both server and clients.
|
8
8
|
|
@@ -11,13 +11,15 @@ The [canonical implementation](https://github.com/twitchtv/twirp) is in Golang.
|
|
11
11
|
|
12
12
|
Add `gem "twirp"` to your Gemfile, or install with `gem install twirp`.
|
13
13
|
|
14
|
-
To auto-generate Ruby code from a proto file, use the `protoc` plugin and the `--ruby_out` option ([see Wiki page](https://github.com/
|
14
|
+
To auto-generate Ruby code from a proto file, use the `protoc` plugin and the `--ruby_out` option ([see Wiki page](https://github.com/arthurnn/twirp-ruby/wiki/Code-Generation)).
|
15
15
|
|
16
|
+
### No backwards compatible breaking changes, between minor versions(1.10.0)
|
16
17
|
|
17
|
-
|
18
|
+
When upgrading from version 1.9.0 to 1.10.0, note that there is a breaking change in the `Twirp::ClientResp#initialize` method. The method now accepts keyword arguments. For more details, refer to this [comparison](https://github.com/arthurnn/twirp-ruby/compare/v1.9.0...v1.10.0#diff-b3c497150f4ae769df1a5d90e43142983cfd4d780392cbaa218d74912fa3a174) and this [issue](https://github.com/arthurnn/twirp-ruby/issues/99).
|
18
19
|
|
19
|
-
|
20
|
+
## Documentation
|
20
21
|
|
22
|
+
[On the wiki](https://github.com/arthurnn/twirp-ruby/wiki).
|
21
23
|
|
22
24
|
## Contributing
|
23
25
|
|
@@ -25,4 +27,4 @@ To auto-generate Ruby code from a proto file, use the `protoc` plugin and the `-
|
|
25
27
|
|
26
28
|
## Releases and changes
|
27
29
|
|
28
|
-
See the [releases](https://github.com/
|
30
|
+
See the [releases](https://github.com/arthurnn/twirp-ruby/releases) page for latest information about released versions.
|
data/lib/twirp/client.rb
CHANGED
@@ -106,7 +106,7 @@ module Twirp
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def is_http_redirect?(status)
|
109
|
-
status >= 300 && status <= 399
|
109
|
+
status && status >= 300 && status <= 399
|
110
110
|
end
|
111
111
|
|
112
112
|
def make_http_request(conn, service_full_name, rpc_method, content_type, req_opts, body)
|
@@ -178,7 +178,7 @@ module Twirp
|
|
178
178
|
# natively with twirp-ruby. For normal Faraday, this is a noop.
|
179
179
|
def rpc_response_thennable(resp)
|
180
180
|
return yield resp unless resp.respond_to?(:then)
|
181
|
-
|
181
|
+
|
182
182
|
resp.then do |resp|
|
183
183
|
yield resp
|
184
184
|
end
|
@@ -186,15 +186,18 @@ module Twirp
|
|
186
186
|
|
187
187
|
def rpc_response_to_clientresp(resp, content_type, rpcdef)
|
188
188
|
if resp.status != 200
|
189
|
-
return ClientResp.new(error: self.class.error_from_response(resp))
|
189
|
+
return ClientResp.new(error: self.class.error_from_response(resp), headers: resp.headers)
|
190
190
|
end
|
191
191
|
|
192
192
|
if resp.headers['Content-Type'] != content_type
|
193
|
-
return ClientResp.new(
|
193
|
+
return ClientResp.new(
|
194
|
+
error: Twirp::Error.internal("Expected response Content-Type #{content_type.inspect} but found #{resp.headers['Content-Type'].inspect}"),
|
195
|
+
headers: resp.headers
|
196
|
+
)
|
194
197
|
end
|
195
198
|
|
196
199
|
data = Encoding.decode(resp.body, rpcdef[:output_class], content_type)
|
197
|
-
return ClientResp.new(data: data, body: resp.body)
|
200
|
+
return ClientResp.new(data: data, body: resp.body, headers: resp.headers)
|
198
201
|
end
|
199
202
|
|
200
203
|
end
|
data/lib/twirp/client_json.rb
CHANGED
@@ -46,11 +46,11 @@ module Twirp
|
|
46
46
|
|
47
47
|
def rpc_response_to_clientresp(resp)
|
48
48
|
if resp.status != 200
|
49
|
-
return ClientResp.new(error: self.class.error_from_response(resp))
|
49
|
+
return ClientResp.new(error: self.class.error_from_response(resp), headers: resp.headers)
|
50
50
|
end
|
51
51
|
|
52
52
|
data = Encoding.decode_json(resp.body)
|
53
|
-
return ClientResp.new(data: data, body: resp.body)
|
53
|
+
return ClientResp.new(data: data, body: resp.body, headers: resp.headers)
|
54
54
|
end
|
55
55
|
|
56
56
|
end
|
data/lib/twirp/client_resp.rb
CHANGED
@@ -16,11 +16,13 @@ module Twirp
|
|
16
16
|
attr_accessor :data
|
17
17
|
attr_accessor :body
|
18
18
|
attr_accessor :error
|
19
|
+
attr_accessor :headers
|
19
20
|
|
20
|
-
def initialize(data: nil, body: nil, error: nil)
|
21
|
+
def initialize(data: nil, body: nil, error: nil, headers: nil)
|
21
22
|
@data = data
|
22
23
|
@error = error
|
23
24
|
@body = body
|
25
|
+
@headers = headers
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
data/lib/twirp/service.rb
CHANGED
@@ -32,7 +32,7 @@ module Twirp
|
|
32
32
|
# Rack response with a Twirp::Error
|
33
33
|
def error_response(twerr)
|
34
34
|
status = Twirp::ERROR_CODES_TO_HTTP_STATUS[twerr.code]
|
35
|
-
headers = {
|
35
|
+
headers = {Rack::CONTENT_TYPE => Encoding::JSON} # Twirp errors are always JSON, even if the request was protobuf
|
36
36
|
resp_body = Encoding.encode_json(twerr.to_h)
|
37
37
|
[status, headers, [resp_body]]
|
38
38
|
end
|
@@ -100,7 +100,7 @@ module Twirp
|
|
100
100
|
input = env[:input_class].new(input) if input.is_a? Hash
|
101
101
|
env[:input] = input
|
102
102
|
env[:content_type] ||= Encoding::PROTO
|
103
|
-
env[:http_response_headers] = {}
|
103
|
+
env[:http_response_headers] = defined?(Rack::Headers) ? Rack::Headers.new : {}
|
104
104
|
call_handler(env)
|
105
105
|
end
|
106
106
|
|
@@ -138,7 +138,7 @@ module Twirp
|
|
138
138
|
input = nil
|
139
139
|
begin
|
140
140
|
body_str = rack_request.body.read
|
141
|
-
rack_request.body.rewind # allow other middleware to read again (https://github.com/
|
141
|
+
rack_request.body.rewind if rack_request.body.respond_to?(:rewind) # allow other middleware to read again (https://github.com/arthurnn/twirp-ruby/issues/50)
|
142
142
|
input = Encoding.decode(body_str, env[:input_class], content_type)
|
143
143
|
rescue => e
|
144
144
|
error_msg = "Invalid request body for rpc method #{method_name.inspect} with Content-Type=#{content_type}"
|
@@ -149,7 +149,7 @@ module Twirp
|
|
149
149
|
end
|
150
150
|
|
151
151
|
env[:input] = input
|
152
|
-
env[:http_response_headers] = {}
|
152
|
+
env[:http_response_headers] = defined?(Rack::Headers) ? Rack::Headers.new : {}
|
153
153
|
return
|
154
154
|
end
|
155
155
|
|
@@ -181,7 +181,7 @@ module Twirp
|
|
181
181
|
env[:output] = output
|
182
182
|
@on_success.each{|hook| hook.call(env) }
|
183
183
|
|
184
|
-
headers = env[:http_response_headers].merge(
|
184
|
+
headers = env[:http_response_headers].merge(Rack::CONTENT_TYPE => env[:content_type])
|
185
185
|
resp_body = Encoding.encode(output, env[:output_class], env[:content_type])
|
186
186
|
[200, headers, [resp_body]]
|
187
187
|
|
data/lib/twirp/version.rb
CHANGED
data/test/client_json_test.rb
CHANGED
@@ -27,6 +27,7 @@ class ClientJSONTest < Minitest::Test
|
|
27
27
|
assert_nil resp.error
|
28
28
|
refute_nil resp.data
|
29
29
|
assert_equal 3, resp.data["blah_resp"]
|
30
|
+
refute_nil resp.headers
|
30
31
|
end
|
31
32
|
|
32
33
|
def test_client_json_thennable
|
@@ -77,6 +78,7 @@ class ClientJSONTest < Minitest::Test
|
|
77
78
|
refute_nil resp.error
|
78
79
|
assert_equal :invalid_argument, resp.error.code
|
79
80
|
assert_equal "dont like empty", resp.error.msg
|
81
|
+
refute_nil resp.headers
|
80
82
|
end
|
81
83
|
|
82
84
|
def test_client_bad_json_route
|
@@ -88,6 +90,7 @@ class ClientJSONTest < Minitest::Test
|
|
88
90
|
assert_nil resp.data
|
89
91
|
refute_nil resp.error
|
90
92
|
assert_equal :bad_route, resp.error.code
|
93
|
+
refute_nil resp.headers
|
91
94
|
end
|
92
95
|
|
93
96
|
|
data/test/client_test.rb
CHANGED
@@ -58,6 +58,17 @@ class ClientTest < Minitest::Test
|
|
58
58
|
assert_equal num_mthds + 1, EmptyClient.instance_methods.size # new method added
|
59
59
|
end
|
60
60
|
|
61
|
+
def test_is_http_redirect
|
62
|
+
assert Twirp::Client.is_http_redirect? 300
|
63
|
+
assert Twirp::Client.is_http_redirect? 301
|
64
|
+
assert Twirp::Client.is_http_redirect? 302
|
65
|
+
assert Twirp::Client.is_http_redirect? 399
|
66
|
+
|
67
|
+
refute Twirp::Client.is_http_redirect? 200
|
68
|
+
refute Twirp::Client.is_http_redirect? 400
|
69
|
+
refute Twirp::Client.is_http_redirect? nil
|
70
|
+
end
|
71
|
+
|
61
72
|
|
62
73
|
# Call .rpc on Protobuf client
|
63
74
|
# ----------------------------
|
@@ -114,6 +125,7 @@ class ClientTest < Minitest::Test
|
|
114
125
|
resp = c.make_hat(inches: 666)
|
115
126
|
assert_nil resp.error
|
116
127
|
refute_nil resp.data
|
128
|
+
refute_nil resp.headers
|
117
129
|
end
|
118
130
|
|
119
131
|
def test_proto_serialized_request_body
|
@@ -128,6 +140,7 @@ class ClientTest < Minitest::Test
|
|
128
140
|
resp = c.make_hat(Example::Size.new(inches: 666))
|
129
141
|
assert_nil resp.error
|
130
142
|
refute_nil resp.data
|
143
|
+
refute_nil resp.headers
|
131
144
|
end
|
132
145
|
|
133
146
|
def test_proto_twirp_error
|
@@ -139,6 +152,7 @@ class ClientTest < Minitest::Test
|
|
139
152
|
refute_nil resp.error
|
140
153
|
assert_equal :internal, resp.error.code
|
141
154
|
assert_equal "something went wrong", resp.error.msg
|
155
|
+
refute_nil resp.headers
|
142
156
|
end
|
143
157
|
|
144
158
|
def test_proto_intermediary_plain_error
|
@@ -153,6 +167,7 @@ class ClientTest < Minitest::Test
|
|
153
167
|
assert_equal "true", resp.error.meta[:http_error_from_intermediary]
|
154
168
|
assert_equal "Response is not JSON", resp.error.meta[:not_a_twirp_error_because]
|
155
169
|
assert_equal "plain text error from proxy", resp.error.meta[:body]
|
170
|
+
refute_nil resp.headers
|
156
171
|
end
|
157
172
|
|
158
173
|
def test_proto_redirect_error
|
@@ -166,6 +181,7 @@ class ClientTest < Minitest::Test
|
|
166
181
|
assert_equal "Unexpected HTTP Redirect from location=http://rainbow.com", resp.error.msg
|
167
182
|
assert_equal "true", resp.error.meta[:http_error_from_intermediary]
|
168
183
|
assert_equal "Redirects not allowed on Twirp requests", resp.error.meta[:not_a_twirp_error_because]
|
184
|
+
refute_nil resp.headers
|
169
185
|
end
|
170
186
|
|
171
187
|
def test_proto_missing_response_header
|
@@ -176,6 +192,7 @@ class ClientTest < Minitest::Test
|
|
176
192
|
refute_nil resp.error
|
177
193
|
assert_equal :internal, resp.error.code
|
178
194
|
assert_equal 'Expected response Content-Type "application/protobuf" but found nil', resp.error.msg
|
195
|
+
refute_nil resp.headers
|
179
196
|
end
|
180
197
|
|
181
198
|
def test_error_with_invalid_code
|
@@ -187,6 +204,7 @@ class ClientTest < Minitest::Test
|
|
187
204
|
refute_nil resp.error
|
188
205
|
assert_equal :internal, resp.error.code
|
189
206
|
assert_equal "Invalid Twirp error code: unicorn", resp.error.msg
|
207
|
+
refute_nil resp.headers
|
190
208
|
end
|
191
209
|
|
192
210
|
def test_error_with_no_code
|
@@ -201,6 +219,7 @@ class ClientTest < Minitest::Test
|
|
201
219
|
assert_equal "true", resp.error.meta[:http_error_from_intermediary]
|
202
220
|
assert_equal 'Response is JSON but it has no "code" attribute', resp.error.meta[:not_a_twirp_error_because]
|
203
221
|
assert_equal '{"msg":"I have no code of honor"}', resp.error.meta[:body]
|
222
|
+
refute_nil resp.headers
|
204
223
|
end
|
205
224
|
|
206
225
|
# Call .rpc on JSON client
|
data/test/fake_services.rb
CHANGED
@@ -5,17 +5,8 @@ require_relative '../lib/twirp'
|
|
5
5
|
|
6
6
|
# Protobuf messages.
|
7
7
|
# An example of the result of the protoc ruby code generator.
|
8
|
-
|
9
|
-
|
10
|
-
optional :inches, :int32, 1
|
11
|
-
end
|
12
|
-
add_message "example.Hat" do
|
13
|
-
optional :inches, :int32, 1
|
14
|
-
optional :color, :string, 2
|
15
|
-
end
|
16
|
-
add_message "example.Empty" do
|
17
|
-
end
|
18
|
-
end
|
8
|
+
descriptor_data = "\n\ntest.proto\x12\x07\x65xample\"\x16\n\x04Size\x12\x0e\n\x06inches\x18\x01 \x01(\x05\"$\n\x03Hat\x12\x0e\n\x06inches\x18\x01 \x01(\x05\x12\r\n\x05\x63olor\x18\x02 \x01(\t\"\x07\n\x05\x45mptyb\x06proto3"
|
9
|
+
Google::Protobuf::DescriptorPool.generated_pool.add_serialized_file(descriptor_data)
|
19
10
|
|
20
11
|
module Example
|
21
12
|
Size = Google::Protobuf::DescriptorPool.generated_pool.lookup("example.Size").msgclass
|
@@ -56,11 +47,9 @@ class EmptyClient < Twirp::Client
|
|
56
47
|
end
|
57
48
|
|
58
49
|
# Foo message
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
50
|
+
descriptor_data = "\n\tfoo.proto\"\x12\n\x03\x46oo\x12\x0b\n\x03\x66oo\x18\x01 \x01(\tb\x06proto3"
|
51
|
+
Google::Protobuf::DescriptorPool.generated_pool.add_serialized_file(descriptor_data)
|
52
|
+
|
64
53
|
Foo = Google::Protobuf::DescriptorPool.generated_pool.lookup("Foo").msgclass
|
65
54
|
|
66
55
|
# Foo Client
|
data/test/service_test.rb
CHANGED
@@ -17,7 +17,7 @@ class ServiceTest < Minitest::Test
|
|
17
17
|
twerr = Twirp::Error.invalid_argument('foo')
|
18
18
|
resp = Twirp::Service.error_response(twerr)
|
19
19
|
assert_equal 400, resp[0]
|
20
|
-
assert_equal 'application/json', resp[1][
|
20
|
+
assert_equal 'application/json', resp[1][Rack::CONTENT_TYPE]
|
21
21
|
assert_equal '{"code":"invalid_argument","msg":"foo"}', resp[2][0]
|
22
22
|
end
|
23
23
|
|
@@ -60,7 +60,7 @@ class ServiceTest < Minitest::Test
|
|
60
60
|
status, headers, body = haberdasher_service.call(rack_env)
|
61
61
|
|
62
62
|
assert_equal 200, status
|
63
|
-
assert_equal 'application/json', headers[
|
63
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
64
64
|
assert_equal({"inches" => 10, "color" => "white"}, JSON.parse(body[0]))
|
65
65
|
end
|
66
66
|
|
@@ -69,7 +69,7 @@ class ServiceTest < Minitest::Test
|
|
69
69
|
status, headers, body = haberdasher_service.call(rack_env)
|
70
70
|
|
71
71
|
assert_equal 200, status
|
72
|
-
assert_equal 'application/json; strict=true', headers[
|
72
|
+
assert_equal 'application/json; strict=true', headers[Rack::CONTENT_TYPE]
|
73
73
|
assert_equal({"inches" => 0, "color" => "white"}, JSON.parse(body[0]))
|
74
74
|
end
|
75
75
|
|
@@ -78,7 +78,7 @@ class ServiceTest < Minitest::Test
|
|
78
78
|
status, headers, body = haberdasher_service.call(rack_env)
|
79
79
|
|
80
80
|
assert_equal 200, status
|
81
|
-
assert_equal 'application/json', headers[
|
81
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
82
82
|
assert_equal({"inches" => 0, "color" => "white"}, JSON.parse(body[0]))
|
83
83
|
end
|
84
84
|
|
@@ -87,7 +87,7 @@ class ServiceTest < Minitest::Test
|
|
87
87
|
status, headers, body = haberdasher_service.call(rack_env)
|
88
88
|
|
89
89
|
assert_equal 200, status
|
90
|
-
assert_equal 'application/protobuf', headers[
|
90
|
+
assert_equal 'application/protobuf', headers[Rack::CONTENT_TYPE]
|
91
91
|
assert_equal Example::Hat.new(inches: 10, color: "white"), Example::Hat.decode(body[0])
|
92
92
|
end
|
93
93
|
|
@@ -96,7 +96,7 @@ class ServiceTest < Minitest::Test
|
|
96
96
|
status, headers, body = haberdasher_service.call(rack_env)
|
97
97
|
|
98
98
|
assert_equal 404, status
|
99
|
-
assert_equal 'application/json', headers[
|
99
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
100
100
|
assert_equal({
|
101
101
|
"code" => 'bad_route',
|
102
102
|
"msg" => 'Invalid rpc method "MakeUnicorns"',
|
@@ -110,7 +110,7 @@ class ServiceTest < Minitest::Test
|
|
110
110
|
status, headers, body = haberdasher_service.call(rack_env)
|
111
111
|
|
112
112
|
assert_equal 404, status
|
113
|
-
assert_equal 'application/json', headers[
|
113
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
114
114
|
assert_equal({
|
115
115
|
"code" => 'bad_route',
|
116
116
|
"msg" => 'HTTP request method must be POST',
|
@@ -124,7 +124,7 @@ class ServiceTest < Minitest::Test
|
|
124
124
|
status, headers, body = haberdasher_service.call(rack_env)
|
125
125
|
|
126
126
|
assert_equal 404, status
|
127
|
-
assert_equal 'application/json', headers[
|
127
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
128
128
|
assert_equal({
|
129
129
|
"code" => 'bad_route',
|
130
130
|
"msg" => 'Unexpected Content-Type: "text/plain". Content-Type header must be one of ["application/json", "application/protobuf"]',
|
@@ -137,7 +137,7 @@ class ServiceTest < Minitest::Test
|
|
137
137
|
status, headers, body = haberdasher_service.call(rack_env)
|
138
138
|
|
139
139
|
assert_equal 404, status
|
140
|
-
assert_equal 'application/json', headers[
|
140
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
141
141
|
assert_equal({
|
142
142
|
"code" => 'bad_route',
|
143
143
|
"msg" => 'Invalid route. Expected format: POST {BaseURL}/example.Haberdasher/{Method}',
|
@@ -150,7 +150,7 @@ class ServiceTest < Minitest::Test
|
|
150
150
|
status, headers, body = haberdasher_service.call(rack_env)
|
151
151
|
|
152
152
|
assert_equal 404, status
|
153
|
-
assert_equal 'application/json', headers[
|
153
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE] # error responses are always JSON, even for Protobuf requests
|
154
154
|
assert_equal({
|
155
155
|
"code" => 'bad_route',
|
156
156
|
"msg" => 'Invalid route. Expected format: POST {BaseURL}/example.Haberdasher/{Method}',
|
@@ -164,7 +164,7 @@ class ServiceTest < Minitest::Test
|
|
164
164
|
status, headers, body = haberdasher_service.call(rack_env)
|
165
165
|
|
166
166
|
assert_equal 400, status
|
167
|
-
assert_equal 'application/json', headers[
|
167
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
168
168
|
assert_equal({
|
169
169
|
"code" => 'malformed',
|
170
170
|
"msg" => 'Invalid request body for rpc method "MakeHat" with Content-Type=application/json: ' +
|
@@ -179,7 +179,7 @@ class ServiceTest < Minitest::Test
|
|
179
179
|
status, headers, body = haberdasher_service.call(rack_env)
|
180
180
|
|
181
181
|
assert_equal 400, status
|
182
|
-
assert_equal 'application/json', headers[
|
182
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
183
183
|
assert_equal({
|
184
184
|
"code" => 'malformed',
|
185
185
|
"msg" => 'Invalid request body for rpc method "MakeHat" with Content-Type=application/protobuf: ' +
|
@@ -193,7 +193,7 @@ class ServiceTest < Minitest::Test
|
|
193
193
|
status, headers, body = haberdasher_service.call(rack_env)
|
194
194
|
|
195
195
|
assert_equal 200, status
|
196
|
-
assert_equal 'application/json', headers[
|
196
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
197
197
|
assert_equal({"inches" => 10, "color" => "white"}, JSON.parse(body[0]))
|
198
198
|
end
|
199
199
|
|
@@ -202,7 +202,7 @@ class ServiceTest < Minitest::Test
|
|
202
202
|
status, headers, body = haberdasher_service.call(rack_env)
|
203
203
|
|
204
204
|
assert_equal 200, status
|
205
|
-
assert_equal 'application/json', headers[
|
205
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
206
206
|
assert_equal({"inches" => 10, "color" => "white"}, JSON.parse(body[0]))
|
207
207
|
end
|
208
208
|
|
@@ -211,7 +211,7 @@ class ServiceTest < Minitest::Test
|
|
211
211
|
status, headers, body = haberdasher_service.call(rack_env)
|
212
212
|
|
213
213
|
assert_equal 400, status
|
214
|
-
assert_equal 'application/json', headers[
|
214
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
215
215
|
assert_equal({
|
216
216
|
"code" => 'malformed',
|
217
217
|
"msg" => 'Invalid request body for rpc method "MakeHat" with Content-Type=application/json; strict=true: ' +
|
@@ -289,7 +289,7 @@ class ServiceTest < Minitest::Test
|
|
289
289
|
rack_env = proto_req "/example.Haberdasher/MakeHat", Example::Size.new(inches: 666)
|
290
290
|
status, headers, body = svc.call(rack_env)
|
291
291
|
assert_equal 400, status
|
292
|
-
assert_equal 'application/json', headers[
|
292
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE] # error responses are always JSON, even for Protobuf requests
|
293
293
|
assert_equal({
|
294
294
|
"code" => 'invalid_argument',
|
295
295
|
"msg" => "I don't like that size",
|
@@ -298,7 +298,7 @@ class ServiceTest < Minitest::Test
|
|
298
298
|
|
299
299
|
def test_handler_method_can_set_response_headers_through_the_env
|
300
300
|
svc = Example::Haberdasher.new(HaberdasherHandler.new do |size, env|
|
301
|
-
env[:http_response_headers][
|
301
|
+
env[:http_response_headers][Rack::CACHE_CONTROL] = "public, max-age=60"
|
302
302
|
{}
|
303
303
|
end)
|
304
304
|
|
@@ -306,8 +306,8 @@ class ServiceTest < Minitest::Test
|
|
306
306
|
status, headers, body = svc.call(rack_env)
|
307
307
|
|
308
308
|
assert_equal 200, status
|
309
|
-
assert_equal "public, max-age=60", headers[
|
310
|
-
assert_equal "application/protobuf", headers[
|
309
|
+
assert_equal "public, max-age=60", headers[Rack::CACHE_CONTROL] # set by the handler
|
310
|
+
assert_equal "application/protobuf", headers[Rack::CONTENT_TYPE] # set by Twirp::Service
|
311
311
|
end
|
312
312
|
|
313
313
|
def test_handler_returns_invalid_type_nil
|
@@ -533,7 +533,7 @@ class ServiceTest < Minitest::Test
|
|
533
533
|
status, headers, body = svc.call(rack_env)
|
534
534
|
|
535
535
|
assert_equal 500, status
|
536
|
-
assert_equal 'application/json', headers[
|
536
|
+
assert_equal 'application/json', headers[Rack::CONTENT_TYPE]
|
537
537
|
assert_equal({
|
538
538
|
"code" => 'intenal',
|
539
539
|
"msg" => 'hook1 failed',
|
data/twirp.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.email = ["forbescyrus@gmail.com", "tothemario@gmail.com"]
|
12
12
|
spec.summary = %q{Twirp services in Ruby.}
|
13
13
|
spec.description = %q{Twirp is a simple RPC framework with protobuf service definitions. The Twirp gem provides native support for Ruby.}
|
14
|
-
spec.homepage = "https://github.com/
|
14
|
+
spec.homepage = "https://github.com/arthurnn/twirp-ruby"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
17
|
spec.files = Dir['lib/**/*'] + %w(Gemfile LICENSE README.md twirp.gemspec)
|
@@ -19,11 +19,12 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.required_ruby_version = '>= 1.9'
|
22
|
-
spec.add_runtime_dependency 'google-protobuf', '
|
22
|
+
spec.add_runtime_dependency 'google-protobuf', '>= 3.25', '< 5.a'
|
23
23
|
spec.add_runtime_dependency 'faraday', '< 3' # for clients
|
24
|
+
spec.add_dependency 'rack', '>= 2.2.3'
|
24
25
|
|
25
26
|
spec.add_development_dependency 'bundler', '~> 2'
|
26
27
|
spec.add_development_dependency 'minitest', '>= 5'
|
27
28
|
spec.add_development_dependency 'rake'
|
28
|
-
|
29
|
+
|
29
30
|
end
|
metadata
CHANGED
@@ -1,36 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twirp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyrus A. Forbes
|
8
8
|
- Mario Izquierdo
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-11-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: google-protobuf
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "~>"
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: '3.0'
|
21
18
|
- - ">="
|
22
19
|
- !ruby/object:Gem::Version
|
23
|
-
version: 3.
|
20
|
+
version: '3.25'
|
21
|
+
- - "<"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 5.a
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- - "~>"
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
version: '3.0'
|
31
28
|
- - ">="
|
32
29
|
- !ruby/object:Gem::Version
|
33
|
-
version: 3.
|
30
|
+
version: '3.25'
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.a
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: faraday
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,6 +45,20 @@ dependencies:
|
|
45
45
|
- - "<"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '3'
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rack
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.2.3
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.2.3
|
48
62
|
- !ruby/object:Gem::Dependency
|
49
63
|
name: bundler
|
50
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,20 +101,6 @@ dependencies:
|
|
87
101
|
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: '0'
|
90
|
-
- !ruby/object:Gem::Dependency
|
91
|
-
name: rack
|
92
|
-
requirement: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: 2.2.3
|
97
|
-
type: :development
|
98
|
-
prerelease: false
|
99
|
-
version_requirements: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: 2.2.3
|
104
104
|
description: Twirp is a simple RPC framework with protobuf service definitions. The
|
105
105
|
Twirp gem provides native support for Ruby.
|
106
106
|
email:
|
@@ -129,11 +129,11 @@ files:
|
|
129
129
|
- test/license_header_test.rb
|
130
130
|
- test/service_test.rb
|
131
131
|
- twirp.gemspec
|
132
|
-
homepage: https://github.com/
|
132
|
+
homepage: https://github.com/arthurnn/twirp-ruby
|
133
133
|
licenses:
|
134
134
|
- MIT
|
135
135
|
metadata: {}
|
136
|
-
post_install_message:
|
136
|
+
post_install_message:
|
137
137
|
rdoc_options: []
|
138
138
|
require_paths:
|
139
139
|
- lib
|
@@ -149,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
149
|
version: '0'
|
150
150
|
requirements: []
|
151
151
|
rubygems_version: 3.3.3
|
152
|
-
signing_key:
|
152
|
+
signing_key:
|
153
153
|
specification_version: 4
|
154
154
|
summary: Twirp services in Ruby.
|
155
155
|
test_files:
|