Class: Twirp::Service
- Inherits:
-
Object
- Object
- Twirp::Service
- Extended by:
- ServiceDSL
- Defined in:
- lib/twirp/service.rb
Class Attribute Summary collapse
-
.raise_exceptions ⇒ Object
Whether to raise exceptions instead of handling them with exception_raised hooks.
Class Method Summary collapse
-
.error_response(twerr) ⇒ Object
Rack response with a Twirp::Error.
Instance Method Summary collapse
-
#before(&block) ⇒ Object
Setup hook blocks.
-
#call(rack_env) ⇒ Object
Rack app handler.
-
#call_rpc(rpc_method, input = {}, env = {}) ⇒ Object
Call the handler method with input attributes or protobuf object.
- #exception_raised(&block) ⇒ Object
-
#full_name ⇒ Object
Service full_name is needed to route http requests to this service.
-
#initialize(handler) ⇒ Service
constructor
A new instance of Service.
- #name ⇒ Object
- #on_error(&block) ⇒ Object
- #on_success(&block) ⇒ Object
Methods included from ServiceDSL
package, package_name, rpc, rpcs, service, service_full_name, service_name
Constructor Details
#initialize(handler) ⇒ Service
Returns a new instance of Service.
42 43 44 45 46 47 48 49 |
# File 'lib/twirp/service.rb', line 42 def initialize(handler) @handler = handler @before = [] @on_success = [] @on_error = [] @exception_raised = [] end |
Class Attribute Details
.raise_exceptions ⇒ Object
Whether to raise exceptions instead of handling them with exception_raised hooks. Useful during tests to easily debug and catch unexpected exceptions.
30 31 32 |
# File 'lib/twirp/service.rb', line 30 def raise_exceptions @raise_exceptions end |
Class Method Details
.error_response(twerr) ⇒ Object
Rack response with a Twirp::Error
33 34 35 36 37 38 |
# File 'lib/twirp/service.rb', line 33 def error_response(twerr) status = Twirp::ERROR_CODES_TO_HTTP_STATUS[twerr.code] headers = {Rack::CONTENT_TYPE => Encoding::JSON} # Twirp errors are always JSON, even if the request was protobuf resp_body = Encoding.encode_json(twerr.to_h) [status, headers, [resp_body]] end |
Instance Method Details
#before(&block) ⇒ Object
Setup hook blocks.
52 |
# File 'lib/twirp/service.rb', line 52 def before(&block) @before << block; end |
#call(rack_env) ⇒ Object
Rack app handler.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/twirp/service.rb', line 62 def call(rack_env) begin env = {} bad_route = route_request(rack_env, env) return error_response(bad_route, env) if bad_route @before.each do |hook| result = hook.call(rack_env, env) return error_response(result, env) if result.is_a? Twirp::Error end output = call_handler(env) return error_response(output, env) if output.is_a? Twirp::Error return success_response(output, env) rescue => e raise e if self.class.raise_exceptions begin @exception_raised.each{|hook| hook.call(e, env) } rescue => hook_e e = hook_e end twerr = Twirp::Error.internal_with(e) return error_response(twerr, env) end end |
#call_rpc(rpc_method, input = {}, env = {}) ⇒ Object
Call the handler method with input attributes or protobuf object. Returns a proto object (response) or a Twirp::Error. Hooks are not called and exceptions are raised instead of being wrapped. This is useful for unit testing the handler. The env should include fake data that is used by the handler, replicating middleware and before hooks.
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/twirp/service.rb', line 95 def call_rpc(rpc_method, input={}, env={}) base_env = self.class.rpcs[rpc_method.to_s] return Twirp::Error.bad_route("Invalid rpc method #{rpc_method.to_s.inspect}") unless base_env env = env.merge(base_env) input = env[:input_class].new(input) if input.is_a? Hash env[:input] = input env[:content_type] ||= Encoding::PROTO env[:http_response_headers] = defined?(Rack::Headers) ? Rack::Headers.new : {} call_handler(env) end |
#exception_raised(&block) ⇒ Object
55 |
# File 'lib/twirp/service.rb', line 55 def exception_raised(&block) @exception_raised << block; end |
#full_name ⇒ Object
Service full_name is needed to route http requests to this service.
58 |
# File 'lib/twirp/service.rb', line 58 def full_name; @full_name ||= self.class.service_full_name; end |
#name ⇒ Object
59 |
# File 'lib/twirp/service.rb', line 59 def name; @name ||= self.class.service_name; end |
#on_error(&block) ⇒ Object
54 |
# File 'lib/twirp/service.rb', line 54 def on_error(&block) @on_error << block; end |
#on_success(&block) ⇒ Object
53 |
# File 'lib/twirp/service.rb', line 53 def on_success(&block) @on_success << block; end |