1 # frozen_string_literal: true
5 require_relative 'constants'
8 # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
9 # the current request to the app at +url+.
11 # raise ForwardRequest.new("/not-found")
14 class ForwardRequest < Exception
15 attr_reader :url, :env
17 def initialize(url, 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}"
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.
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))
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}"
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(""))