twirp 0.0.1 → 0.0.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
  SHA1:
3
- metadata.gz: cd5d364eb9a55aa4f9f80a217d0c25a9a3b5377d
4
- data.tar.gz: add09813fd7965e1c510b5774a30445e66859b3e
3
+ metadata.gz: 2de989bef622a106065d7cad486cd575cc10d783
4
+ data.tar.gz: 5e01d8fae314ab0f4c53e64f9ede154aef54eafb
5
5
  SHA512:
6
- metadata.gz: 1a0e61629575ec564449543c16b6c4842541abaea0c97e944318aea5ed385941b155371cbe2926faf2fe0c50824d46d1eb44302bed983749859599b6906d9063
7
- data.tar.gz: f4113090daee32f775653c563fdb2ba60bad0d34ccc0b2287e8636b820288411933d20e41988d43ae17035db737e3e7cdce4079ad888fd16a4fc14a4eb8ee608
6
+ metadata.gz: 609f958dec7ba47552c36bd54a96aa7404e602f56ed669e22401deccf9e4568852beac96d09fe40cf81bf42bc601c811d6165fc1a2b1d67c6b92fa1412c26307
7
+ data.tar.gz: a7414cf878277e142d4b52a1492f03f8e37bfe71fe82ff1046c29199cd9405a5e8e59f4be13b26ecb69ed0d9d689eef98d5378da93ea6fbfa6e365ada542709f
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/README.md CHANGED
@@ -1,3 +1,81 @@
1
1
  # Ruby Twirp
2
2
 
3
3
  Twirp services and clients in Ruby.
4
+
5
+ ### Installation
6
+ Use `go get` to install the ruby_twirp protoc plugin:
7
+ ```
8
+ ➜ go get github.com/cyrusaf/ruby-twirp/protoc-gen-twirp_ruby
9
+ ```
10
+
11
+ You will also need:
12
+ - [protoc](https://github.com/golang/protobuf), the protobuf compiler. You need
13
+ version 3+.
14
+
15
+ ### Haberdasher Example
16
+ See the `examples/` folder for the final product.
17
+
18
+ First create a basic `.proto` file:
19
+ ```
20
+ // haberdasher.proto
21
+ syntax = "proto3";
22
+ package examples;
23
+
24
+ service Haberdasher {
25
+ rpc HelloWorld(HelloWorldRequest) returns (HelloWorldResponse);
26
+ }
27
+
28
+ message HelloWorldRequest {
29
+ string name = 1;
30
+ }
31
+
32
+ message HelloWorldResponse {
33
+ string message = 1;
34
+ }
35
+
36
+ ```
37
+
38
+ Run the `protoc` binary to generate `gen/haberdasher_pb.rb` and `gen/haberdasher_twirp.rb`.
39
+ ```
40
+ ➜ protoc --proto_path=. ./haberdasher.proto --ruby_out=gen --twirp_ruby_out=gen
41
+ ```
42
+
43
+ Write an implementation of our haberdasher service and attach to a rack server:
44
+ ```
45
+ # config.ru
46
+ require 'rack'
47
+ require_relative 'gen/haberdasher_pb.rb'
48
+ require_relative 'gen/haberdasher_twirp.rb'
49
+
50
+ class HaberdasherImplementation
51
+ def HelloWorld(req)
52
+ return Examples::HelloWorldResponse.new(message: "Hello #{req.name}")
53
+ end
54
+ end
55
+
56
+ svc = HaberdasherImplementation.new()
57
+ run Rack::URLMap.new HaberdasherService::PATH_PREFIX => HaberdasherService.new(svc).handler
58
+ ```
59
+
60
+ You can also mount onto a rails service:
61
+ ```
62
+ App::Application.routes.draw do
63
+ svc = HaberdasherImplementation.new()
64
+ mount HaberdasherServer.new(svc).handler, at: HaberdasherServer::PATH_PREFIX
65
+ end
66
+ ```
67
+
68
+ Run `config.ru` to start the server on port 8080:
69
+ ```
70
+ ➜ rackup
71
+ ```
72
+
73
+ `curl` your server to get a response:
74
+ ```
75
+ ➜ curl --request POST \
76
+ --url http://localhost:8080/twirp/examples.Haberdasher/HelloWorld \
77
+ --header 'content-type: application/json' \
78
+ --data '{
79
+ "name": "World"
80
+ }'
81
+ ```
data/examples/Gemfile ADDED
@@ -0,0 +1,7 @@
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"
@@ -0,0 +1,17 @@
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
@@ -0,0 +1,12 @@
1
+ require 'rack'
2
+ require_relative 'gen/haberdasher_pb.rb'
3
+ require_relative 'gen/haberdasher_twirp.rb'
4
+
5
+ class HaberdasherImplementation
6
+ def HelloWorld(req)
7
+ return Examples::HelloWorldResponse.new(message: "Hello #{req.name}")
8
+ end
9
+ end
10
+
11
+ svc = HaberdasherImplementation.new()
12
+ run Rack::URLMap.new HaberdasherService::PATH_PREFIX => HaberdasherService.new(svc).handler
@@ -0,0 +1,18 @@
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 "examples.HelloWorldRequest" do
8
+ optional :name, :string, 1
9
+ end
10
+ add_message "examples.HelloWorldResponse" do
11
+ optional :message, :string, 1
12
+ end
13
+ end
14
+
15
+ module Examples
16
+ HelloWorldRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("examples.HelloWorldRequest").msgclass
17
+ HelloWorldResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("examples.HelloWorldResponse").msgclass
18
+ end
@@ -0,0 +1,7 @@
1
+ # Code generated by protoc-gen-twirp_ruby, DO NOT EDIT.
2
+ require 'twirp'
3
+
4
+ class HaberdasherService < Twirp::Service
5
+ PATH_PREFIX = "/twirp/examples.Haberdasher"
6
+ rpc :HelloWorld, Examples::HelloWorldRequest, Examples::HelloWorldResponse
7
+ end
@@ -0,0 +1,14 @@
1
+ syntax = "proto3";
2
+ package examples;
3
+
4
+ service Haberdasher {
5
+ rpc HelloWorld(HelloWorldRequest) returns (HelloWorldResponse);
6
+ }
7
+
8
+ message HelloWorldRequest {
9
+ string name = 1;
10
+ }
11
+
12
+ message HelloWorldResponse {
13
+ string message = 1;
14
+ }
data/lib/twirp.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  require_relative 'twirp/version'
2
2
  require_relative 'twirp/error'
3
+ require_relative 'twirp/service'
@@ -1,5 +1,5 @@
1
1
  module Twirp
2
- class Server
2
+ class Service
3
3
  @@rpcs = {}
4
4
 
5
5
  def initialize(svc)
@@ -34,13 +34,13 @@ module Twirp
34
34
 
35
35
  def serve_json(req, method_name, request_class, response_class)
36
36
  params = request_class.decode_json(req.body.read)
37
- resp = @svc.send(method_name.underscore, params)
37
+ resp = @svc.send(method_name, params)
38
38
  self.serve_success_json(response_class.encode_json(resp))
39
39
  end
40
40
 
41
41
  def serve_proto(req, method_name, request_class, response_class)
42
42
  params = request_type.decode(req.body.read)
43
- resp = @svc.send(method_name.underscore, params)
43
+ resp = @svc.send(method_name, params)
44
44
  self.serve_success_proto(response_class.encode(resp))
45
45
  end
46
46
 
data/lib/twirp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Twirp
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -72,14 +72,15 @@ func (g *generator) generateFile(file *descriptor.FileDescriptorProto) *plugin.C
72
72
  g.P(`# Code generated by protoc-gen-twirp_ruby, DO NOT EDIT.`)
73
73
  for _, service := range file.Service {
74
74
  serviceName := serviceName(service)
75
+ g.P(`require 'twirp'`)
75
76
  g.P(``)
76
- g.P(fmt.Sprintf("class %s < Twirp::Server", serviceName))
77
- g.P(fmt.Sprintf(`PATH_PREFIX = "/twirp/%s.%s"`, pkgName, serviceName))
77
+ g.P(fmt.Sprintf("class %sService < Twirp::Service", serviceName))
78
+ g.P(fmt.Sprintf(` PATH_PREFIX = "/twirp/%s.%s"`, pkgName, serviceName))
78
79
  for _, method := range service.GetMethod() {
79
80
  methName := methodName(method)
80
81
  inputName := methodInputName(method)
81
82
  outputName := methodOutputName(method)
82
- g.P(fmt.Sprintf(" rpc :%s, %s, %s", methName, inputName, outputName))
83
+ g.P(fmt.Sprintf(" rpc :%s, %s::%s, %s::%s", methName, CamelCase(pkgName), inputName, CamelCase(pkgName), outputName))
83
84
  }
84
85
  g.P(`end`)
85
86
  }
@@ -183,3 +184,61 @@ func writeResponse(w io.Writer, resp *plugin.CodeGeneratorResponse) {
183
184
  Fail(err.Error(), "writing response")
184
185
  }
185
186
  }
187
+
188
+ // CamelCase converts a string from snake_case to CamelCased.
189
+ //
190
+ // If there is an interior underscore followed by a lower case letter, drop the
191
+ // underscore and convert the letter to upper case. There is a remote
192
+ // possibility of this rewrite causing a name collision, but it's so remote
193
+ // we're prepared to pretend it's nonexistent - since the C++ generator
194
+ // lowercases names, it's extremely unlikely to have two fields with different
195
+ // capitalizations. In short, _my_field_name_2 becomes XMyFieldName_2.
196
+ func CamelCase(s string) string {
197
+ if s == "" {
198
+ return ""
199
+ }
200
+ t := make([]byte, 0, 32)
201
+ i := 0
202
+ if s[0] == '_' {
203
+ // Need a capital letter; drop the '_'.
204
+ t = append(t, 'X')
205
+ i++
206
+ }
207
+ // Invariant: if the next letter is lower case, it must be converted
208
+ // to upper case.
209
+ //
210
+ // That is, we process a word at a time, where words are marked by _ or upper
211
+ // case letter. Digits are treated as words.
212
+ for ; i < len(s); i++ {
213
+ c := s[i]
214
+ if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
215
+ continue // Skip the underscore in s.
216
+ }
217
+ if isASCIIDigit(c) {
218
+ t = append(t, c)
219
+ continue
220
+ }
221
+ // Assume we have a letter now - if not, it's a bogus identifier. The next
222
+ // word is a sequence of characters that must start upper case.
223
+ if isASCIILower(c) {
224
+ c ^= ' ' // Make it a capital letter.
225
+ }
226
+ t = append(t, c) // Guaranteed not lower case.
227
+ // Accept lower case sequence that follows.
228
+ for i+1 < len(s) && isASCIILower(s[i+1]) {
229
+ i++
230
+ t = append(t, s[i])
231
+ }
232
+ }
233
+ return string(t)
234
+ }
235
+
236
+ // Is c an ASCII lower-case letter?
237
+ func isASCIILower(c byte) bool {
238
+ return 'a' <= c && c <= 'z'
239
+ }
240
+
241
+ // Is c an ASCII digit?
242
+ func isASCIIDigit(c byte) bool {
243
+ return '0' <= c && c <= '9'
244
+ }
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.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyrus A. Forbes
@@ -48,12 +48,19 @@ executables: []
48
48
  extensions: []
49
49
  extra_rdoc_files: []
50
50
  files:
51
+ - ".gitignore"
51
52
  - Gemfile
52
53
  - Gemfile.lock
53
54
  - README.md
55
+ - examples/Gemfile
56
+ - examples/Gemfile.lock
57
+ - examples/config.ru
58
+ - examples/gen/haberdasher_pb.rb
59
+ - examples/gen/haberdasher_twirp.rb
60
+ - examples/haberdasher.proto
54
61
  - lib/twirp.rb
55
62
  - lib/twirp/error.rb
56
- - lib/twirp/server.rb
63
+ - lib/twirp/service.rb
57
64
  - lib/twirp/version.rb
58
65
  - protoc-gen-twirp_ruby/main.go
59
66
  - test/error_test.rb