-
Notifications
You must be signed in to change notification settings - Fork 61
Service Hooks
Mario Izquierdo edited this page Apr 16, 2019
·
3 revisions
Hooks allow injecting useful code during the lifecycle of a Twirp server request.
routing -> before -> handler -> on_success
-> on_error
One and only one of on_success or on_error is called per request. If exceptions are raised, the exception_raised hook is called before calling on_error.
routing -> before -> handler
! exception_raised -> on_error
-
before: (block
|rack_env, env|) Runs after the request is routed to an rpc method, but before calling the method handler. This is the only place to read therack_envto access http request and middleware data, and can add more values to the Twirpenv, for example authentication data likeenv[:user_id]. The Twirpenvalready has some routing info likeenv[:rpc_method],env[:input]and env[:input_class]. Returning aTwirp::Errorfrom the before hook immediately cancels the request. -
on_success: (block
|env|) Runs after the rpc method is handled, unless it returned aTwirp:Erroror raised an exception. Theenv[:output]contains the serialized message of classenv[:ouput_class]. -
on_error: (block
|twerr, env|) Runs on error responses, that isbad_routeerrors during routing, Twirp errors returned from before hooks or method handlers, or after an exception was raised. Raised exceptions are wrapped withTwirp::Error.internal_with(e), that has codeinternaland the original exception is stored intwerr.cause. -
exception_raised: (block
|e, env|) Runs if an exception was raised from the handler or any of the other hooks.
svc = Example::HelloWorldService.new(handler)
svc.before do |rack_env, env|
env[:user_id] = authenticate(rack_env)
env[:enviornment] = (ENV['ENVIRONMENT'] || :local).to_sym
end
svc.on_success do |env|
Stats.inc("requests.success")
end
svc.on_error do |twerr, env|
Stats.inc("requests.error.#{twerr.code}")
end
svc.exception_raised do |e, env|
if env[:environment] == :local
puts "[Exception] #{e}"
puts e.backtrace.join("\n")
else
ExceptionTracker.send(e)
end
endIf for some reason you need to run code before the Twirp service routes the request, then you should use standard Rack Middleware.
For example:
class MyMiddleware
def initialize(app)
@app = app
end
def call(rack_env)
# do some stuff and decide to return an early Twirp error
if not_cool(env)
twerr = Twirp::Error.invalid_argument("not cool", foo: "bar-meta")
return Twirp::Service.error_response(twerr)
end
rack_env["mystaff"] = "foobar" # this is available in before hooks
@app.call(rack_env)
end
endA Twirp::Service is also Rack Middleware, and the before hook has access to the rack_env. If your middleware adds data into the rack_env, that will be available in the before hook. The before hook could also add it to the Twirp env, so that data is also available in method handlers.