bf8b9659255917a430a1dccef74f4a0e85d64a23
[feedcatcher.git] / vendor / rails / actionpack / lib / action_controller / vendor / rack-1.0 / rack / recursive.rb
1 require 'uri'
2
3 module Rack
4 # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
5 # the current request to the app at +url+.
6 #
7 # raise ForwardRequest.new("/not-found")
8 #
9
10 class ForwardRequest < Exception
11 attr_reader :url, :env
12
13 def initialize(url, env={})
14 @url = URI(url)
15 @env = env
16
17 @env["PATH_INFO"] = @url.path
18 @env["QUERY_STRING"] = @url.query if @url.query
19 @env["HTTP_HOST"] = @url.host if @url.host
20 @env["HTTP_PORT"] = @url.port if @url.port
21 @env["rack.url_scheme"] = @url.scheme if @url.scheme
22
23 super "forwarding to #{url}"
24 end
25 end
26
27 # Rack::Recursive allows applications called down the chain to
28 # include data from other applications (by using
29 # <tt>rack['rack.recursive.include'][...]</tt> or raise a
30 # ForwardRequest to redirect internally.
31
32 class Recursive
33 def initialize(app)
34 @app = app
35 end
36
37 def call(env)
38 @script_name = env["SCRIPT_NAME"]
39 @app.call(env.merge('rack.recursive.include' => method(:include)))
40 rescue ForwardRequest => req
41 call(env.merge(req.env))
42 end
43
44 def include(env, path)
45 unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ ||
46 path[@script_name.size].nil?)
47 raise ArgumentError, "can only include below #{@script_name}, not #{path}"
48 end
49
50 env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name,
51 "REQUEST_METHOD" => "GET",
52 "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
53 "rack.input" => StringIO.new(""))
54 @app.call(env)
55 end
56 end
57 end