Module: Goliath::Rack::AsyncMiddleware
- Includes:
- Validator
- Included in:
- DefaultResponseFormat, Formatters::HTML, Formatters::JSON, Formatters::PLIST, Formatters::XML, Formatters::YAML, JSONP, Render, Tracer
- Defined in:
- lib/goliath/rack/async_middleware.rb
Overview
Some caveats on writing middleware. Unlike other Rack powered app servers, Goliath creates a single instance of the middleware chain at startup, and reuses it for all incoming requests. Since everything is asynchronous, you can have multiple requests using the middleware chain at the same time. If your middleware tries to store any instance or class level variables they’ll end up getting stomped all over by the next request. Everything that you need to store needs to be stored in local variables.
Include this to enable middleware that can perform post-processing.
For internal reasons, you can’t do the following as you would in Rack:
def call(env)
# ... do pre-processing
status, headers, body = @app.call(env)
new_body = make_totally_awesome(body) ## !! BROKEN !!
[status, headers, new_body]
end
By including this middleware, you can do that kind of “around” middleware: it lets goliath proceed asynchronously, but still “unwind” the request by walking up the callback chain.
Instance Method Summary collapse
-
#call(env, *args) ⇒ Array
Store the previous async.callback into async_cb and redefines it to be our own.
- #final_response?(resp) ⇒ Boolean
-
#hook_into_callback_chain(env, *args) ⇒ Object
Put a callback block in the middle of the async_callback chain: * save the old callback chain; * have the downstream callback send results to our proc…
-
#initialize(app) ⇒ Goliath::Rack::AsyncMiddleware
Called by the framework to create the middleware.
-
#post_process(env, status, headers, body) ⇒ Object
Override this method in your middleware to perform any postprocessing.
Methods included from Validator
Instance Method Details
#call(env, *args) ⇒ Array
Store the previous async.callback into async_cb and redefines it to be our own. When the asynchronous response is done, Goliath can “unwind” the request by walking up the callback chain.
However, you will notice that we execute the post_process method in the default return case. If the validations fail later in the middleware chain before your classes response(env) method is executed, the response will come back up through the chain normally and be returned.
To do preprocessing, override this method in your subclass and invoke super(env) as the last line. Any extra arguments will be made available to the post_process method.
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/goliath/rack/async_middleware.rb', line 69 def call(env, *args) hook_into_callback_chain(env, *args) downstream_resp = @app.call(env) if final_response?(downstream_resp) status, headers, body = downstream_resp post_process(env, status, headers, body, *args) else return Goliath::Connection::AsyncResponse end end |
#final_response?(resp) ⇒ Boolean
100 101 102 |
# File 'lib/goliath/rack/async_middleware.rb', line 100 def final_response?(resp) resp != Goliath::Connection::AsyncResponse end |
#hook_into_callback_chain(env, *args) ⇒ Object
Put a callback block in the middle of the async_callback chain:
-
save the old callback chain;
-
have the downstream callback send results to our proc…
-
which fires old callback chain when it completes
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/goliath/rack/async_middleware.rb', line 87 def hook_into_callback_chain(env, *args) async_callback = env['async.callback'] # The response from the downstream app is sent to post_process # and then directly up the callback chain downstream_callback = Proc.new do |status, headers, body| new_resp = safely(env){ post_process(env, status, headers, body, *args) } async_callback.call(new_resp) end env['async.callback'] = downstream_callback end |
#initialize(app) ⇒ Goliath::Rack::AsyncMiddleware
Called by the framework to create the middleware.
50 51 52 |
# File 'lib/goliath/rack/async_middleware.rb', line 50 def initialize(app) @app = app end |
#post_process(env, status, headers, body) ⇒ Object
Override this method in your middleware to perform any postprocessing. Note that this can be called in the asynchronous case (walking back up the middleware async.callback chain), or synchronously (in the case of a validation error, or if a downstream middleware supplied a direct response).
109 110 111 |
# File 'lib/goliath/rack/async_middleware.rb', line 109 def post_process(env, status, headers, body) [status, headers, body] end |