twirp 1.7.0 → 1.7.2
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/lib/twirp/client_json.rb +3 -1
- data/lib/twirp/encoding.rb +8 -3
- data/lib/twirp/version.rb +1 -1
- data/test/client_json_test.rb +14 -0
- data/test/service_test.rb +29 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f17d89c29073da7ebffa780c9e8577e10f2537e28900344d8a055e098aa5f3d
|
4
|
+
data.tar.gz: 2932fb1abec1db6b14c3b39e8b7d2f81e318c0bdc02639d83a99bdfacd26001f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aca9edc089a15abfe4426880e8db8a8e2cac3f47ff056703e686dc14a3fe879a952a2b96c2de8bb06301b7406262601102c29fe48af6f9ead8775e9e2c76e35b
|
7
|
+
data.tar.gz: 10fc31c496e2fa4020ff9a643e08aa9ba333b0baa2324d1a42444ca6916d672a449eeef7ab22e674de81cc7a3e906d82fc97736714dfab29a999bfb4dd191f75
|
data/lib/twirp/client_json.rb
CHANGED
@@ -24,6 +24,7 @@ module Twirp
|
|
24
24
|
|
25
25
|
package = opts[:package].to_s
|
26
26
|
service = opts[:service].to_s
|
27
|
+
@strict = opts.fetch( :strict, false )
|
27
28
|
raise ArgumentError.new("Missing option :service") if service.empty?
|
28
29
|
@service_full_name = package.empty? ? service : "#{package}.#{service}"
|
29
30
|
end
|
@@ -33,7 +34,8 @@ module Twirp
|
|
33
34
|
def rpc(rpc_method, attrs={}, req_opts=nil)
|
34
35
|
body = Encoding.encode_json(attrs)
|
35
36
|
|
36
|
-
|
37
|
+
encoding = @strict ? Encoding::JSON_STRICT : Encoding::JSON
|
38
|
+
resp = self.class.make_http_request(@conn, @service_full_name, rpc_method, encoding, req_opts, body)
|
37
39
|
if resp.status != 200
|
38
40
|
return ClientResp.new(nil, self.class.error_from_response(resp))
|
39
41
|
end
|
data/lib/twirp/encoding.rb
CHANGED
@@ -17,13 +17,18 @@ module Twirp
|
|
17
17
|
|
18
18
|
module Encoding
|
19
19
|
JSON = "application/json"
|
20
|
+
# An opt-in content type useful when curling or manually testing a twirp
|
21
|
+
# service. This will fail if unknown fields are encountered. The return
|
22
|
+
# content type will be application/json.
|
23
|
+
JSON_STRICT = "application/json; strict=true"
|
20
24
|
PROTO = "application/protobuf"
|
21
25
|
|
22
26
|
class << self
|
23
27
|
|
24
28
|
def decode(bytes, msg_class, content_type)
|
25
29
|
case content_type
|
26
|
-
when JSON
|
30
|
+
when JSON then msg_class.decode_json(bytes, ignore_unknown_fields: true)
|
31
|
+
when JSON_STRICT then msg_class.decode_json(bytes, ignore_unknown_fields: false)
|
27
32
|
when PROTO then msg_class.decode(bytes)
|
28
33
|
else raise ArgumentError.new("Invalid content_type")
|
29
34
|
end
|
@@ -31,7 +36,7 @@ module Twirp
|
|
31
36
|
|
32
37
|
def encode(msg_obj, msg_class, content_type)
|
33
38
|
case content_type
|
34
|
-
when JSON
|
39
|
+
when JSON, JSON_STRICT then msg_class.encode_json(msg_obj, emit_defaults: true)
|
35
40
|
when PROTO then msg_class.encode(msg_obj)
|
36
41
|
else raise ArgumentError.new("Invalid content_type")
|
37
42
|
end
|
@@ -46,7 +51,7 @@ module Twirp
|
|
46
51
|
end
|
47
52
|
|
48
53
|
def valid_content_type?(content_type)
|
49
|
-
content_type == JSON || content_type == PROTO
|
54
|
+
content_type == JSON || content_type == PROTO || content_type == JSON_STRICT
|
50
55
|
end
|
51
56
|
|
52
57
|
def valid_content_types
|
data/lib/twirp/version.rb
CHANGED
data/test/client_json_test.rb
CHANGED
@@ -29,6 +29,20 @@ class ClientJSONTest < Minitest::Test
|
|
29
29
|
assert_equal 3, resp.data["blah_resp"]
|
30
30
|
end
|
31
31
|
|
32
|
+
def test_client_json_strict_encoding
|
33
|
+
c = Twirp::ClientJSON.new(conn_stub("/my.pkg.Talking/Blah") {|req|
|
34
|
+
assert_equal "application/json; strict=true", req.request_headers['Content-Type']
|
35
|
+
assert_equal '{"blah1":1,"blah2":2}', req.body # body is json
|
36
|
+
|
37
|
+
[200, {}, '{"blah_resp": 3}']
|
38
|
+
}, package: "my.pkg", service: "Talking", strict: true)
|
39
|
+
|
40
|
+
resp = c.rpc :Blah, blah1: 1, blah2: 2
|
41
|
+
assert_nil resp.error
|
42
|
+
refute_nil resp.data
|
43
|
+
assert_equal 3, resp.data["blah_resp"]
|
44
|
+
end
|
45
|
+
|
32
46
|
def test_client_json_error
|
33
47
|
c = Twirp::ClientJSON.new(conn_stub("/Foo/Foomo") {|req|
|
34
48
|
[400, {}, '{"code": "invalid_argument", "msg": "dont like empty"}']
|
data/test/service_test.rb
CHANGED
@@ -64,6 +64,15 @@ class ServiceTest < Minitest::Test
|
|
64
64
|
assert_equal({"inches" => 10, "color" => "white"}, JSON.parse(body[0]))
|
65
65
|
end
|
66
66
|
|
67
|
+
def test_successful_json_strict_request_emit_defaults
|
68
|
+
rack_env = json_strict_req "/example.Haberdasher/MakeHat", inches: 0 # default int value
|
69
|
+
status, headers, body = haberdasher_service.call(rack_env)
|
70
|
+
|
71
|
+
assert_equal 200, status
|
72
|
+
assert_equal 'application/json; strict=true', headers['Content-Type']
|
73
|
+
assert_equal({"inches" => 0, "color" => "white"}, JSON.parse(body[0]))
|
74
|
+
end
|
75
|
+
|
67
76
|
def test_successful_json_request_emit_defaults
|
68
77
|
rack_env = json_req "/example.Haberdasher/MakeHat", inches: 0 # default int value
|
69
78
|
status, headers, body = haberdasher_service.call(rack_env)
|
@@ -188,6 +197,20 @@ class ServiceTest < Minitest::Test
|
|
188
197
|
assert_equal({"inches" => 10, "color" => "white"}, JSON.parse(body[0]))
|
189
198
|
end
|
190
199
|
|
200
|
+
def test_json_strict_request_fails_unknown_fields
|
201
|
+
rack_env = json_strict_req "/example.Haberdasher/MakeHat", inches: 10, fake: 3
|
202
|
+
status, headers, body = haberdasher_service.call(rack_env)
|
203
|
+
|
204
|
+
assert_equal 400, status
|
205
|
+
assert_equal 'application/json', headers['Content-Type']
|
206
|
+
assert_equal({
|
207
|
+
"code" => 'malformed',
|
208
|
+
"msg" => 'Invalid request body for rpc method "MakeHat" with Content-Type=application/json; strict=true: ' +
|
209
|
+
"Error occurred during parsing: No such field: fake",
|
210
|
+
"meta" => {"twirp_invalid_route" => "POST /example.Haberdasher/MakeHat"},
|
211
|
+
}, JSON.parse(body[0]))
|
212
|
+
end
|
213
|
+
|
191
214
|
def test_bad_route_triggers_on_error_hooks
|
192
215
|
svc = haberdasher_service
|
193
216
|
|
@@ -809,6 +832,12 @@ class ServiceTest < Minitest::Test
|
|
809
832
|
"CONTENT_TYPE" => "application/json"
|
810
833
|
end
|
811
834
|
|
835
|
+
def json_strict_req(path, attrs)
|
836
|
+
Rack::MockRequest.env_for path, method: "POST",
|
837
|
+
input: JSON.generate(attrs),
|
838
|
+
"CONTENT_TYPE" => "application/json; strict=true"
|
839
|
+
end
|
840
|
+
|
812
841
|
def proto_req(path, proto_message)
|
813
842
|
Rack::MockRequest.env_for path, method: "POST",
|
814
843
|
input: proto_message.class.encode(proto_message),
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twirp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyrus A. Forbes
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-11-
|
12
|
+
date: 2020-11-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: google-protobuf
|