lib/rack-cgi.rb in rack-cgi-0.2.3 vs lib/rack-cgi.rb in rack-cgi-0.3.0
- old
+ new
@@ -1,165 +2 @@
-require 'childprocess'
-
-module Rack
- class CGI
- class Executable
- def self.=~ rhs
- ::File.executable? rhs
- end
- end
-
- 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
-
- 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
-
- 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
-
- def match_cgi_rule path
- @rules.each do |m, r|
- if m =~ path
- return r
- end
- end
- return nil
- end
-
- 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
-
- 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
-
- 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
-
- 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
-
- 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
- end
-end
-
+require_relative 'rack/cgi'