rack-cgi 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a57e39eb35e6fbd1bf45f61d55dc6573ebdfdd1d
4
- data.tar.gz: 14ba6dbf2ba1a2de9f667af129677ec3631ddc6e
3
+ metadata.gz: 4618ec968b358ef35f6d1ea3399aa48229fadaec
4
+ data.tar.gz: 17b358d43485c6cacb06d371f1ce7d6b8873436f
5
5
  SHA512:
6
- metadata.gz: 596e99e2e0f7e6cf232897087252457a72a0c44c434d0e9e3bd0e1f2825aa97eddbab57f7ce16ba4437dd6e2320cd495fe24eea7031d073e0b3698b42cd4c0d4
7
- data.tar.gz: 25d98ca0ee4d4eed6e59baf8779e9f9d884cba91f98026b33a0dfdbbf843fcbb3fe043c165278c509f9cd34064395aa1a9cddd4f0b24587f9a9d2f1c80a54e45
6
+ metadata.gz: 4e401f35c930f09fbe29b44329b1c39b03be50df738891f2c1ab9b535d223c473cf3f92f82030a09c85fdd604c0717bafd88fbc209b49dad0fa4db8753c9814a
7
+ data.tar.gz: 8ef794dcd8a596bfda31a2967aba5583f6e0010af48e2320ecb00091383a6f5a334d201a23cef8b15206dcbcedf96ea6cb70264ca071091bbd9e538ff90c99ec
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Cgi
3
- VERSION = "0.2.3"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
data/lib/rack/cgi.rb CHANGED
@@ -1 +1,174 @@
1
- require 'rack-cgi'
1
+ require 'childprocess'
2
+
3
+ module Rack
4
+ class CGI
5
+ class Executable
6
+ def self.=~ rhs
7
+ ::File.executable? rhs
8
+ end
9
+ end
10
+
11
+ def initialize app, args = {}
12
+ @app = app
13
+ @opts = args.select {|k, _| k.is_a? Symbol}
14
+ @rules = args.select {|k, _| !k.is_a? Symbol}
15
+
16
+ @root = @opts[:cgi_path]
17
+ if @root !~ /^\//
18
+ @root = ::File.join(Dir.pwd, @root)
19
+ end
20
+
21
+ @index = @opts[:index] || []
22
+ @index = [@index] if not @index.is_a? Hash
23
+ end
24
+
25
+ def solve_path path
26
+ path = ::File.join(@root, path)
27
+ if ::File.directory? path
28
+ @index.each do |f|
29
+ path2 = ::File.join(path, f)
30
+ return path2 if ::File.file? path2
31
+ end
32
+ else
33
+ return path if ::File.file? path
34
+ end
35
+ nil
36
+ end
37
+
38
+ def cgi_env env, path
39
+ env = env.select {|k, _| k =~ /^[A-Z]/}
40
+ env['SCRIPT_FILENAME'] = path
41
+ env['DOCUMENT_ROOT'] = @root
42
+ env['REDIRECT_STATUS'] = "200"
43
+ env
44
+ end
45
+
46
+ def match_cgi_rule path
47
+ @rules.each do |m, r|
48
+ if m =~ path
49
+ return r
50
+ end
51
+ end
52
+ return nil
53
+ end
54
+
55
+ def run_cgi rule, path, env
56
+ if rule.empty?
57
+ args = [path]
58
+ else
59
+ args = [rule, path]
60
+ end
61
+
62
+ process = ChildProcess.build(*args)
63
+ process.io.stdout = Tempfile.new('rack-cgi-stdout')
64
+ process.io.stderr = Tempfile.new('rack-cgi-stderr')
65
+ env.each do |k, v|
66
+ process.environment[k] = v
67
+ end
68
+ process.cwd = Dir.pwd
69
+ process.start
70
+ process.wait
71
+
72
+ cont_out = ::File.read(process.io.stdout.path)
73
+ cont_err = ::File.read(process.io.stderr.path)
74
+ process.io.stdout.unlink
75
+ process.io.stderr.unlink
76
+
77
+ [process.exit_code, cont_out, cont_err]
78
+ end
79
+
80
+ def split_header_content output
81
+ lines = output.lines.to_a
82
+ header = []
83
+
84
+ until lines.empty?
85
+ l = lines.shift
86
+ if l == "\n" or l == "\r\n"
87
+ # find break line between header and content
88
+ return header.join, lines.join
89
+ elsif l =~ /:/
90
+ header << l
91
+ else
92
+ # content break header ruler, so deal as no header
93
+ return "", output
94
+ end
95
+ end
96
+
97
+ # deal all content as header
98
+ return output, ""
99
+ end
100
+
101
+ def parse_output output
102
+ header, content = split_header_content output
103
+
104
+ h = {}
105
+ header.each_line do |l|
106
+ k, v = l.split ':', 2
107
+ k.strip!
108
+ v.strip!
109
+ h[k.downcase] = [k, v]
110
+ end
111
+
112
+ if h['status']
113
+ status = h['status'][1].to_i
114
+ h.delete 'status'
115
+ else
116
+ status = 200
117
+ end
118
+
119
+ header_hash = Hash[h.values]
120
+
121
+ [status, header_hash, [content]]
122
+ end
123
+
124
+ def report_error code, out, err, cgi_env
125
+ h = {'Content-Type' => 'text/plain'}
126
+ status = 500
127
+ reports = []
128
+
129
+ reports << "CGI Error!\n\n"
130
+ reports << "stdout output:\n"
131
+ reports << out
132
+ reports << "\n"
133
+ reports << "stderr output:\n"
134
+ reports << err
135
+ reports << "\n"
136
+ reports << "environments:\n"
137
+ cgi_env.each do |k, v|
138
+ reports << "#{k} => #{v}\n"
139
+ end
140
+
141
+ [status, h, reports]
142
+ end
143
+
144
+ def call(env)
145
+ path = solve_path env["PATH_INFO"]
146
+ if not path
147
+ return @app.call(env)
148
+ end
149
+
150
+ rule = match_cgi_rule path
151
+ if not rule
152
+ return @app.call(env)
153
+ end
154
+
155
+ cgi_env = cgi_env(env, path)
156
+ code, out, err = run_cgi rule, path, cgi_env
157
+ if code == 0
158
+ parse_output out
159
+ else
160
+ report_error code, out, err, cgi_env
161
+ end
162
+ end
163
+ def run(env, rule, path)
164
+ cgi_env = cgi_env(env, path)
165
+ code, out, err = run_cgi rule, path, cgi_env
166
+ if code == 0
167
+ parse_output out
168
+ else
169
+ report_error code, out, err, cgi_env
170
+ end
171
+ end
172
+ end
173
+ end
174
+
data/lib/rack-cgi.rb CHANGED
@@ -1,165 +1 @@
1
- require 'childprocess'
2
-
3
- module Rack
4
- class CGI
5
- class Executable
6
- def self.=~ rhs
7
- ::File.executable? rhs
8
- end
9
- end
10
-
11
- def initialize app, args = {}
12
- @app = app
13
- @opts = args.select {|k, _| k.is_a? Symbol}
14
- @rules = args.select {|k, _| !k.is_a? Symbol}
15
-
16
- @root = @opts[:cgi_path]
17
- if @root !~ /^\//
18
- @root = ::File.join(Dir.pwd, @root)
19
- end
20
-
21
- @index = @opts[:index] || []
22
- @index = [@index] if not @index.is_a? Hash
23
- end
24
-
25
- def solve_path path
26
- path = ::File.join(@root, path)
27
- if ::File.directory? path
28
- @index.each do |f|
29
- path2 = ::File.join(path, f)
30
- return path2 if ::File.file? path2
31
- end
32
- else
33
- return path if ::File.file? path
34
- end
35
- nil
36
- end
37
-
38
- def cgi_env env, path
39
- env = env.select {|k, _| k =~ /^[A-Z]/}
40
- env['SCRIPT_FILENAME'] = path
41
- env['DOCUMENT_ROOT'] = @root
42
- env['REDIRECT_STATUS'] = "200"
43
- env
44
- end
45
-
46
- def match_cgi_rule path
47
- @rules.each do |m, r|
48
- if m =~ path
49
- return r
50
- end
51
- end
52
- return nil
53
- end
54
-
55
- def run_cgi rule, path, env
56
- if rule.empty?
57
- args = [path]
58
- else
59
- args = [rule, path]
60
- end
61
-
62
- process = ChildProcess.build(*args)
63
- process.io.stdout = Tempfile.new('rack-cgi-stdout')
64
- process.io.stderr = Tempfile.new('rack-cgi-stderr')
65
- env.each do |k, v|
66
- process.environment[k] = v
67
- end
68
- process.cwd = Dir.pwd
69
- process.start
70
- process.wait
71
-
72
- cont_out = ::File.read(process.io.stdout.path)
73
- cont_err = ::File.read(process.io.stderr.path)
74
- process.io.stdout.unlink
75
- process.io.stderr.unlink
76
-
77
- [process.exit_code, cont_out, cont_err]
78
- end
79
-
80
- def split_header_content output
81
- lines = output.lines.to_a
82
- header = []
83
-
84
- until lines.empty?
85
- l = lines.shift
86
- if l == "\n" or l == "\r\n"
87
- # find break line between header and content
88
- return header.join, lines.join
89
- elsif l =~ /:/
90
- header << l
91
- else
92
- # content break header ruler, so deal as no header
93
- return "", output
94
- end
95
- end
96
-
97
- # deal all content as header
98
- return output, ""
99
- end
100
-
101
- def parse_output output
102
- header, content = split_header_content output
103
-
104
- h = {}
105
- header.each_line do |l|
106
- k, v = l.split ':', 2
107
- k.strip!
108
- v.strip!
109
- h[k.downcase] = [k, v]
110
- end
111
-
112
- if h['status']
113
- status = h['status'][1].to_i
114
- h.delete 'status'
115
- else
116
- status = 200
117
- end
118
-
119
- header_hash = Hash[h.values]
120
-
121
- [status, header_hash, [content]]
122
- end
123
-
124
- def report_error code, out, err, cgi_env
125
- h = {'Content-Type' => 'text/plain'}
126
- status = 500
127
- reports = []
128
-
129
- reports << "CGI Error!\n\n"
130
- reports << "stdout output:\n"
131
- reports << out
132
- reports << "\n"
133
- reports << "stderr output:\n"
134
- reports << err
135
- reports << "\n"
136
- reports << "environments:\n"
137
- cgi_env.each do |k, v|
138
- reports << "#{k} => #{v}\n"
139
- end
140
-
141
- [status, h, reports]
142
- end
143
-
144
- def call(env)
145
- path = solve_path env["PATH_INFO"]
146
- if not path
147
- return @app.call(env)
148
- end
149
-
150
- rule = match_cgi_rule path
151
- if not rule
152
- return @app.call(env)
153
- end
154
-
155
- cgi_env = cgi_env(env, path)
156
- code, out, err = run_cgi rule, path, cgi_env
157
- if code == 0
158
- parse_output out
159
- else
160
- report_error code, out, err, cgi_env
161
- end
162
- end
163
- end
164
- end
165
-
1
+ require_relative 'rack/cgi'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-cgi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chizhong Jin