-
-
Save deepak/411049 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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