twirp 0.5.2 → 1.0.0

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
  SHA1:
3
- metadata.gz: 1465cef8ea8070380498d84e1678ef5edd495a6e
4
- data.tar.gz: 97dda993421db600ef94146eede425f198f22145
3
+ metadata.gz: b8d83ed2c83e7cebf51801f40168dc7605e9e5be
4
+ data.tar.gz: cb2ce6ebc8517f887dfc4db4015f612330b85b8b
5
5
  SHA512:
6
- metadata.gz: 206d4febd931eb71b6cbccf555bbd05edf53d74104a9bcec72676298c49b38a6c1cb390efeb489fd7271fc4504c76276d9f588fba6bada377e83a0d706a7837a
7
- data.tar.gz: 230f965eeca4501b4618acc32cb7ccc89563831b9d70c621b5c05c88a4c180e86d0b98ee4fe7dca3805faa13583e72ca66d3666f761f49fa4d67e6ed25d14cf1
6
+ metadata.gz: ca5336f98853c5b86a85e60f5757f6c259d43c9635092937e40edd5f77b2e7756e7f7144335a9b3bb4a8e17f2d00dbccbd6aff52703f24beddb2c58fb471d254
7
+ data.tar.gz: 20c0c0f7b52e6e6fb041cdc9ec818ea096ce52535df779969c979fe450036a31bcfff031c9e89df02372e9cdcbf9ee5d6b0809734c2e80795bb06134a712526a
data/README.md CHANGED
@@ -1,245 +1,15 @@
1
- # Twirp
1
+ # Twirp-Ruby
2
2
 
3
- Twirp allows to easily define RPC services and clients that communicate using Protobuf or JSON over HTTP.
3
+ [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.
4
4
 
5
- The [Twirp protocol](https://twitchtv.github.io/twirp/docs/spec_v5.html) is implemented in multiple languages. This means that you can write your service in one language and automatically generate clients in other languages. Refer to the [Golang implementation](https://github.com/twitchtv/twirp) for more details on the project.
5
+ The [cannonical implementation](https://github.com/twitchtv/twirp) is in Golang. The Twirp-Ruby project in this repository is the Ruby implementation.
6
6
 
7
- ## Install
8
-
9
- Add `gem "twirp"` to your Gemfile, or install with
10
-
11
- ```
12
- gem install twirp
13
- ```
14
-
15
- Code generation works with [protoc](https://github.com/golang/protobuf) (the protobuf compiler)
16
- using the `--ruby_out` option to generate messages and `--twirp_ruby_out` to generate services and clients. Make sure to install `protoc` version 3+.
17
-
18
- Then use `go get` (Golang) to install the ruby_twirp protoc plugin:
19
-
20
- ```sh
21
- go get -u github.com/cyrusaf/ruby-twirp/protoc-gen-twirp_ruby
22
- ```
23
-
24
- ## Code Generation
25
-
26
- Service and client definitions can be auto-generated form a `.proto` file. For example, given a [Protobuf](https://developers.google.com/protocol-buffers/docs/proto3) file like [example/hello_world/service.proto](example/hello_world/service.proto), you can auto-generate proto and twirp files with the command:
27
-
28
- ```sh
29
- protoc --proto_path=. --ruby_out=. --twirp_ruby_out=. ./example/hello_world/service.proto
30
- ```
31
-
32
- ## Service DSL
33
-
34
- The generated code makes use of the service DSL. For example, the generated code for the `HelloWorld` service looks like this:
35
-
36
- ```ruby
37
- module Example
38
- class HelloWorldService < Twirp::Service
39
- package "example"
40
- service "HelloWorld"
41
- rpc :Hello, HelloRequest, HelloResponse, :ruby_method => :hello
42
- end
43
-
44
- class HelloWorldClient < Twirp::Client
45
- client_for HelloWorldService
46
- end
47
- end
48
- ```
49
-
50
- The `HelloRequest` and `HelloResponse` messages are expected to be [google-protobuf](https://github.com/google/protobuf/tree/master/ruby) messages. They are generated by `protoc`, but could also be defined from their DSL.
51
-
52
-
53
- ## Twirp Service Handler
54
-
55
- A handler implements the rpc methods. For example a handler for `HelloWorldService`:
56
-
57
- ```ruby
58
- class HelloWorldHandler
59
-
60
- def hello(req, env)
61
- if req.name.empty?
62
- return Twirp::Error.invalid_argument("is mandatory", argument: "name")
63
- end
64
-
65
- {message: "Hello #{req.name}"}
66
- end
67
-
68
- end
69
- ```
70
-
71
- For each rpc method:
72
-
73
- * The `req` argument is the input request message, already serialized.
74
- * The `env` argument is the Twirp environment with data related to the request (e.g. `env[:output_class]`), and other fields that could have been set from before-hooks (e.g. `env[:user_id]` from authentication).
75
- * The returned value is expected to be the response message (or its attributes), or a `Twirp::Error`.
76
-
77
-
78
- #### Start the Service
79
-
80
- Instantiate the service with your handler impementation. Here is where you would use dependency injection or any other extra setup.
81
-
82
- ```ruby
83
- handler = HelloWorldHandler.new()
84
- service = Example::HelloWorldService.new(handler)
85
- ```
86
-
87
- The service is a [Rack app](https://rack.github.io/), it be mounted in a Rails app (e.g. in /config/routes.rb: `mount service, at: service.full_name`). And are also compatible with many other HTTP frameworks. For example, to mount on Webrick with base_url "http://localhost:3000/twirp":
88
-
89
- ```ruby
90
- require 'rack'
91
-
92
- path_prefix = "/twirp/" + service.full_name
93
- server = WEBrick::HTTPServer.new(Port: 3000)
94
- server.mount path_prefix, Rack::Handler::WEBrick, service
95
- server.start
96
- ```
97
-
98
- #### Unit Tests
99
-
100
- Twirp already takes care of HTTP routing and serialization, you don't really need to test that part, insteadof that, focus on testing the handler using the method `.call_rpc(rpc_method, attrs={}, env={})` on the service:
101
-
102
- ```ruby
103
- require 'minitest/autorun'
104
-
105
- class HelloWorldHandlerTest < Minitest::Test
106
-
107
- def test_hello_responds_with_name
108
- resp = service.call_rpc :Hello, name: "World"
109
- assert_equal "Hello World", resp.message
110
- end
111
7
 
112
- def test_hello_name_is_mandatory
113
- twerr = service.call_rpc :Hello, name: ""
114
- assert_equal :invalid_argument, twerr.code
115
- end
116
-
117
- def service
118
- handler = HelloWorldHandler.new()
119
- Example::HelloWorldService.new(handler)
120
- end
121
- end
122
- ```
123
-
124
-
125
- ## Twirp Clients
126
-
127
- Instantiate a client with the service base url:
128
-
129
- ```ruby
130
- client = Example::HelloWorldClient.new("http://localhost:3000/twirp")
131
- ```
132
-
133
- Clients implement the same methods as the service handler. For example the client for `HelloWorldService` implements the `hello` method:
134
-
135
- ```ruby
136
- resp = client.hello(name: "World")
137
- ```
138
-
139
- As an alternative, in case that a service method collides with a Ruby method, you can always use the more general `.rpc` method:
140
-
141
- ```ruby
142
- resp = client.rpc(:Hello, name: "World") # alternative
143
- ```
144
-
145
- If the request fails, the response has an `error` with a `Twirp::Error`. If the request succeeds, the response has `data` with an instance of the response message class.
146
-
147
- ```ruby
148
- if resp.error
149
- puts resp.error # <Twirp::Error code:... msg:"..." meta:{...}>
150
- else
151
- puts resp.data # <Example::HelloResponse: message:"Hello World">
152
- end
153
- ```
154
-
155
- #### Configure Clients with Faraday
156
-
157
- While Twirp takes care of routing, serialization and error handling, other advanced HTTP options can be configured with [Faraday](https://github.com/lostisland/faraday) middleware. Clients can be initialized with a Faraday connection. For example:
158
-
159
- ```ruby
160
- conn = Faraday.new(:url => 'http://localhost:3000/twirp') do |c|
161
- c.use Faraday::Request::Retry
162
- c.use Faraday::Request::BasicAuthentication, 'login', 'pass'
163
- c.use Faraday::Response::Logger # log to STDOUT
164
- c.use Faraday::Adapter::NetHttp # can use different HTTP libraries
165
- end
166
-
167
- client = Example::HelloWorldClient.new(conn)
168
- ```
169
-
170
- #### Protobuf or JSON
171
-
172
- Protobuf is used by default. To serialize with JSON, set the `content_type` option as 2nd argument:
173
-
174
- ```ruby
175
- client = Example::HelloWorldClient.new(conn, content_type: "application/json")
176
- resp = client.hello(name: "World") # serialized with JSON
177
- ```
178
-
179
- #### Add-hoc JSON requests
180
-
181
- If you just want to make a few quick requests from the console, you can make a `ClientJSON` instance. This doesn't require a service definition at all, but in the other hand, request and response values are not validated. Responses are just a Hash with attributes.
182
-
183
- ```ruby
184
- client = Twirp::ClientJSON.new(conn, package: "example", service: "HelloWorld")
185
- resp = client.rpc(:Hello, name: "World") # serialized with JSON, resp.data is a plain Hash
186
- ```
187
-
188
-
189
- ## Server Hooks
190
-
191
- In the lifecycle of a server request, Twirp starts by routing the request to a valid RPC method. If routing fails, the `on_error` hook is called with a bad_route error. If routing succeeds, the `before` hook is called before calling the RPC method handler, and then either `on_success` or `on_error` depending if the response is a Twirp error or not.
192
-
193
- ```
194
- routing -> before -> handler -> on_success
195
- -> on_error
196
- ```
197
-
198
- On every request, one and only one of `on_success` or `on_error` is called.
199
-
200
-
201
- If exceptions are raised, the `exception_raised` hook is called. The exceptioni is wrapped with an internal Twirp error, and if the `on_error` hook was not called yet, then it is called with the wrapped exception.
202
-
203
-
204
- ```
205
- routing -> before -> handler
206
- ! exception_raised -> on_error
207
- ```
208
-
209
- Hooks are setup in the service instance. For example:
210
-
211
- ```ruby
212
- svc = Example::HelloWorldService.new(handler)
213
-
214
- svc.before do |rack_env, env|
215
- # Runs if properly routed to an rpc method, but before calling the method handler.
216
- # This is the only place to read the Rack env to access http request and middleware data.
217
- # The Twirp env has the same routing info as in the handler method, e.g. :rpc_method, :input and :input_class.
218
- # Returning a Twirp::Error here cancels the request, and the error is returned instead.
219
- # If an exception is raised, the exception_raised hook will be called followed by on_error.
220
- env[:user_id] = authenticate(rack_env)
221
- end
8
+ ## Install
222
9
 
223
- svc.on_success do |env|
224
- # Runs after the rpc method is handled, if it didn't return Twirp errors or raised exceptions.
225
- # The env[:output] contains the serialized message of class env[:ouput_class].
226
- # If an exception is raised, the exception_raised hook will be called.
227
- success_count += 1
228
- end
10
+ Add `gem "twirp"` to your Gemfile, or install with `gem install twirp`.
229
11
 
230
- svc.on_error do |twerr, env|
231
- # Runs on error responses, that is:
232
- # * bad_route errors
233
- # * before filters returning Twirp errors or raising exceptions.
234
- # * hander methods returning Twirp errors or raising exceptions.
235
- # Raised exceptions are wrapped with Twirp::Error.internal_with(e).
236
- # If an exception is raised here, the exception_raised hook will be called.
237
- error_count += 1
238
- end
239
12
 
240
- svc.exception_raised do |e, env|
241
- # Runs if an exception was raised from the handler or any of the hooks.
242
- puts "[Error] #{e}\n#{e.backtrace.join("\n")}"
243
- end
244
- ```
13
+ ## Documentation
245
14
 
15
+ [Go to the Wiki](https://github.com/twitchtv/twirp-ruby/wiki).
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  require_relative 'twirp/version'
2
15
  require_relative 'twirp/error'
3
16
  require_relative 'twirp/service'
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  require 'faraday'
2
15
 
3
16
  require_relative 'client_resp'
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  require_relative 'client'
2
15
 
3
16
  module Twirp
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  module Twirp
2
15
  class ClientResp
3
16
  attr_accessor :data
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  require 'json'
2
15
 
3
16
  module Twirp
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  module Twirp
2
15
 
3
16
  # Valid Twirp error codes and their mapping to related HTTP status.
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  require_relative 'encoding'
2
15
  require_relative 'error'
3
16
  require_relative 'service_dsl'
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  module Twirp
2
15
 
3
16
  module ServiceDSL
@@ -1,3 +1,16 @@
1
+ # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
+ # use this file except in compliance with the License. A copy of the License is
5
+ # located at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # or in the "license" file accompanying this file. This file is distributed on
10
+ # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11
+ # express or implied. See the License for the specific language governing
12
+ # permissions and limitations under the License.
13
+
1
14
  module Twirp
2
- VERSION = "0.5.2"
15
+ VERSION = "1.0.0"
3
16
  end
@@ -0,0 +1,37 @@
1
+ require 'minitest/autorun'
2
+
3
+ # Check that all .rb files in /lib have the license header.
4
+ class LicenseHeaderTest < Minitest::Test
5
+
6
+ LICENSE_HEADER_LINES = [
7
+ "# Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.",
8
+ "#",
9
+ "# Licensed under the Apache License, Version 2.0 (the \"License\"). You may not",
10
+ "# use this file except in compliance with the License. A copy of the License is",
11
+ "# located at",
12
+ "#",
13
+ "# http://www.apache.org/licenses/LICENSE-2.0",
14
+ "#",
15
+ "# or in the \"license\" file accompanying this file. This file is distributed on",
16
+ "# an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either",
17
+ "# express or implied. See the License for the specific language governing",
18
+ "# permissions and limitations under the License.",
19
+ ]
20
+
21
+ def test_files_have_license_header
22
+ test_dir = File.dirname(__FILE__)
23
+
24
+ files = Dir.glob("#{test_dir}/../lib/**/*.rb")
25
+ assert_operator files.size, :>, 1, "at least one file was loaded, otherwise the glob expression may be failing"
26
+
27
+ files.each do |filepath|
28
+ lines = File.read(filepath).split("\n")
29
+ assert_operator lines.size, :>, LICENSE_HEADER_LINES.size, "has license header"
30
+ LICENSE_HEADER_LINES.each_with_index do |license_line, i|
31
+ file_line = lines[i]
32
+ assert_equal license_line, file_line
33
+ end
34
+ end
35
+ end
36
+
37
+ end
@@ -11,15 +11,15 @@ 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/cyrusaf/ruby-twirp"
14
+ spec.homepage = "https://github.com/twitchtv/twirp-ruby"
15
15
  spec.license = "MIT"
16
16
 
17
17
  spec.files = Dir['lib/**/*'] + %w(Gemfile LICENSE README.md twirp.gemspec)
18
18
  spec.test_files = Dir['test/**/*']
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.required_ruby_version = '>= 1.9'
21
22
  spec.add_runtime_dependency 'google-protobuf', '~> 3.0', '>= 3.0.0'
22
- spec.add_runtime_dependency 'faraday', '~> 0'
23
-
23
+ spec.add_runtime_dependency 'faraday', '~> 0' # for clients
24
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.5.2
4
+ version: 1.0.0
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: 2018-04-13 00:00:00.000000000 Z
12
+ date: 2018-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-protobuf
@@ -84,9 +84,10 @@ files:
84
84
  - test/client_test.rb
85
85
  - test/error_test.rb
86
86
  - test/fake_services.rb
87
+ - test/license_header_test.rb
87
88
  - test/service_test.rb
88
89
  - twirp.gemspec
89
- homepage: https://github.com/cyrusaf/ruby-twirp
90
+ homepage: https://github.com/twitchtv/twirp-ruby
90
91
  licenses:
91
92
  - MIT
92
93
  metadata: {}
@@ -98,7 +99,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
99
  requirements:
99
100
  - - ">="
100
101
  - !ruby/object:Gem::Version
101
- version: '0'
102
+ version: '1.9'
102
103
  required_rubygems_version: !ruby/object:Gem::Requirement
103
104
  requirements:
104
105
  - - ">="
@@ -115,4 +116,5 @@ test_files:
115
116
  - test/client_test.rb
116
117
  - test/error_test.rb
117
118
  - test/fake_services.rb
119
+ - test/license_header_test.rb
118
120
  - test/service_test.rb