# The rewrite and redirect methods are terminal methods meaning # that they return a Rack response or modify the Rack request. # # Return nil to allow the request to fall-through to the Application. module Rack class Ajax class Parser # Instantiate an ActionController::Request object to make it # easier to introspect the headers. def initialize(env) @env = env @request = ActionController::Request.new(env) end protected def hashed_url? @hashed_url ||= ::Ajax.is_hashed_url?(@env['REQUEST_URI']) end def ajax_request? @request.xml_http_request? end def get_request? @request.get? end def post_request? @request.post? end def url_is_root? @url_is_root ||= ::Ajax.url_is_root?(@env['PATH_INFO']) end # Return a boolean indicating if the request is from a robot. # # Inspect the headers first - if there are any - so we don't # look in the database unneccessarily. # # Sets the result in a header {Ajax-Info}[user_is_robot] so we # don't have to repeat this check in the application. def user_is_robot? return @user_is_robot if instance_variable_defined?(:@user_is_robot) @user_is_robot = if @request.user_agent.nil? false else ::Ajax.is_robot?(@request.user_agent) end ::Ajax.set_header(@env, :robot, @user_is_robot) @user_is_robot end def rewrite_to_traditional_url_from_fragment rewrite(::Ajax.traditional_url_from_fragment(@env['REQUEST_URI'])) end # Redirect to a hashed URL consisting of the fragment portion of the current URL. # This is an edge case. What can theoretically happen is a user visits a # bookmarked URL, then browses via AJAX and ends up with a URL like # '/Beyonce#/Akon'. Redirect them to '/#/Akon'. def redirect_to_hashed_url_from_fragment r302(::Ajax.hashed_url_from_fragment(@env['REQUEST_URI'])) end # Redirect to the hashed URL equivalent of the current traditional URL. # The user has likely followed a traditional link or bookmark. def redirect_to_hashed_url_equivalent r302(::Ajax.hashed_url_from_traditional(@env['REQUEST_URI'])) end def rewrite_to_render_ajax_framework rewrite('/ajax/framework') end private def r302(url) rack_response('Redirecting...', 302, 'Location' => url) end def rewrite(interpreted_to) @env['REQUEST_URI'] = interpreted_to if q_index = interpreted_to.index('?') @env['PATH_INFO'] = interpreted_to[0..q_index-1] @env['QUERY_STRING'] = interpreted_to[q_index+1..interpreted_to.size-1] else @env['PATH_INFO'] = interpreted_to @env['QUERY_STRING'] = '' end nil # fallthrough to app end # You can use this method during integration testing Rack::Ajax # in your Rails app. If you don't return a proper Rack response # during integration testing, ActiveSupport can't parse the # response. # # If you're testing Rack without Rails you can return base types # so you don't need this method. def self.rack_response(msg, code=200, headers={}) headers.reverse_merge!({'Content-Type' => 'text/html'}) [code, headers, [msg.to_s]] end def rack_response(*args) self.class.rack_response(*args) end end end end