aparams are used when inside of something that has been scheduled asynchronously in an asynchronous route. Essentially it is the last parameters to be set by the router (for example, containing the route captures).
Asynchronous halt must be used when the halt is occuring outside of the original call stack.
# File lib/sinatra/async.rb, line 188 def ahalt(*args) invoke { halt(*args) } invoke { error_block! response.status } unless @env['sinatra.error'] end
# File lib/sinatra/async.rb, line 160 def async_catch_execute(&b) @async_running = true async_handle_exception do if h = catch(:halt, &b) invoke { halt h } invoke { error_block! response.status } body(response.body) end end end
# File lib/sinatra/async.rb, line 171 def async_handle_exception yield rescue ::Exception => boom if settings.show_exceptions? printer = Sinatra::ShowExceptions.new(proc{ raise boom }) s, h, b = printer.call(request.env) response.status = s response.headers.replace(h) response.body = b body(response.body) else body(handle_exception!(boom)) end end
Defaults to throw async as that is most commonly used by servers.
# File lib/sinatra/async.rb, line 143 def async_response throw :async end
# File lib/sinatra/async.rb, line 147 def async_runner(meth, *bargs) @aparams = @params.dup async_schedule do begin original, @params = @params, @aparams method(meth).arity == 0 ? send(meth) : send(meth, *bargs) ensure @params = original end nil end end
#async_schedule is used to schedule work in a future context, the block is wrapped up so that exceptions and halts (redirect, etc) are handled correctly.
# File lib/sinatra/async.rb, line 126 def async_schedule(&b) if settings.environment == :test settings.set :async_schedules, [] unless settings.respond_to? :async_schedules settings.async_schedules << lambda { async_catch_execute(&b) } else native_async_schedule { async_catch_execute(&b) } end end
Send the given body or block as the final response to the asynchronous request.
# File lib/sinatra/async.rb, line 89 def body(value = nil) if @async_running if block_given? super { async_handle_exception { yield } } else super end if response.body.respond_to?(:call) response.body = Array(async_handle_exception {response.body.call}) end # Taken from Base#call unless @response['Content-Type'] if Array === response.body and response.body[0].respond_to? :content_type content_type response.body[0].content_type else content_type :html end end result = response.finish # We don't get the HEAD middleware, so just do something convenient # here. result[-1] = [] if request.head? request.env['async.callback'][ result ] response.body else super end end
By default #native_async_schedule calls EventMachine#next_tick, if you're using threads or some other scheduling mechanism, it must take the block passed here and schedule it for running in the future.
# File lib/sinatra/async.rb, line 138 def native_async_schedule(&b) EM.next_tick(&b) end
The given block will be executed if the user closes the connection prematurely (before we've sent a response). This is good for deregistering callbacks that would otherwise send the body (for example channel subscriptions).
# File lib/sinatra/async.rb, line 197 def on_close(&blk) env['async.close'].callback(&blk) end