-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathrecursive.rb
66 lines (53 loc) · 1.78 KB
/
recursive.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 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