12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- require 'uri'
- module Rack
- # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
- # the current request to the app at +url+.
- #
- # raise ForwardRequest.new("/not-found")
- #
- class ForwardRequest < Exception
- attr_reader :url, :env
- def initialize(url, env={})
- @url = URI(url)
- @env = env
- @env["PATH_INFO"] = @url.path
- @env["QUERY_STRING"] = @url.query if @url.query
- @env["HTTP_HOST"] = @url.host if @url.host
- @env["HTTP_PORT"] = @url.port if @url.port
- @env["rack.url_scheme"] = @url.scheme if @url.scheme
- super "forwarding to #{url}"
- end
- end
- # Rack::Recursive allows applications called down the chain to
- # include data from other applications (by using
- # <tt>rack['rack.recursive.include'][...]</tt> or raise a
- # ForwardRequest to redirect internally.
- class Recursive
- def initialize(app)
- @app = app
- end
- def call(env)
- dup._call(env)
- end
- def _call(env)
- @script_name = env["SCRIPT_NAME"]
- @app.call(env.merge('rack.recursive.include' => method(:include)))
- rescue ForwardRequest => req
- call(env.merge(req.env))
- end
- def include(env, path)
- unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ ||
- path[@script_name.size].nil?)
- raise ArgumentError, "can only include below #{@script_name}, not #{path}"
- end
- env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name,
- "REQUEST_METHOD" => "GET",
- "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
- "rack.input" => StringIO.new(""))
- @app.call(env)
- end
- end
- end
|