Class: Rack::CGI
- Inherits:
-
Object
- Object
- Rack::CGI
- Defined in:
- lib/rack/cgi.rb
Defined Under Namespace
Classes: Executable
Instance Method Summary collapse
- #call(env) ⇒ Object
- #cgi_env(env, path) ⇒ Object
-
#initialize(app, args = {}) ⇒ CGI
constructor
A new instance of CGI.
- #match_cgi_rule(path) ⇒ Object
- #parse_output(output) ⇒ Object
- #report_error(code, out, err, cgi_env) ⇒ Object
- #run(env, rule, path) ⇒ Object
- #run_cgi(rule, path, env) ⇒ Object
- #solve_path(path) ⇒ Object
- #split_header_content(output) ⇒ Object
Constructor Details
#initialize(app, args = {}) ⇒ CGI
Returns a new instance of CGI.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/rack/cgi.rb', line 11 def initialize app, args = {} @app = app @opts = args.select {|k, _| k.is_a? Symbol} @rules = args.select {|k, _| !k.is_a? Symbol} @root = @opts[:cgi_path] if @root !~ /^\// @root = ::File.join(Dir.pwd, @root) end @index = @opts[:index] || [] @index = [@index] if not @index.is_a? Array @dir_redirect = @opts[:dir_redirect] end |
Instance Method Details
#call(env) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/rack/cgi.rb', line 152 def call(env) catch :rack_cgi_result do path = solve_path env["PATH_INFO"] if not path return @app.call(env) end rule = match_cgi_rule path if not rule return @app.call(env) end cgi_env = cgi_env(env, path) code, out, err = run_cgi rule, path, cgi_env if code == 0 parse_output out else report_error code, out, err, cgi_env end end end |
#cgi_env(env, path) ⇒ Object
46 47 48 49 50 51 52 |
# File 'lib/rack/cgi.rb', line 46 def cgi_env env, path env = env.select {|k, _| k =~ /^[A-Z]/} env['SCRIPT_FILENAME'] = path env['DOCUMENT_ROOT'] = @root env['REDIRECT_STATUS'] = "200" env end |
#match_cgi_rule(path) ⇒ Object
54 55 56 57 58 59 60 61 |
# File 'lib/rack/cgi.rb', line 54 def match_cgi_rule path @rules.each do |m, r| if m =~ path return r end end return nil end |
#parse_output(output) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/rack/cgi.rb', line 109 def parse_output output header, content = split_header_content output h = {} header.each_line do |l| k, v = l.split ':', 2 k.strip! v.strip! h[k.downcase] = [k, v] end if h['status'] status = h['status'][1].to_i h.delete 'status' else status = 200 end header_hash = Hash[h.values] [status, header_hash, [content]] end |
#report_error(code, out, err, cgi_env) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/rack/cgi.rb', line 132 def report_error code, out, err, cgi_env h = {'Content-Type' => 'text/plain'} status = 500 reports = [] reports << "CGI Error!\n\n" reports << "stdout output:\n" reports << out reports << "\n" reports << "stderr output:\n" reports << err reports << "\n" reports << "environments:\n" cgi_env.each do |k, v| reports << "#{k} => #{v}\n" end [status, h, reports] end |
#run(env, rule, path) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/rack/cgi.rb', line 173 def run(env, rule, path) catch :rack_cgi_result do cgi_env = cgi_env(env, path) code, out, err = run_cgi rule, path, cgi_env if code == 0 parse_output out else report_error code, out, err, cgi_env end end end |
#run_cgi(rule, path, env) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/rack/cgi.rb', line 63 def run_cgi rule, path, env if rule.empty? args = [path] else args = [rule, path] end process = ChildProcess.build(*args) process.io.stdout = Tempfile.new('rack-cgi-stdout') process.io.stderr = Tempfile.new('rack-cgi-stderr') env.each do |k, v| process.environment[k] = v end process.cwd = Dir.pwd process.start process.wait cont_out = ::File.read(process.io.stdout.path) cont_err = ::File.read(process.io.stderr.path) process.io.stdout.unlink process.io.stderr.unlink [process.exit_code, cont_out, cont_err] end |
#solve_path(path) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/rack/cgi.rb', line 27 def solve_path path path = ::File.join(@root, path) if ::File.directory? path @index.each do |f| path2 = ::File.join(path, f) if ::File.file? path2 if @dir_redirect and path !~ %r{/$} throw :rack_cgi_result, [302, {'Location' => path + '/'}, [""]] else return path2 end end end else return path if ::File.file? path end nil end |
#split_header_content(output) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rack/cgi.rb', line 88 def split_header_content output lines = output.lines.to_a header = [] until lines.empty? l = lines.shift if l == "\n" or l == "\r\n" # find break line between header and content return header.join, lines.join elsif l =~ /:/ header << l else # content break header ruler, so deal as no header return "", output end end # deal all content as header return output, "" end |