rails_twirp 0.11.0 → 0.12.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
  SHA256:
3
- metadata.gz: 9dc494fd35fa5a920f6ca55c6a024f73bda616a10cc91336fefb3d7520f9c3ed
4
- data.tar.gz: 5da02487fde28997da7fb200c0a9693fc952fc5662a2e43864d0a12c788ec7d5
3
+ metadata.gz: '09e97be65f570cd7a2cecaaf0ef83d2ead287fd1fc8c556b833ae45395ee1c2b'
4
+ data.tar.gz: 1b30d280c8c724747b0b71ef7996ad23fd0a8e189818156602f284677ac9c637
5
5
  SHA512:
6
- metadata.gz: e67eba63003648f4ba6cbc604e4e2006783c5f2873e95745f56bb1f9cfea0660d1f55850b4128b088728f829ef41989c634839b6168d5a512480e465631a60e0
7
- data.tar.gz: 163e1cd73f34ed7ee62a531c71b6a5153c35231b731645ceba25e22f37e45d94f0a51fc1ff220928eb33d2297964f108cb71696779ea958cd80dc0e4410fe462
6
+ metadata.gz: 858ea0680c3efd03f2f1fdc766f6097b6e0a7b19ff39974412207139cd28a432d4c620a7a4f9243b63b9f70eff1919cb5a92d0c3dc6b5cd73ba99eb1349ac870
7
+ data.tar.gz: ba6311d0b7cb64755380eff9d1168d24458d5804f36acf21c7fceab2a8b0db305722353d8c5f493bf1692225f973342e3194f825d995df286802da6958631e3a
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ ### 0.12.0
2
+
3
+ * Allow a custom exception handling proc to be assigned using `RailsTwirp.unhandled_exception_handler`
4
+
5
+ ### 0.11.0
6
+
7
+ * Update configuration and tests for Rails 7 compatibility
8
+
9
+ ### 0.10.0
10
+
11
+ * Handle exceptions more like the Rails controllers do it, do not capture all of them as if they were Twirp exceptions
data/README.md CHANGED
@@ -1,8 +1,56 @@
1
1
  # RailsTwirp
2
- Short description and motivation.
2
+
3
+ Allows for effortless integration of [Twirp](https://github.com/twitchtv/twirp) endpoints into your Rails application. RailsTwirp permits you to define your Twirp endpoints using the familiar vocabulary of Rails routes, controllers, actions and views.
4
+
5
+ Using an extra routes file you map your Twirp RPCs to controllers, and define your views using [pbbuilder.](https://github.com/cheddar-me/pbbuilder) Even though you are now serving Twirp RPC endpoints instead of HTML or JSON, all the skills and tools you have for working your usual Rails infrastructure apply. `TwirpRails` provides a customised controller superclass called `RailsTwirp::Base` which includes all the relevant ActionController components which still make sense when using Protobufs.
3
6
 
4
7
  ## Usage
5
- How to use my plugin.
8
+
9
+ Add the gem to your project (see "Installation" below). Then add a file called `config/twirp/routes.rb` to your application, and map your RPCs inside of that file. We will map a `GreetWorld` RPC call as an example:
10
+
11
+ ```ruby
12
+ Rails.application.twirp.routes.draw do
13
+ service HelloService, module: :api do
14
+ rpc "GreetWorld", to: "greetings#greet"
15
+ end
16
+ end
17
+ ```
18
+
19
+ The `module` defines the module which will contain your `TwirpRails` controller. The `HelloService` module is your Protobuf mapping generated using Twirp, it inherits from `Twirp::Service` and could look like this:
20
+
21
+ ```ruby
22
+ class HelloService < Twirp::Service
23
+ package 'api'
24
+ service 'App'
25
+ rpc :GreetWorld, GreetWorldRequest, GreetWorldResponse, :ruby_method => :greet_world
26
+ end
27
+ ```
28
+
29
+ The `GreetWorldRequest` in this case is the autogenerated protobuf request class, the `GreetWorldResponse` is the response class.
30
+
31
+ Then you define your controller, which looks like a standard Rails controller - just with a different base class:
32
+
33
+ ```ruby
34
+ class API::GreetingsController < RailsTwirp::Base
35
+ def greet
36
+ render pb: API::GreetResponse.new
37
+ end
38
+ end
39
+ ```
40
+
41
+ Note that the controller is routed using the same naming conventions as Rails. Inside of a `TwirpRails` controller you can do most of the things you are used to from Rails controllers, such as renders and implicit renders - which have to be `pbbuilder` views. If our `GreetWorldResponse` has a `greeting` field, it can be filled inside the `pbbuilder` view like so:
42
+
43
+ ```ruby
44
+ pb.greeting "Hello stranger"
45
+ ```
46
+
47
+ Inside the controllers you have access to the call parameters of your RPC call using `request`:
48
+
49
+ ```ruby
50
+ def greet
51
+ request.name #=> # Returns the value of the "name" field from the request Protobuf
52
+ end
53
+ ```
6
54
 
7
55
  ## Installation
8
56
  Add this line to your application's Gemfile:
@@ -37,7 +85,14 @@ end
37
85
  ```
38
86
 
39
87
  ## Contributing
40
- Contribution directions go here.
88
+
89
+ * Check out the latest `main` to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
90
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
91
+ * Fork the project.
92
+ * Start a feature/bugfix branch.
93
+ * Commit and push until you are happy with your contribution.
94
+ * Make sure to add tests for your change. This is important so we don't break it in a future version unintentionally.
95
+ * Please try not to mess with the Rakefile, version, or history.
41
96
 
42
97
  ## License
43
98
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -9,17 +9,27 @@ module RailsTwirp
9
9
  def process_action(*)
10
10
  super
11
11
  rescue Exception => e
12
+ # Only the exceptions which are not captured by ActionController-like "rescue_from" end up here.
13
+ # The idea is that any exception which is rescued by the controller is treated as part of the business
14
+ # logic, and thus taking action on it is the responsibility of the controller which uses "rescue_from".
15
+ # If an exception ends up here it means it wasn't captured by the handlers defined in the controller.
16
+
12
17
  # We adopt the same error handling logic as Rails' standard middlewares:
13
18
  # 1. When we 'show exceptions' we make the exception bubble up—this is useful for testing
19
+ # If the exception gets raised here error reporting will happen in the middleware of the APM package
20
+ # higher in the call stack.
14
21
  raise e unless http_request.show_exceptions?
15
22
 
16
- # 2. When we want to show detailed exceptions we include the exception message in the error
23
+ # 2. We report the error to the error tracking service, this needs to be configured.
24
+ RailsTwirp.unhandled_exception_handler&.call(e)
25
+
26
+ # 3. When we want to show detailed exceptions we include the exception message in the error
17
27
  if http_request.get_header("action_dispatch.show_detailed_exceptions")
18
28
  self.response_body = Twirp::Error.internal_with(e)
19
29
  return
20
30
  end
21
31
 
22
- # 3. Otherwise we just return a vague internal error message
32
+ # 4. Otherwise we just return a vague internal error message
23
33
  self.response_body = Twirp::Error.internal("Internal error")
24
34
  end
25
35
  end
@@ -1,3 +1,3 @@
1
1
  module RailsTwirp
2
- VERSION = "0.11.0"
2
+ VERSION = "0.12.0"
3
3
  end
data/lib/rails_twirp.rb CHANGED
@@ -8,6 +8,7 @@ require "rails_twirp/log_subscriber"
8
8
 
9
9
  module RailsTwirp
10
10
  mattr_accessor :test_app
11
+ mattr_accessor :unhandled_exception_handler
11
12
  end
12
13
 
13
14
  require "rails_twirp/engine" if defined?(Rails)
@@ -66,6 +66,24 @@ class PingControllerTest < RailsTwirp::IntegrationTest
66
66
  Rails.application.env_config["action_dispatch.show_exceptions"] = false
67
67
  end
68
68
 
69
+ test "uncaught errors should be fanned out to the exception handler proc if one is defined" do
70
+ Rails.application.env_config["action_dispatch.show_exceptions"] = true
71
+
72
+ captured_exception = nil
73
+ RailsTwirp.unhandled_exception_handler = ->(e) { captured_exception = e }
74
+
75
+ req = RPC::DummyAPI::PingRequest.new
76
+ rpc RPC::DummyAPI::DummyService, "UncaughtError", req
77
+ assert_instance_of Twirp::Error, response
78
+ assert_equal :internal, response.code
79
+ assert_equal "Uncaught", response.msg
80
+ assert_equal "StandardError", response.meta["cause"]
81
+ assert_kind_of StandardError, captured_exception
82
+ ensure
83
+ RailsTwirp.unhandled_exception_handler = nil
84
+ Rails.application.env_config["action_dispatch.show_exceptions"] = false
85
+ end
86
+
69
87
  test "uncaught errors should return an internal error without if show_exceptions is true and show_detailed_exceptions is false" do
70
88
  Rails.application.env_config["action_dispatch.show_exceptions"] = true
71
89
  Rails.application.env_config["action_dispatch.show_detailed_exceptions"] = false
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_twirp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bouke van der Bijl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-12 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -56,6 +56,7 @@ files:
56
56
  - ".gitignore"
57
57
  - ".ruby-version"
58
58
  - ".standard.yml"
59
+ - CHANGELOG.md
59
60
  - Gemfile
60
61
  - MIT-LICENSE
61
62
  - README.md