twirp 1.7.0 → 1.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0046cb23f769232f34b2ec9b85961ee1311e59d68458b08539a0bb4f5789e83
4
- data.tar.gz: dae8b79d9d9b05f95916f7676a228732f1ca3f3779174fde51a2a2f0e7b09f87
3
+ metadata.gz: 3f17d89c29073da7ebffa780c9e8577e10f2537e28900344d8a055e098aa5f3d
4
+ data.tar.gz: 2932fb1abec1db6b14c3b39e8b7d2f81e318c0bdc02639d83a99bdfacd26001f
5
5
  SHA512:
6
- metadata.gz: db7e199e1a1593e4f6493fa8675018740d8d946f418ef02964c64d6a94b3410aa7ec1e79f5655fea89741cf65acbd0bce7003bdc844d9640d577b9a81ac27c24
7
- data.tar.gz: db7a5ce35a8ca7b0b532594b0535c350f96667c4530830be14dfdb4016f142c21ff3939375183f7836d752ba3c31af70a910785829820b0ff7d1127f0b683c9a
6
+ metadata.gz: aca9edc089a15abfe4426880e8db8a8e2cac3f47ff056703e686dc14a3fe879a952a2b96c2de8bb06301b7406262601102c29fe48af6f9ead8775e9e2c76e35b
7
+ data.tar.gz: 10fc31c496e2fa4020ff9a643e08aa9ba333b0baa2324d1a42444ca6916d672a449eeef7ab22e674de81cc7a3e906d82fc97736714dfab29a999bfb4dd191f75
@@ -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
- resp = self.class.make_http_request(@conn, @service_full_name, rpc_method, Encoding::JSON, req_opts, body)
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
@@ -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 then msg_class.decode_json(bytes, ignore_unknown_fields: true)
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 then msg_class.encode_json(msg_obj, emit_defaults: true)
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
@@ -12,5 +12,5 @@
12
12
  # permissions and limitations under the License.
13
13
 
14
14
  module Twirp
15
- VERSION = "1.7.0"
15
+ VERSION = "1.7.2"
16
16
  end
@@ -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"}']
@@ -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.0
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-05 00:00:00.000000000 Z
12
+ date: 2020-11-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-protobuf