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_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.
12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/rack-cgi.rb', line 12 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? Hash end |
Instance Method Details
#call(env) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/rack-cgi.rb', line 145 def call(env) 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 |
#cgi_env(env, path) ⇒ Object
39 40 41 42 43 44 45 |
# File 'lib/rack-cgi.rb', line 39 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
47 48 49 50 51 52 53 54 |
# File 'lib/rack-cgi.rb', line 47 def match_cgi_rule path @rules.each do |m, r| if m =~ path return r end end return nil end |
#parse_output(output) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/rack-cgi.rb', line 102 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
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/rack-cgi.rb', line 125 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_cgi(rule, path, env) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/rack-cgi.rb', line 56 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
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/rack-cgi.rb', line 26 def solve_path path path = ::File.join(@root, path) if ::File.directory? path @index.each do |f| path2 = ::File.join(path, f) return path2 if ::File.file? path2 end else return path if ::File.file? path end nil end |
#split_header_content(output) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/rack-cgi.rb', line 81 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 |