action_controller-twirp 0.1.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +84 -0
- data/Rakefile +5 -0
- data/lib/action_controller/twirp/railtie.rb +19 -0
- data/lib/action_controller/twirp/twirp_error_renderer.rb +48 -0
- data/lib/action_controller/twirp/version.rb +7 -0
- data/lib/action_controller/twirp.rb +29 -0
- data/lib/action_dispatch/routing/mapper/twirp.rb +18 -0
- data/lib/action_dispatch/twirp/railtie.rb +13 -0
- data/lib/tasks/action_controller/twirp_tasks.rake +5 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f6de4da76df23f5785f040d5e30c5b7c6f9a641f70c913a6bce1861cb9d8001d
|
4
|
+
data.tar.gz: 7ac05c58f7c1bbf94a3f24625ba04e3e7e74511124a83bd2dab8a23448356dfc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 02f89f5b0c538f22d79c457bfd1e86f9948a085236165406ecc0793fc54b697284112adb6912ee274fffc04e24355e432675c3f9923f8536611d0ec1dbe66174
|
7
|
+
data.tar.gz: 432b4da795794b2decd181836e9a5752bea31db4b94bb361e7a049c2fbaac40b048eb0186885900aeb5f13e514785a8dc87ddcea6f2e3dac6fc664bf69c19997
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Kosuke Arisawa
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# ActionController::Twirp
|
2
|
+
|
3
|
+
[](https://github.com/arisawa/action_controller-twirp/actions/workflows/ruby.yml)
|
4
|
+

|
5
|
+
|
6
|
+
Implement twirp service with Rails controller.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem "action_controller-twirp"
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
```bash
|
17
|
+
$ bundle
|
18
|
+
```
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
```bash
|
22
|
+
$ gem install action_controller-twirp
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
[twirp-ruby](https://github.com/twitchtv/twirp-ruby) with Ruby on Rails.
|
27
|
+
|
28
|
+
It provides routing method `twirp` that maps twirp service class and Rails controller class, and a module of `ActionController::Twirp` to help execute RPC methods and rendering Twirp::Error.
|
29
|
+
|
30
|
+
First, you should generate twirp service class. see: [example in twirp-ruby](https://github.com/twitchtv/twirp-ruby/wiki#usage-example)
|
31
|
+
|
32
|
+
Next, add twirp action in config/routes.rb
|
33
|
+
```ruby
|
34
|
+
Rails.application.routes.draw do
|
35
|
+
scope :twirp do
|
36
|
+
twirp Example::V1::UserApiService, controller: 'users'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
Result of `bin/rails routes`
|
42
|
+
```sh
|
43
|
+
> bin/rails routes
|
44
|
+
Prefix Verb URI Pattern Controller#Action
|
45
|
+
POST /twirp/example.v1.UserApi/ListUsers(.:format) users#list_users
|
46
|
+
POST /twirp/example.v1.UserApi/GetUser(.:format) users#get_user
|
47
|
+
```
|
48
|
+
|
49
|
+
Finally, implement rpc method your controller
|
50
|
+
```ruby
|
51
|
+
class UsersController < ApplicationController # :nodoc:
|
52
|
+
include ActionController::Twirp
|
53
|
+
|
54
|
+
rescue_from ActiveRecord::RecordNotFound do |e|
|
55
|
+
twerr = Twirp::Error.not_found('The message',
|
56
|
+
reason: e.class.name.demodulize,
|
57
|
+
id: params[:id].to_s)
|
58
|
+
render twirp_error: twerr
|
59
|
+
end
|
60
|
+
|
61
|
+
USERS = [
|
62
|
+
{ id: 1, name: 'Anna' },
|
63
|
+
{ id: 2, name: 'Reina' }
|
64
|
+
].freeze
|
65
|
+
|
66
|
+
def list_users(_req, _env)
|
67
|
+
Example::V1::ListUsersResponse.new(users: USERS)
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_user(req, _env)
|
71
|
+
user = USERS.find { |u| u[:id] == req.id }
|
72
|
+
|
73
|
+
raise ActiveRecord::RecordNotFound unless user
|
74
|
+
|
75
|
+
Example::V1::User.new(user)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
## Contributing
|
81
|
+
Contribution directions go here.
|
82
|
+
|
83
|
+
## License
|
84
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_controller/twirp/twirp_error_renderer'
|
4
|
+
require 'action_dispatch/twirp/railtie'
|
5
|
+
|
6
|
+
module ActionController
|
7
|
+
module Twirp
|
8
|
+
class Railtie < ::Rails::Railtie # :nodoc:
|
9
|
+
initializer 'action_controller.twirp' do
|
10
|
+
ActiveSupport.on_load(:action_controller) do
|
11
|
+
ActionController::Renderers.add :twirp_error do |content, options|
|
12
|
+
renderer = TwirpErrorRenderer.new(content, options)
|
13
|
+
render(**renderer.to_render_option)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
module Twirp
|
5
|
+
# Convert Twirp::Error to #render option
|
6
|
+
class TwirpErrorRenderer
|
7
|
+
# @param content [Twirp::Error] given as a value of :twirp_error key of render method.
|
8
|
+
# @param options [Hash] options of render method.
|
9
|
+
def initialize(content, options)
|
10
|
+
unless content.is_a?(::Twirp::Error)
|
11
|
+
raise ArgumentError, 'Only Twirp::Error instance can be specified'
|
12
|
+
end
|
13
|
+
|
14
|
+
@content = content
|
15
|
+
@options = options.dup
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_render_option
|
19
|
+
{
|
20
|
+
json: twirp_error.to_h,
|
21
|
+
**@options.merge(status: status, content_type: content_type)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def twirp_error
|
28
|
+
return @twirp_error if defined? @twirp_error
|
29
|
+
|
30
|
+
code = @content.code
|
31
|
+
|
32
|
+
@twirp_error = if ::Twirp::Error.valid_code?(code)
|
33
|
+
@content
|
34
|
+
else
|
35
|
+
::Twirp::Error.internal("Invalid code: #{code}", invalid_code: code.to_s)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def status
|
40
|
+
::Twirp::ERROR_CODES_TO_HTTP_STATUS[twirp_error.code]
|
41
|
+
end
|
42
|
+
|
43
|
+
def content_type
|
44
|
+
::Twirp::Encoding::JSON
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_controller/twirp/version'
|
4
|
+
require 'action_controller/twirp/railtie'
|
5
|
+
|
6
|
+
module ActionController
|
7
|
+
# Module to execute your implemented methods on Twirp with Rails
|
8
|
+
module Twirp
|
9
|
+
private
|
10
|
+
|
11
|
+
# Override it to call a twirp class from request path
|
12
|
+
def send_action(*_args)
|
13
|
+
twirp_service_class.raise_exceptions = true
|
14
|
+
|
15
|
+
status, header, body = twirp_service_class.new(self)&.call(request.env)
|
16
|
+
|
17
|
+
response.status = status
|
18
|
+
response.header.merge(header)
|
19
|
+
response.body = body
|
20
|
+
end
|
21
|
+
|
22
|
+
def twirp_service_class
|
23
|
+
return @twirp_service_class if defined? @twirp_service_class
|
24
|
+
|
25
|
+
class_name = request.path.split('/')[-2].underscore.gsub('.', '/').classify
|
26
|
+
@twirp_service_class = "#{class_name}Service".constantize
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
module Routing
|
5
|
+
class Mapper
|
6
|
+
# Define mapping a generated twirp class and your controller
|
7
|
+
module Twirp
|
8
|
+
def twirp(service_class, controller:)
|
9
|
+
service_class.rpcs.each do |_, rpcdef|
|
10
|
+
path = [service_class.service_full_name, rpcdef[:rpc_method]].join('/')
|
11
|
+
action = [controller, rpcdef[:ruby_method]].join('#')
|
12
|
+
match path, to: action, via: :post
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_dispatch/routing/mapper/twirp'
|
4
|
+
|
5
|
+
module ActionDispatch
|
6
|
+
module Twirp
|
7
|
+
class Railtie < ::Rails::Railtie # :nodoc:
|
8
|
+
initializer 'action_dispatch.twirp' do
|
9
|
+
ActionDispatch::Routing::Mapper.prepend(ActionDispatch::Routing::Mapper::Twirp)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: action_controller-twirp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kosuke Arisawa
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 6.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: twirp
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.9'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.9'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.36.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.36.0
|
55
|
+
description: You can implement twirp service with Rails controller
|
56
|
+
email:
|
57
|
+
- arisawa@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- lib/action_controller/twirp.rb
|
66
|
+
- lib/action_controller/twirp/railtie.rb
|
67
|
+
- lib/action_controller/twirp/twirp_error_renderer.rb
|
68
|
+
- lib/action_controller/twirp/version.rb
|
69
|
+
- lib/action_dispatch/routing/mapper/twirp.rb
|
70
|
+
- lib/action_dispatch/twirp/railtie.rb
|
71
|
+
- lib/tasks/action_controller/twirp_tasks.rake
|
72
|
+
homepage: https://github.com/arisawa/action_controller-twirp
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata:
|
76
|
+
homepage_uri: https://github.com/arisawa/action_controller-twirp
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.2.32
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Twirp for Rails Controller
|
96
|
+
test_files: []
|