fix: malformed charset param (#2263)
[rack.git] / lib / rack / recursive.rb
blob0945d3227814b952ddf4993590569c84f04ef8c6
1 # frozen_string_literal: true
3 require 'uri'
5 require_relative 'constants'
7 module Rack
8   # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
9   # the current request to the app at +url+.
10   #
11   #   raise ForwardRequest.new("/not-found")
12   #
14   class ForwardRequest < Exception
15     attr_reader :url, :env
17     def initialize(url, env = {})
18       @url = URI(url)
19       @env = env
21       @env[PATH_INFO]       = @url.path
22       @env[QUERY_STRING]    = @url.query  if @url.query
23       @env[HTTP_HOST]       = @url.host   if @url.host
24       @env[HTTP_PORT]       = @url.port   if @url.port
25       @env[RACK_URL_SCHEME] = @url.scheme if @url.scheme
27       super "forwarding to #{url}"
28     end
29   end
31   # Rack::Recursive allows applications called down the chain to
32   # include data from other applications (by using
33   # <tt>rack['rack.recursive.include'][...]</tt> or raise a
34   # ForwardRequest to redirect internally.
36   class Recursive
37     def initialize(app)
38       @app = app
39     end
41     def call(env)
42       dup._call(env)
43     end
45     def _call(env)
46       @script_name = env[SCRIPT_NAME]
47       @app.call(env.merge(RACK_RECURSIVE_INCLUDE => method(:include)))
48     rescue ForwardRequest => req
49       call(env.merge(req.env))
50     end
52     def include(env, path)
53       unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ ||
54                                                path[@script_name.size].nil?)
55         raise ArgumentError, "can only include below #{@script_name}, not #{path}"
56       end
58       env = env.merge(PATH_INFO => path,
59                       SCRIPT_NAME => @script_name,
60                       REQUEST_METHOD => GET,
61                       "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
62                       RACK_INPUT => StringIO.new(""))
63       @app.call(env)
64     end
65   end
66 end