Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save deepak/411049 to your computer and use it in GitHub Desktop.
Save deepak/411049 to your computer and use it in GitHub Desktop.
# Oleg Andreev <[email protected]> Oct 16, 2009
#
# This demonstrates how to perform a request to the same Rails instance without hitting HTTP server.
# Note 1: this does not boot another Rails instance
# Note 2: this does not involve HTTP parsing
# Note 3: dispatch_unlocked and rack.multithread=true are used to prevent deadlock on a dispatch mutex,
# NOT to make inner requests operate concurrently as one may think.
# Note 4: inner request is created by merging outer request with some HTTP headers and rack options.
# This may probably lead to strange effects, so be aware of it.
# Perhaps, we shouldn't use outer request at all. I don't know.
class LocalDispatcher < ActionController::Dispatcher
def get(path, request)
env = request.env.merge({
"REQUEST_METHOD" => "GET",
"SCRIPT_NAME" => "/",
"PATH_INFO" => path,
"REQUEST_PATH" => path,
"REQUEST_URI" => path,
"rack.version" => [1,0],
"rack.url_scheme" => (request.ssl? ? "https" : "http"),
"rack.input" => StringIO.new(''),
"rack.errors" => $stderr,
"rack.multithread" => true, # we probably need this to avoid deadlocks
"rack.multiprocess" => true,
"rack.run_once" => false
# Rack environment spec:
# http://rack.rubyforge.org/doc/SPEC.html
})
@request = ActionController::RackRequest.new(env)
@response = ActionController::RackResponse.new(@request)
begin
status, headers, body = dispatch_unlocked
rescue Exception => e
Rails.logger.error("OfflineDispatcher got an exception #{e}")
raise e
end
# TODO: more error checks before returning body
out = ""
body.each do |chunk|
out << chunk
end
out
end
# override dispatch_unlocked to avoid class reloading
def dispatch_unlocked
begin
handle_request
rescue Exception => exception
failsafe_rescue exception
end
end
end
class OfflineArchivesController < ApplicationController
def show
page = get_path("/page/123")
render :text => page
end
private
def get_path(path)
LocalDispatcher.new.get(path, request)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment