twirp 0.5.2 → 1.0.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 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