Current File : //opt/alt/ruby31/share/gems/gems/rack-3.0.8/lib/rack/recursive.rb |
# frozen_string_literal: true
require 'uri'
require_relative 'constants'
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