twirp 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,7 +29,11 @@ module Example
29
29
  class Haberdasher < Twirp::Service
30
30
  package "example"
31
31
  service "Haberdasher"
32
- rpc :MakeHat, Size, Hat, :handler_method => :make_hat
32
+ rpc :MakeHat, Size, Hat, :ruby_method => :make_hat
33
+ end
34
+
35
+ class HaberdasherClient < Twirp::Client
36
+ client_for Haberdasher
33
37
  end
34
38
  end
35
39
 
@@ -48,3 +52,19 @@ end
48
52
  # Twirp Service with no package and no rpc methods.
49
53
  class EmptyService < Twirp::Service
50
54
  end
55
+ class EmptyClient < Twirp::Client
56
+ end
57
+
58
+ # Foo message
59
+ Google::Protobuf::DescriptorPool.generated_pool.build do
60
+ add_message "Foo" do
61
+ optional :foo, :string, 1
62
+ end
63
+ end
64
+ Foo = Google::Protobuf::DescriptorPool.generated_pool.lookup("Foo").msgclass
65
+
66
+ # Foo Client
67
+ class FooClient < Twirp::Client
68
+ service "Foo"
69
+ rpc :Foo, Foo, Foo, :ruby_method => :foo
70
+ end
@@ -13,14 +13,14 @@ class ServiceTest < Minitest::Test
13
13
  end
14
14
 
15
15
  # The rpc DSL should properly build the base Twirp environment for each rpc method.
16
- def test_base_envs_accessor
17
- assert_equal 1, Example::Haberdasher.base_envs.size
16
+ def test_rpcs_accessor
17
+ assert_equal 1, Example::Haberdasher.rpcs.size
18
18
  assert_equal({
19
19
  rpc_method: :MakeHat,
20
20
  input_class: Example::Size,
21
21
  output_class: Example::Hat,
22
- handler_method: :make_hat,
23
- }, Example::Haberdasher.base_envs["MakeHat"])
22
+ ruby_method: :make_hat,
23
+ }, Example::Haberdasher.rpcs["MakeHat"])
24
24
  end
25
25
 
26
26
  # DSL package and service define the proper data on the service
@@ -33,7 +33,7 @@ class ServiceTest < Minitest::Test
33
33
  assert_equal "EmptyService", EmptyService.service_name # defaults to class name
34
34
  assert_equal "EmptyService", EmptyService.service_full_name # with no package is just the service name
35
35
  end
36
-
36
+
37
37
  def test_init_service
38
38
  svc = Example::Haberdasher.new(HaberdasherHandler.new)
39
39
  assert svc.respond_to?(:call) # so it is a Proc that can be used as Rack middleware
@@ -71,35 +71,35 @@ class ServiceTest < Minitest::Test
71
71
  assert_equal 404, status
72
72
  assert_equal 'application/json', headers['Content-Type']
73
73
  assert_equal({
74
- "code" => 'bad_route',
74
+ "code" => 'bad_route',
75
75
  "msg" => 'Invalid rpc method "MakeUnicorns"',
76
76
  "meta" => {"twirp_invalid_route" => "POST /twirp/example.Haberdasher/MakeUnicorns"},
77
- }, JSON.parse(body[0]))
77
+ }, JSON.parse(body[0]))
78
78
  end
79
79
 
80
80
  def test_bad_route_with_wrong_http_method
81
- rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
81
+ rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
82
82
  method: "GET", input: '{"inches": 10}', "CONTENT_TYPE" => "application/json"
83
83
  status, headers, body = haberdasher_service.call(rack_env)
84
84
 
85
85
  assert_equal 404, status
86
86
  assert_equal 'application/json', headers['Content-Type']
87
87
  assert_equal({
88
- "code" => 'bad_route',
88
+ "code" => 'bad_route',
89
89
  "msg" => 'HTTP request method must be POST',
90
90
  "meta" => {"twirp_invalid_route" => "GET /example.Haberdasher/MakeHat"},
91
91
  }, JSON.parse(body[0]))
92
92
  end
93
93
 
94
94
  def test_bad_route_with_wrong_content_type
95
- rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
95
+ rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
96
96
  method: "POST", input: 'free text', "CONTENT_TYPE" => "text/plain"
97
97
  status, headers, body = haberdasher_service.call(rack_env)
98
98
 
99
99
  assert_equal 404, status
100
100
  assert_equal 'application/json', headers['Content-Type']
101
101
  assert_equal({
102
- "code" => 'bad_route',
102
+ "code" => 'bad_route',
103
103
  "msg" => 'unexpected Content-Type: "text/plain". Content-Type header must be one of application/json or application/protobuf',
104
104
  "meta" => {"twirp_invalid_route" => "POST /example.Haberdasher/MakeHat"},
105
105
  }, JSON.parse(body[0]))
@@ -112,7 +112,7 @@ class ServiceTest < Minitest::Test
112
112
  assert_equal 404, status
113
113
  assert_equal 'application/json', headers['Content-Type']
114
114
  assert_equal({
115
- "code" => 'bad_route',
115
+ "code" => 'bad_route',
116
116
  "msg" => 'Invalid route. Expected format: POST {BaseURL}/example.Haberdasher/{Method}',
117
117
  "meta" => {"twirp_invalid_route" => "POST /wrongpath"},
118
118
  }, JSON.parse(body[0]))
@@ -125,35 +125,35 @@ class ServiceTest < Minitest::Test
125
125
  assert_equal 404, status
126
126
  assert_equal 'application/json', headers['Content-Type'] # error responses are always JSON, even for Protobuf requests
127
127
  assert_equal({
128
- "code" => 'bad_route',
128
+ "code" => 'bad_route',
129
129
  "msg" => 'Invalid route. Expected format: POST {BaseURL}/example.Haberdasher/{Method}',
130
130
  "meta" => {"twirp_invalid_route" => "POST /another/wrong.Path/MakeHat"},
131
131
  }, JSON.parse(body[0]))
132
132
  end
133
133
 
134
134
  def test_bad_route_with_wrong_json_body
135
- rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
135
+ rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
136
136
  method: "POST", input: 'bad json', "CONTENT_TYPE" => "application/json"
137
137
  status, headers, body = haberdasher_service.call(rack_env)
138
138
 
139
139
  assert_equal 404, status
140
140
  assert_equal 'application/json', headers['Content-Type']
141
141
  assert_equal({
142
- "code" => 'bad_route',
142
+ "code" => 'bad_route',
143
143
  "msg" => 'Invalid request body for rpc method "MakeHat" with Content-Type=application/json',
144
144
  "meta" => {"twirp_invalid_route" => "POST /example.Haberdasher/MakeHat"},
145
145
  }, JSON.parse(body[0]))
146
146
  end
147
147
 
148
148
  def test_bad_route_with_wrong_protobuf_body
149
- rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
149
+ rack_env = Rack::MockRequest.env_for "example.Haberdasher/MakeHat",
150
150
  method: "POST", input: 'bad protobuf', "CONTENT_TYPE" => "application/protobuf"
151
151
  status, headers, body = haberdasher_service.call(rack_env)
152
152
 
153
153
  assert_equal 404, status
154
154
  assert_equal 'application/json', headers['Content-Type']
155
155
  assert_equal({
156
- "code" => 'bad_route',
156
+ "code" => 'bad_route',
157
157
  "msg" => 'Invalid request body for rpc method "MakeHat" with Content-Type=application/protobuf',
158
158
  "meta" => {"twirp_invalid_route" => "POST /example.Haberdasher/MakeHat"},
159
159
  }, JSON.parse(body[0]))
@@ -230,7 +230,7 @@ class ServiceTest < Minitest::Test
230
230
  assert_equal 400, status
231
231
  assert_equal 'application/json', headers['Content-Type'] # error responses are always JSON, even for Protobuf requests
232
232
  assert_equal({
233
- "code" => 'invalid_argument',
233
+ "code" => 'invalid_argument',
234
234
  "msg" => "I don't like that size",
235
235
  }, JSON.parse(body[0]))
236
236
  end
@@ -243,7 +243,7 @@ class ServiceTest < Minitest::Test
243
243
 
244
244
  rack_env = proto_req "/example.Haberdasher/MakeHat", Example::Size.new
245
245
  status, headers, body = svc.call(rack_env)
246
-
246
+
247
247
  assert_equal 200, status
248
248
  assert_equal "public, max-age=60", headers["Cache-Control"] # set by the handler
249
249
  assert_equal "application/protobuf", headers["Content-Type"] # set by Twirp::Service
@@ -397,7 +397,7 @@ class ServiceTest < Minitest::Test
397
397
  assert_equal 500, status
398
398
  refute handler_called
399
399
  assert_equal({
400
- "code" => 'intenal',
400
+ "code" => 'intenal',
401
401
  "msg" => 'error from before hook',
402
402
  }, JSON.parse(body[0]))
403
403
  end
@@ -474,7 +474,7 @@ class ServiceTest < Minitest::Test
474
474
  assert_equal 500, status
475
475
  assert_equal 'application/json', headers['Content-Type']
476
476
  assert_equal({
477
- "code" => 'intenal',
477
+ "code" => 'intenal',
478
478
  "msg" => 'hook1 failed',
479
479
  }, JSON.parse(body[0]))
480
480
 
@@ -517,7 +517,7 @@ class ServiceTest < Minitest::Test
517
517
  assert_equal 500, status
518
518
  refute success_called # after hook not called
519
519
  assert_equal({
520
- "code" => 'intenal',
520
+ "code" => 'intenal',
521
521
  "msg" => 'error from handler',
522
522
  }, JSON.parse(body[0]))
523
523
  end
@@ -591,7 +591,7 @@ class ServiceTest < Minitest::Test
591
591
 
592
592
  assert_equal 500, status
593
593
  assert_equal({
594
- "code" => 'intenal',
594
+ "code" => 'intenal',
595
595
  "msg" => 'before failed',
596
596
  }, JSON.parse(body[0]))
597
597
  assert error_called
@@ -634,7 +634,7 @@ class ServiceTest < Minitest::Test
634
634
  svc = Example::Haberdasher.new(HaberdasherHandler.new do |size, env|
635
635
  return Twirp::Error.internal "handler error"
636
636
  end)
637
-
637
+
638
638
  error_called = false
639
639
  svc.on_error do |twerr, env|
640
640
  error_called = true
@@ -647,7 +647,7 @@ class ServiceTest < Minitest::Test
647
647
 
648
648
  assert_equal 500, status
649
649
  assert_equal({
650
- "code" => 'intenal',
650
+ "code" => 'intenal',
651
651
  "msg" => 'handler error',
652
652
  }, JSON.parse(body[0]))
653
653
  assert error_called
@@ -771,18 +771,17 @@ class ServiceTest < Minitest::Test
771
771
 
772
772
 
773
773
 
774
-
775
774
  # Test Helpers
776
775
  # ------------
777
776
 
778
777
  def json_req(path, attrs)
779
- Rack::MockRequest.env_for path, method: "POST",
778
+ Rack::MockRequest.env_for path, method: "POST",
780
779
  input: JSON.generate(attrs),
781
780
  "CONTENT_TYPE" => "application/json"
782
781
  end
783
782
 
784
783
  def proto_req(path, proto_message)
785
- Rack::MockRequest.env_for path, method: "POST",
784
+ Rack::MockRequest.env_for path, method: "POST",
786
785
  input: proto_message.class.encode(proto_message),
787
786
  "CONTENT_TYPE" => "application/protobuf"
788
787
  end
@@ -10,16 +10,16 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ["Cyrus A. Forbes", "Mario Izquierdo"]
11
11
  spec.email = ["forbescyrus@gmail.com", "tothemario@gmail.com"]
12
12
  spec.summary = %q{Twirp services in Ruby.}
13
- spec.description = %q{Twirp is a simple RPC framework with protobuf service definitions. The Twirp gem provides support for Ruby.}
13
+ spec.description = %q{Twirp is a simple RPC framework with protobuf service definitions. The Twirp gem provides native support for Ruby.}
14
14
  spec.homepage = "https://github.com/cyrusaf/ruby-twirp"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.files = `git ls-files -z`.split("\x0")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.files = Dir['lib/**/*'] + %w(Gemfile LICENSE README.md twirp.gemspec)
18
+ spec.test_files = Dir['test/**/*']
20
19
  spec.require_paths = ["lib"]
21
20
 
22
- spec.add_runtime_dependency 'google-protobuf', '>= 3.0.0'
21
+ spec.add_runtime_dependency 'google-protobuf', '~> 3.0', '>= 3.0.0'
22
+ spec.add_runtime_dependency 'faraday', '~> 0'
23
23
 
24
- spec.add_development_dependency 'bundler', '>= 1'
24
+ spec.add_development_dependency 'bundler', '~> 1'
25
25
  end
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: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyrus A. Forbes
@@ -9,12 +9,15 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-03-12 00:00:00.000000000 Z
12
+ date: 2018-04-07 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'
18
21
  - - ">="
19
22
  - !ruby/object:Gem::Version
20
23
  version: 3.0.0
@@ -22,25 +25,42 @@ dependencies:
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '3.0'
25
31
  - - ">="
26
32
  - !ruby/object:Gem::Version
27
33
  version: 3.0.0
34
+ - !ruby/object:Gem::Dependency
35
+ name: faraday
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
28
48
  - !ruby/object:Gem::Dependency
29
49
  name: bundler
30
50
  requirement: !ruby/object:Gem::Requirement
31
51
  requirements:
32
- - - ">="
52
+ - - "~>"
33
53
  - !ruby/object:Gem::Version
34
54
  version: '1'
35
55
  type: :development
36
56
  prerelease: false
37
57
  version_requirements: !ruby/object:Gem::Requirement
38
58
  requirements:
39
- - - ">="
59
+ - - "~>"
40
60
  - !ruby/object:Gem::Version
41
61
  version: '1'
42
62
  description: Twirp is a simple RPC framework with protobuf service definitions. The
43
- Twirp gem provides support for Ruby.
63
+ Twirp gem provides native support for Ruby.
44
64
  email:
45
65
  - forbescyrus@gmail.com
46
66
  - tothemario@gmail.com
@@ -48,22 +68,16 @@ executables: []
48
68
  extensions: []
49
69
  extra_rdoc_files: []
50
70
  files:
51
- - ".gitignore"
52
71
  - Gemfile
53
- - Gemfile.lock
54
72
  - LICENSE
55
73
  - README.md
56
- - example/Gemfile
57
- - example/Gemfile.lock
58
- - example/gen/haberdasher_pb.rb
59
- - example/gen/haberdasher_twirp.rb
60
- - example/haberdasher.proto
61
- - example/main.rb
62
74
  - lib/twirp.rb
75
+ - lib/twirp/client.rb
63
76
  - lib/twirp/error.rb
64
77
  - lib/twirp/service.rb
78
+ - lib/twirp/service_dsl.rb
65
79
  - lib/twirp/version.rb
66
- - protoc-gen-twirp_ruby/main.go
80
+ - test/client_test.rb
67
81
  - test/error_test.rb
68
82
  - test/fake_services.rb
69
83
  - test/service_test.rb
@@ -88,11 +102,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
102
  version: '0'
89
103
  requirements: []
90
104
  rubyforge_project:
91
- rubygems_version: 2.6.14
105
+ rubygems_version: 2.6.8
92
106
  signing_key:
93
107
  specification_version: 4
94
108
  summary: Twirp services in Ruby.
95
109
  test_files:
110
+ - test/client_test.rb
96
111
  - test/error_test.rb
97
112
  - test/fake_services.rb
98
113
  - test/service_test.rb
data/.gitignore DELETED
@@ -1 +0,0 @@
1
- *.gem
@@ -1,20 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- twirp (0.0.1)
5
- google-protobuf (>= 3.0.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- google-protobuf (3.5.1.2)
11
-
12
- PLATFORMS
13
- ruby
14
-
15
- DEPENDENCIES
16
- bundler (>= 1)
17
- twirp!
18
-
19
- BUNDLED WITH
20
- 1.14.6
@@ -1,7 +0,0 @@
1
-
2
- source "https://rubygems.org"
3
-
4
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
5
-
6
- gem "twirp"
7
- gem "rack"
@@ -1,17 +0,0 @@
1
- GEM
2
- remote: https://rubygems.org/
3
- specs:
4
- google-protobuf (3.5.1.2)
5
- rack (2.0.1)
6
- twirp (0.0.1)
7
- google-protobuf (>= 3.0.0)
8
-
9
- PLATFORMS
10
- ruby
11
-
12
- DEPENDENCIES
13
- rack
14
- twirp
15
-
16
- BUNDLED WITH
17
- 1.16.1
@@ -1,18 +0,0 @@
1
- # Generated by the protocol buffer compiler. DO NOT EDIT!
2
- # source: haberdasher.proto
3
-
4
- require 'google/protobuf'
5
-
6
- Google::Protobuf::DescriptorPool.generated_pool.build do
7
- add_message "example.HelloWorldRequest" do
8
- optional :name, :string, 1
9
- end
10
- add_message "example.HelloWorldResponse" do
11
- optional :message, :string, 1
12
- end
13
- end
14
-
15
- module Example
16
- HelloWorldRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("example.HelloWorldRequest").msgclass
17
- HelloWorldResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("example.HelloWorldResponse").msgclass
18
- end
@@ -1,10 +0,0 @@
1
- # Code generated by protoc-gen-twirp_ruby, DO NOT EDIT.
2
- require 'twirp'
3
-
4
- module Example
5
- class HaberdasherService < Twirp::Service
6
- package "example"
7
- service "Haberdasher"
8
- rpc :HelloWorld, HelloWorldRequest, HelloWorldResponse, :handler_method => :hello_world
9
- end
10
- end