rails_twirp 0.5.0 → 0.6.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
  SHA256:
3
- metadata.gz: 8df8457b09993d7d5c986130e724948df049c201b6797f33a7b66458bde98918
4
- data.tar.gz: 0a2100cbefd37754f9dbd6cf666def1c29d0936322f72837d7e60653b5510b79
3
+ metadata.gz: 34fc8b4e84ba8c456ac2fa01c3c35dd0fd11224360d6e21b832b5d17ed1f57a5
4
+ data.tar.gz: 9626b771c35bfdd034fa1dccad6ef5ed921aad0abdf3086bfe27a6b3b26f50b9
5
5
  SHA512:
6
- metadata.gz: 1b50c23cd6fa8852686ca96066c0a65a532f06ec0225b5ed04ac860218760d187e868d0b3d499855527ed23d355dacf8bf33eb1aaf2fd1b590b29aa12c8e836a
7
- data.tar.gz: 461fe47bbafdd0bcf304f48b4938f307fd380d7bbce7049a703c60f7bc781b0f58b1cf06b7410c4a168e39441b1a9bd49b5091a0dbfc3472870c002bef6f51e1
6
+ metadata.gz: e4621381feff50a031faf89079aa49054d246bd52f0e9d0fe4fe588f3014c2dd9a779f249aa16ac15340d9e259b61e273b393dd6a69ecaa15b5bf76c29578434
7
+ data.tar.gz: e91d714d2ef9c5e6a45e34911a29de4c1927d2e8442c5bf3538c5c43f137c10010b0282d9a5f2d4c5901d9c1733191cd0e7ff4e2764d8ae546233798ef81d64b
data/lib/rails_twirp.rb CHANGED
@@ -4,6 +4,7 @@ require "rails_twirp/application"
4
4
  require "rails_twirp/base"
5
5
  require "rails_twirp/route_set"
6
6
  require "rails_twirp/testing/integration_test"
7
+ require "rails_twirp/log_subscriber"
7
8
 
8
9
  module RailsTwirp
9
10
  mattr_accessor :test_app
@@ -10,6 +10,8 @@ require "abstract_controller/callbacks"
10
10
  require "action_controller/metal/helpers"
11
11
  require "rails_twirp/rescue"
12
12
  require "rails_twirp/url_for"
13
+ require "rails_twirp/implicit_render"
14
+ require "rails_twirp/instrumentation"
13
15
 
14
16
  module RailsTwirp
15
17
  class Base < AbstractController::Base
@@ -24,15 +26,16 @@ module RailsTwirp
24
26
  include UrlFor
25
27
  include AbstractController::AssetPaths
26
28
  include AbstractController::Caching
27
- include AbstractController::Logger
28
29
 
29
30
  include ActionView::Rendering
30
31
  include RenderPb
31
32
  include Errors
33
+ include ImplicitRender
32
34
 
33
35
  # These need to be last so errors can be handled as early as possible.
34
36
  include AbstractController::Callbacks
35
37
  include Rescue
38
+ include Instrumentation
36
39
 
37
40
  attr_internal :request, :env, :response_class
38
41
  def initialize
@@ -55,8 +58,6 @@ module RailsTwirp
55
58
 
56
59
  process(action)
57
60
 
58
- # Implicit render
59
- self.response_body = render unless response_body
60
61
  response_body
61
62
  end
62
63
 
@@ -0,0 +1,11 @@
1
+ require "action_controller/metal/basic_implicit_render"
2
+
3
+ module RailsTwirp
4
+ module ImplicitRender
5
+ include ActionController::BasicImplicitRender
6
+
7
+ def default_render
8
+ render
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ module RailsTwirp
2
+ module Instrumentation
3
+ extend ActiveSupport::Concern
4
+
5
+ include AbstractController::Logger
6
+
7
+ def process_action(*)
8
+ raw_payload = {
9
+ controller: self.class.name,
10
+ action: action_name,
11
+ request: request,
12
+ http_request: http_request,
13
+ headers: http_request.headers,
14
+ path: http_request.fullpath
15
+ }
16
+
17
+ ActiveSupport::Notifications.instrument("start_processing.rails_twirp", raw_payload)
18
+
19
+ ActiveSupport::Notifications.instrument("process_action.rails_twirp", raw_payload) do |payload|
20
+ result = super
21
+ if response_body.is_a?(Twirp::Error)
22
+ payload[:code] = response_body.code
23
+ payload[:msg] = response_body.msg
24
+ else
25
+ payload[:code] = :success
26
+ end
27
+ payload[:response] = response_body
28
+ result
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,64 @@
1
+ require "active_support/log_subscriber"
2
+
3
+ module RailsTwirp
4
+ class LogSubscriber < ActiveSupport::LogSubscriber
5
+ def start_processing(event)
6
+ return unless logger.info?
7
+
8
+ payload = event.payload
9
+
10
+ info "Processing by #{payload[:controller]}##{payload[:action]}"
11
+ end
12
+
13
+ def process_action(event)
14
+ payload = event.payload
15
+ exception_raised(payload[:http_request], payload[:exception_object]) if payload[:exception_object]
16
+
17
+ info do
18
+ code = payload.fetch(:code, :internal)
19
+
20
+ message = +"Completed #{code} in #{event.duration.round}ms (Allocations: #{event.allocations})"
21
+ message << "\n\n" if defined?(Rails.env) && Rails.env.development?
22
+
23
+ message
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def exception_raised(request, exception)
30
+ backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
31
+ wrapper = ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception)
32
+
33
+ log_error(wrapper)
34
+ end
35
+
36
+ def log_error(wrapper)
37
+ exception = wrapper.exception
38
+ trace = wrapper.exception_trace
39
+
40
+ message = []
41
+ message << " "
42
+ message << "#{exception.class} (#{exception.message}):"
43
+ message.concat(exception.annotated_source_code) if exception.respond_to?(:annotated_source_code)
44
+ message << " "
45
+ message.concat(trace)
46
+
47
+ log_array(message)
48
+ end
49
+
50
+ def log_array(array)
51
+ lines = Array(array)
52
+
53
+ return if lines.empty?
54
+
55
+ if logger.formatter&.respond_to?(:tags_text)
56
+ fatal { lines.join("\n#{logger.formatter.tags_text}") }
57
+ else
58
+ fatal { lines.join("\n") }
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ RailsTwirp::LogSubscriber.attach_to :rails_twirp
@@ -1,11 +1,17 @@
1
+ require "twirp/encoding"
2
+
1
3
  module RailsTwirp
2
4
  class IntegrationTest < ActiveSupport::TestCase
5
+ Response = Struct.new(:status, :body, :headers)
6
+
3
7
  attr_reader :response, :request, :controller
8
+ attr_writer :mount_path
4
9
 
5
10
  def initialize(name)
6
11
  super
7
12
  reset!
8
13
  @before_rpc = []
14
+ @mount_path = "/twirp"
9
15
  end
10
16
 
11
17
  def reset!
@@ -19,32 +25,59 @@ module RailsTwirp
19
25
 
20
26
  def rpc(service, rpc, request, headers: nil)
21
27
  @request = request
22
- service = app.twirp.routes.services[service].to_service
23
-
24
- rack_env = {
25
- "HTTP_HOST" => "localhost"
26
- }
27
- http_request = ActionDispatch::Request.new(rack_env)
28
- http_request.headers.merge! headers if headers.present?
29
- env = {rack_env: rack_env}
30
28
 
29
+ env = build_rack_env(service, rpc, request, headers)
31
30
  @before_rpc.each do |hook|
32
31
  hook.call(env)
33
32
  end
34
33
 
35
- response = begin
36
- service.call_rpc rpc, request, env
37
- rescue => e
38
- Twirp::Error.internal_with(e)
39
- end
34
+ status, headers, body = app.call(env)
35
+ @response = decode_rack_response(service, rpc, status, headers, body)
36
+ set_controller_from_rack_env(env)
40
37
 
41
- @response = response
42
- @controller = http_request.controller_instance
43
- response
38
+ @response
44
39
  end
45
40
 
46
41
  def app
47
42
  RailsTwirp.test_app
48
43
  end
44
+
45
+ private
46
+
47
+ def build_rack_env(service, rpc, request, headers)
48
+ env = {
49
+ "CONTENT_TYPE" => request_content_type,
50
+ "HTTP_HOST" => "localhost",
51
+ "PATH_INFO" => "#{@mount_path}/#{service.service_full_name}/#{rpc}",
52
+ "REQUEST_METHOD" => "POST"
53
+ }
54
+ if headers.present?
55
+ http_request = ActionDispatch::Request.new(env)
56
+ http_request.headers.merge! headers
57
+ end
58
+
59
+ input_class = service.rpcs[rpc][:input_class]
60
+ env["rack.input"] = StringIO.new(Twirp::Encoding.encode(request, input_class, request_content_type))
61
+ env
62
+ end
63
+
64
+ def request_content_type
65
+ Twirp::Encoding::PROTO
66
+ end
67
+
68
+ def decode_rack_response(service, rpc, status, headers, body)
69
+ body = body.join # body is an Enumerable
70
+
71
+ if status === 200
72
+ output_class = service.rpcs[rpc][:output_class]
73
+ Twirp::Encoding.decode(body, output_class, headers["Content-Type"])
74
+ else
75
+ Twirp::Client.error_from_response(Response.new(status, body, headers))
76
+ end
77
+ end
78
+
79
+ def set_controller_from_rack_env(env)
80
+ @controller = ActionDispatch::Request.new(env).controller_class
81
+ end
49
82
  end
50
83
  end
@@ -1,3 +1,3 @@
1
1
  module RailsTwirp
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
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.5.0
4
+ version: 0.6.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: 2021-04-20 00:00:00.000000000 Z
11
+ date: 2021-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -59,6 +59,9 @@ files:
59
59
  - lib/rails_twirp/base.rb
60
60
  - lib/rails_twirp/engine.rb
61
61
  - lib/rails_twirp/errors.rb
62
+ - lib/rails_twirp/implicit_render.rb
63
+ - lib/rails_twirp/instrumentation.rb
64
+ - lib/rails_twirp/log_subscriber.rb
62
65
  - lib/rails_twirp/mapper.rb
63
66
  - lib/rails_twirp/render_pb.rb
64
67
  - lib/rails_twirp/rescue.rb