cgialt 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.txt ADDED
@@ -0,0 +1,13 @@
1
+ ## $Rev$
2
+ ## 0.0.2
3
+ ## copyright(c) 2007 kuwata-lab.com all rights reserved.
4
+
5
+
6
+ - release: 0.0.2
7
+ date: 2007-12-11
8
+ enhancements:
9
+ - FastCGI supported. If you required 'cgialt/fcgi' instead of 'fcgi',
10
+ you can use FCGI.each_cgi() method.
11
+
12
+ - release: 0.0.1
13
+ date: 2007-12-09
data/README.txt CHANGED
@@ -1,9 +1,11 @@
1
1
  = README.txt
2
2
 
3
- Release: 0.0.1
3
+ Release: 0.0.2
4
4
 
5
5
  copyright(c) 2007 kuwata-lab.com all rights reserved.
6
6
 
7
+ http://rubyforge.org/projects/cgialt/
8
+
7
9
 
8
10
  == About
9
11
 
@@ -17,14 +19,15 @@ It is written in pure Ruby but works faster than 'cgi.rb'.
17
19
  * Faster and more lightweight than 'cgi.rb'.
18
20
  * Available to install with CGIExt (which is a re-implementation of 'cgi.rb'
19
21
  in C extension).
22
+ * FastCGI support
20
23
 
21
24
 
22
25
  == Install
23
26
 
24
- Download cgialt-0.0.1.tar.gz and install it according to the following:
27
+ Download cgialt-0.0.2.tar.gz and install it according to the following:
25
28
 
26
- $ tar xzf cgialt-0.0.1.tar.gz
27
- $ cd cgialt-0.0.1/
29
+ $ tar xzf cgialt-0.0.2.tar.gz
30
+ $ cd cgialt-0.0.2/
28
31
  $ ruby setup.rb config
29
32
  $ ruby setup.rb setup
30
33
  $ sudo ruby setup.rb install
@@ -45,17 +48,24 @@ CGI class which is compatible with 'cgi.rb'.
45
48
  require 'rubygems' # if you have installed with RubyGems
46
49
  require 'cgialt'
47
50
 
51
+ If you want to use CGIAlt with FastCGI (fcgi.rb), require 'cgialt/fcgi'
52
+ instead of 'fcgi'.
53
+
54
+ require 'cgialt'
55
+ require 'cgialt/fcgi'
56
+
48
57
  If you want to replace original 'cgi.rb' entirely by 'cgialt',
49
58
  create 'cgi.rb' which requires 'cgialt' under proper directory such as
50
59
  '/usr/local/lib/ruby/site_ruby/1.8'.
51
60
 
52
61
  $ sudo echo 'require "cgialt"' > /usr/local/lib/ruby/site_ruby/1.8/cgi.rb
62
+ $ sudo echo 'require "cgialt/fcgi"' > /usr/local/lib/ruby/site_ruby/1.8/fcgi.rb
53
63
 
54
64
  When $DEBUG is true or ENV['DEBUG'] is set, CGIAlt prints release number
55
65
  to $stderr when loaded.
56
66
 
57
67
  $ DEBUG=1 ruby -e 'require "cgi"'
58
- *** CGIAlt: release 0.0.1
68
+ *** CGIAlt: release 0.0.2
59
69
 
60
70
 
61
71
  == Benchmark
@@ -92,8 +102,9 @@ The following is an example of benchmark.
92
102
  CGI#header (simple) 6.0400 0.0100 6.0500 ( 6.0553)
93
103
  CGI#header (complex) 36.2200 0.0400 36.2600 ( 36.3138)
94
104
 
105
+
95
106
  It is good thing for performance to install CGIExt as well as CGIAlt.
96
- The following is an benchmark example of using both CGIAlt and CGIExt.
107
+ The following is a benchmark example of using both CGIAlt and CGIExt.
97
108
 
98
109
  ## CGIAlt and CGIExt
99
110
  $ ruby -s bench.rb -N=1000 -cgialt -cgiext
@@ -110,16 +121,28 @@ The following is an benchmark example of using both CGIAlt and CGIExt.
110
121
  CGI#header (simple) 6.0300 0.0100 6.0400 ( 6.0651)
111
122
  CGI#header (complex) 36.5400 0.0800 36.6200 ( 37.0642)
112
123
 
124
+
113
125
  The following is a summary of above benchmark results.
114
126
 
115
- Table 1. summary of benchmark
116
- cgi.rb CGIAlt CGIAlt+CGIExt
117
- -----------------------------------------------------------------------
118
- require "cgi" (x1000) 13.16 7.89 9.18
119
- CGI#new (simple) (x100000) 20.34 14.53 12.46
120
- CGI#new (comple) (x100000) 26.62 20.10 13.19
121
- CGI#header (simple) (x1000000) 12.68 6.05 6.04
122
- CGI#header (complex) (x1000000) 43.52 36.26 36.62
127
+ Table 1. summary of benchmark
128
+ cgi.rb CGIAlt CGIAlt+CGIExt
129
+ ---------------------------------------------------------------------------
130
+ require "cgi" (x1000) 13.16 7.89 ( 67%) 9.18 ( 43%)
131
+ CGI#new (simple) (x100000) 20.34 14.53 ( 40%) 12.46 ( 63%)
132
+ CGI#new (comple) (x100000) 26.62 20.10 ( 32%) 13.19 (102%)
133
+ CGI#header (simple) (x1000000) 12.68 6.05 (110%) 6.04 (110%)
134
+ CGI#header (complex) (x1000000) 43.52 36.26 ( 20%) 36.62 ( 19%)
135
+
136
+
137
+ Another benchmark script 'bench.fcgi' is provided. It is for FastCGI.
138
+ The following is an example result of benchmark.
139
+
140
+ Table 2. result of bench.fcgi
141
+ Time taken for tests Request per second
142
+ --------------------------------------------------------------------------
143
+ cgi + fcgi 16.686 [sec] 1198.61 [#/sec]
144
+ cgialt + cgialt/fcgi 15.562 [sec] 1285.18 [#/sec]
145
+ cgialt + cgialt/fcgi + cgiext 15.310 [sec] 1306.34 [#/sec]
123
146
 
124
147
 
125
148
  == License
@@ -127,7 +150,7 @@ The following is a summary of above benchmark results.
127
150
  Ruby's license
128
151
 
129
152
 
130
- == Authoer
153
+ == Author
131
154
 
132
155
  makoto kuwata <kwa(at)kuwata-lab.com>
133
156
 
data/bench.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ##
2
2
  ## $Rev: 30 $
3
- ## $Release: 0.0.1 $
3
+ ## $Release: 0.0.2 $
4
4
  ## copyright(c) 2007 kuwata-lab.com all rights reserved.
5
5
  ##
6
6
 
data/lib/cgialt/cookie.rb CHANGED
@@ -1,6 +1,4 @@
1
1
  ##
2
- ## copyright(c) 2007 kuwata-lab.com all rights reserved.
3
- ##
4
2
  ## Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
5
3
  ##
6
4
  ## Copyright (C) 2000 Information-technology Promotion Agency, Japan
@@ -9,6 +7,9 @@
9
7
  ##
10
8
  ## Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
11
9
  ##
10
+ ## $Rev: 32 $
11
+ ## $Release: 0.0.2 $
12
+ ## copyright(c) 2007 kuwata-lab.com all rights reserved.
12
13
 
13
14
  class CGI
14
15
 
@@ -77,13 +78,13 @@ class CGI
77
78
  if name.is_a?(String)
78
79
  @name = name
79
80
  @value = value # value is an Array
80
- @path = rexp.match(ENV['SCRIPT_NAME']) ? $& : ''
81
+ @path = rexp.match($CGI_ENV['SCRIPT_NAME']) ? $& : ''
81
82
  @secure = false
82
83
  else
83
84
  options = name
84
85
  @name = options['name'] or raise ArgumentError, "`name' required"
85
86
  @value = Array(options['value'])
86
- @path = options['path'] || (rexp.match(ENV['SCRIPT_NAME']) ? $& : '') # simple support for IE
87
+ @path = options['path'] || (rexp.match($CGI_ENV['SCRIPT_NAME']) ? $& : '') # simple support for IE
87
88
  @domain = options['domain']
88
89
  @expires = options['expires']
89
90
  @secure = options['secure'] == true
data/lib/cgialt/core.rb CHANGED
@@ -1,6 +1,4 @@
1
1
  ##
2
- ## copyright(c) 2007 kuwata-lab.com all rights reserved.
3
- ##
4
2
  ## Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
5
3
  ##
6
4
  ## Copyright (C) 2000 Information-technology Promotion Agency, Japan
@@ -9,6 +7,9 @@
9
7
  ##
10
8
  ## Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
11
9
  ##
10
+ ## $Rev: 32 $
11
+ ## $Release: 0.0.2 $
12
+ ## copyright(c) 2007 kuwata-lab.com all rights reserved.
12
13
 
13
14
  raise "Please, use ruby 1.5.4 or later." if RUBY_VERSION < "1.5.4"
14
15
 
@@ -257,6 +258,8 @@ class CGI
257
258
 
258
259
  # :stopdoc:
259
260
 
261
+ $CGI_ENV = ENV # for FCGI support
262
+
260
263
  EOL = "\r\n"
261
264
  #*** original
262
265
  #*# String for carriage return
@@ -268,7 +271,7 @@ class CGI
268
271
  #*# Standard internet newline sequence
269
272
  #*EOL = CR + LF
270
273
  #*
271
- #*REVISION = '$Id: core.rb 27 2007-12-08 23:17:16Z kwatch $' #:nodoc:
274
+ #*REVISION = '$Id: core.rb 32 2007-12-11 04:22:35Z kwatch $' #:nodoc:
272
275
  #*
273
276
  #*NEEDS_BINMODE = true if /WIN/ni.match(RUBY_PLATFORM)
274
277
  #*
@@ -309,14 +312,24 @@ class CGI
309
312
  def env_table
310
313
  ENV
311
314
  end
315
+ #*** original
316
+ #*def env_table
317
+ #* ENV
318
+ #*end
319
+ #/*** original
312
320
 
313
321
  def stdinput
314
322
  $stdin
315
323
  end
316
324
 
317
325
  def stdoutput
318
- $DEFAULT_OUTPUT
326
+ $stdout
319
327
  end
328
+ #*** original
329
+ #*def stdoutput
330
+ #* $DEFAULT_OUTPUT
331
+ #*end
332
+ #*** /original
320
333
 
321
334
  private :env_table, :stdinput, :stdoutput
322
335
 
@@ -424,9 +437,9 @@ class CGI
424
437
  def _header_for_string(content_type) #:nodoc:
425
438
  buf = ''
426
439
  if nph?()
427
- buf << "#{ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
440
+ buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
428
441
  buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
429
- buf << "Server: #{ENV['SERVER_SOFTWARE']}#{EOL}"
442
+ buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
430
443
  buf << "Connection: close#{EOL}"
431
444
  end
432
445
  buf << "Content-Type: #{content_type}#{EOL}"
@@ -446,12 +459,12 @@ class CGI
446
459
  ## NPH
447
460
  options.delete('nph') if defined?(MOD_RUBY)
448
461
  if options.delete('nph') || nph?()
449
- protocol = ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
462
+ protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
450
463
  status = options.delete('status')
451
464
  status = HTTP_STATUS[status] || status || '200 OK'
452
465
  buf << "#{protocol} #{status}#{EOL}"
453
466
  buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
454
- options['server'] ||= ENV['SERVER_SOFTWARE'] || ''
467
+ options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
455
468
  options['connection'] ||= 'close'
456
469
  end
457
470
  ## common headers
@@ -494,7 +507,7 @@ class CGI
494
507
  private :_header_for_hash
495
508
 
496
509
  def nph? #:nodoc:
497
- return /IIS\/(\d+)/n.match(ENV['SERVER_SOFTWARE']) && $1.to_i < 5
510
+ return /IIS\/(\d+)/n.match($CGI_ENV['SERVER_SOFTWARE']) && $1.to_i < 5
498
511
  end
499
512
 
500
513
  def _header_for_modruby(buf) #:nodoc:
@@ -702,7 +715,7 @@ class CGI
702
715
  content = convert_content(content, options)
703
716
  options['length'] = content.length.to_s
704
717
  stdout.print header(options)
705
- stdout.print content unless ENV['REQUEST_METHOD'] == 'HEAD'
718
+ stdout.print content unless $CGI_ENV['REQUEST_METHOD'] == 'HEAD'
706
719
  end
707
720
  def convert_content(content, options) #:nodoc:
708
721
  charset = options['charset']
@@ -823,88 +836,88 @@ class CGI
823
836
  module QueryExtension
824
837
 
825
838
  ## return Integer(ENV['CONTENT_LENGTH'])
826
- def content_length ; return Integer(ENV['CONTENT_LENGTH']) ; end
839
+ def content_length ; return Integer($CGI_ENV['CONTENT_LENGTH']) ; end
827
840
 
828
841
  ## return Integer(ENV['SERVER_PORT'])
829
- def server_port ; return Integer(ENV['SERVER_PORT']) ; end
842
+ def server_port ; return Integer($CGI_ENV['SERVER_PORT']) ; end
830
843
 
831
844
  ## return ENV['AUTH_TYPE']
832
- def auth_type ; return ENV['AUTH_TYPE'] ; end
845
+ def auth_type ; return $CGI_ENV['AUTH_TYPE'] ; end
833
846
 
834
847
  ## return ENV['CONTENT_TYPE']
835
- def content_type ; return ENV['CONTENT_TYPE'] ; end
848
+ def content_type ; return $CGI_ENV['CONTENT_TYPE'] ; end
836
849
 
837
850
  ## return ENV['GATEWAY_INTERFACE']
838
- def gateway_interface ; return ENV['GATEWAY_INTERFACE'] ; end
851
+ def gateway_interface ; return $CGI_ENV['GATEWAY_INTERFACE'] ; end
839
852
 
840
853
  ## return ENV['PATH_INFO']
841
- def path_info ; return ENV['PATH_INFO'] ; end
854
+ def path_info ; return $CGI_ENV['PATH_INFO'] ; end
842
855
 
843
856
  ## return ENV['PATH_TRANSLATED']
844
- def path_translated ; return ENV['PATH_TRANSLATED'] ; end
857
+ def path_translated ; return $CGI_ENV['PATH_TRANSLATED'] ; end
845
858
 
846
859
  ## return ENV['QUERY_STRING']
847
- def query_string ; return ENV['QUERY_STRING'] ; end
860
+ def query_string ; return $CGI_ENV['QUERY_STRING'] ; end
848
861
 
849
862
  ## return ENV['REMOTE_ADDR']
850
- def remote_addr ; return ENV['REMOTE_ADDR'] ; end
863
+ def remote_addr ; return $CGI_ENV['REMOTE_ADDR'] ; end
851
864
 
852
865
  ## return ENV['REMOTE_HOST']
853
- def remote_host ; return ENV['REMOTE_HOST'] ; end
866
+ def remote_host ; return $CGI_ENV['REMOTE_HOST'] ; end
854
867
 
855
868
  ## return ENV['REMOTE_IDENT']
856
- def remote_ident ; return ENV['REMOTE_IDENT'] ; end
869
+ def remote_ident ; return $CGI_ENV['REMOTE_IDENT'] ; end
857
870
 
858
871
  ## return ENV['REMOTE_USER']
859
- def remote_user ; return ENV['REMOTE_USER'] ; end
872
+ def remote_user ; return $CGI_ENV['REMOTE_USER'] ; end
860
873
 
861
874
  ## return ENV['REQUEST_METHOD']
862
- def request_method ; return ENV['REQUEST_METHOD'] ; end
875
+ def request_method ; return $CGI_ENV['REQUEST_METHOD'] ; end
863
876
 
864
877
  ## return ENV['SCRIPT_NAME']
865
- def script_name ; return ENV['SCRIPT_NAME'] ; end
878
+ def script_name ; return $CGI_ENV['SCRIPT_NAME'] ; end
866
879
 
867
880
  ## return ENV['SERVER_NAME']
868
- def server_name ; return ENV['SERVER_NAME'] ; end
881
+ def server_name ; return $CGI_ENV['SERVER_NAME'] ; end
869
882
 
870
883
  ## return ENV['SERVER_PROTOCOL']
871
- def server_protocol ; return ENV['SERVER_PROTOCOL'] ; end
884
+ def server_protocol ; return $CGI_ENV['SERVER_PROTOCOL'] ; end
872
885
 
873
886
  ## return ENV['SERVER_SOFTWARE']
874
- def server_software ; return ENV['SERVER_SOFTWARE'] ; end
887
+ def server_software ; return $CGI_ENV['SERVER_SOFTWARE'] ; end
875
888
 
876
889
  ## return ENV['HTTP_ACCEPT']
877
- def accept ; return ENV['HTTP_ACCEPT'] ; end
890
+ def accept ; return $CGI_ENV['HTTP_ACCEPT'] ; end
878
891
 
879
892
  ## return ENV['HTTP_ACCEPT_CHARSET']
880
- def accept_charset ; return ENV['HTTP_ACCEPT_CHARSET'] ; end
893
+ def accept_charset ; return $CGI_ENV['HTTP_ACCEPT_CHARSET'] ; end
881
894
 
882
895
  ## return ENV['HTTP_ACCEPT_ENCODING']
883
- def accept_encoding ; return ENV['HTTP_ACCEPT_ENCODING'] ; end
896
+ def accept_encoding ; return $CGI_ENV['HTTP_ACCEPT_ENCODING'] ; end
884
897
 
885
898
  ## return ENV['HTTP_ACCEPT_LANGUAGE']
886
- def accept_language ; return ENV['HTTP_ACCEPT_LANGUAGE'] ; end
899
+ def accept_language ; return $CGI_ENV['HTTP_ACCEPT_LANGUAGE'] ; end
887
900
 
888
901
  ## return ENV['HTTP_CACHE_CONTROL']
889
- def cache_control ; return ENV['HTTP_CACHE_CONTROL'] ; end
902
+ def cache_control ; return $CGI_ENV['HTTP_CACHE_CONTROL'] ; end
890
903
 
891
904
  ## return ENV['HTTP_FROM']
892
- def from ; return ENV['HTTP_FROM'] ; end
905
+ def from ; return $CGI_ENV['HTTP_FROM'] ; end
893
906
 
894
907
  ## return ENV['HTTP_HOST']
895
- def host ; return ENV['HTTP_HOST'] ; end
908
+ def host ; return $CGI_ENV['HTTP_HOST'] ; end
896
909
 
897
910
  ## return ENV['HTTP_NEGOTIATE']
898
- def negotiate ; return ENV['HTTP_NEGOTIATE'] ; end
911
+ def negotiate ; return $CGI_ENV['HTTP_NEGOTIATE'] ; end
899
912
 
900
913
  ## return ENV['HTTP_PRAGMA']
901
- def pragma ; return ENV['HTTP_PRAGMA'] ; end
914
+ def pragma ; return $CGI_ENV['HTTP_PRAGMA'] ; end
902
915
 
903
916
  ## return ENV['HTTP_REFERER']
904
- def referer ; return ENV['HTTP_REFERER'] ; end
917
+ def referer ; return $CGI_ENV['HTTP_REFERER'] ; end
905
918
 
906
919
  ## return ENV['HTTP_USER_AGENT']
907
- def user_agent ; return ENV['HTTP_USER_AGENT'] ; end
920
+ def user_agent ; return $CGI_ENV['HTTP_USER_AGENT'] ; end
908
921
 
909
922
  #*** orignal
910
923
  #*%w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
@@ -929,7 +942,7 @@ class CGI
929
942
 
930
943
  # Get the raw cookies as a string.
931
944
  def raw_cookie
932
- return ENV['HTTP_COOKIE']
945
+ return $CGI_ENV['HTTP_COOKIE']
933
946
  end
934
947
  #*** original
935
948
  #*def raw_cookie
@@ -939,7 +952,7 @@ class CGI
939
952
 
940
953
  # Get the raw RFC2965 cookies as a string.
941
954
  def raw_cookie2
942
- return ENV['HTTP_COOKIE2']
955
+ return $CGI_ENV['HTTP_COOKIE2']
943
956
  end
944
957
  #*** original
945
958
  #*def raw_cookie2
@@ -1064,7 +1077,7 @@ class CGI
1064
1077
  return body
1065
1078
  end
1066
1079
  def unescape_filename? #:nodoc:
1067
- user_agent = ENV['HTTP_USER_AGENT']
1080
+ user_agent = $CGI_ENV['HTTP_USER_AGENT']
1068
1081
  return /Mac/ni.match(user_agent) && /Mozilla/ni.match(user_agent) && !/MSIE/ni.match(user_agent)
1069
1082
  end
1070
1083
  #*** original
@@ -1222,16 +1235,16 @@ class CGI
1222
1235
  # Handles multipart forms (in particular, forms that involve file uploads).
1223
1236
  # Reads query parameters in the @params field, and cookies into @cookies.
1224
1237
  def initialize_query()
1225
- case ENV['REQUEST_METHOD']
1238
+ case $CGI_ENV['REQUEST_METHOD']
1226
1239
  when 'GET', 'HEAD'
1227
- query_str = defined?(MOD_RUBY) ? Apache::request.args : ENV['QUERY_STRING']
1240
+ query_str = defined?(MOD_RUBY) ? Apache::request.args : $CGI_ENV['QUERY_STRING']
1228
1241
  @params = CGI.parse(query_str || '')
1229
1242
  @multipart = false
1230
1243
  when 'POST'
1231
- content_length = Integer(ENV['CONTENT_LENGTH'])
1232
- if /\Amultipart\/form-data/.match(ENV['CONTENT_TYPE'])
1244
+ content_length = Integer($CGI_ENV['CONTENT_LENGTH'])
1245
+ if /\Amultipart\/form-data/.match($CGI_ENV['CONTENT_TYPE'])
1233
1246
  raise StandardError.new("too large multipart data.") if content_length > MAX_MULTIPART_LENGTH
1234
- unless /boundary=(?:"([^";,]+?)"|([^;,\s]+))/.match(ENV['CONTENT_TYPE'])
1247
+ unless /boundary=(?:"([^";,]+?)"|([^;,\s]+))/.match($CGI_ENV['CONTENT_TYPE'])
1235
1248
  raise StandardError.new("no boundary of multipart data.")
1236
1249
  end
1237
1250
  boundary = $1 || $2
@@ -1249,7 +1262,7 @@ class CGI
1249
1262
  @params = Hash.new([].freeze)
1250
1263
  @multipart = false
1251
1264
  end
1252
- @cookies = CGI::Cookie.parse(ENV['HTTP_COOKIE'] || ENV['COOKIE'])
1265
+ @cookies = CGI::Cookie.parse($CGI_ENV['HTTP_COOKIE'] || $CGI_ENV['COOKIE'])
1253
1266
  nil
1254
1267
  end
1255
1268
  private :initialize_query
@@ -1383,7 +1396,7 @@ class CGI
1383
1396
  # cookies and other parameters are parsed automatically from the standard
1384
1397
  # CGI locations, which varies according to the REQUEST_METHOD.
1385
1398
  def initialize(type=nil)
1386
- if defined?(MOD_RUBY) && !ENV['GATEWAY_INTERFACE']
1399
+ if defined?(MOD_RUBY) && !$CGI_ENV['GATEWAY_INTERFACE']
1387
1400
  Apache.request.setup_cgi_env
1388
1401
  end
1389
1402
  ##
@@ -0,0 +1,102 @@
1
+ ##
2
+ ## $Rev: 33 $
3
+ ## $Release: 0.0.2 $
4
+ ## copyright(c) 2007 kuwata-lab.com all rights reserved.
5
+ ##
6
+
7
+ =begin
8
+
9
+ fcgi.rb 0.8.5 - fcgi.so compatible pure-ruby FastCGI library
10
+
11
+ fastcgi.rb Copyright (C) 2001 Eli Green
12
+ fcgi.rb Copyright (C) 2002-2003 MoonWolf <moonwolf@moonwolf.com>
13
+ fcgi.rb Copyright (C) 2004 Minero Aoki
14
+
15
+ =end
16
+
17
+ require 'cgialt' unless defined?(CGI)
18
+
19
+ class FCGI
20
+
21
+ if FCGI.is_cgi?
22
+ def FCGI.each_cgi(arg=nil)
23
+ #require 'cgialt' unless defined?(CGI)
24
+ yield CGI.new(arg)
25
+ end
26
+ else
27
+ def FCGI.each_cgi(arg=nil)
28
+ #require 'cgialt' unless defined?(CGI)
29
+ #exit_requested = false
30
+ FCGI.each do |request|
31
+ $FCGI_REQUEST = request
32
+ $stdout = request.out
33
+ $stderr = request.err
34
+ #ENV.clear
35
+ #ENV.update(request.env)
36
+ $CGI_ENV = request.env
37
+ yield CGI.new(arg)
38
+ request.finish
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+ #*** original
45
+ #*# There is no C version of 'each_cgi'
46
+ #*# Note: for ruby-1.6.8 at least, the constants CGI_PARAMS/CGI_COOKIES
47
+ #*# are defined within module 'CGI', even if you have subclassed it
48
+ #*
49
+ #*class FCGI
50
+ #* def self::each_cgi(*args)
51
+ #* require 'cgi'
52
+ #*
53
+ #* eval(<<-EOS,TOPLEVEL_BINDING)
54
+ #* class CGI
55
+ #* public :env_table
56
+ #* def self::remove_params
57
+ #* if (const_defined?(:CGI_PARAMS))
58
+ #* remove_const(:CGI_PARAMS)
59
+ #* remove_const(:CGI_COOKIES)
60
+ #* end
61
+ #* end
62
+ #* end # ::CGI class
63
+ #*
64
+ #* class FCGI
65
+ #* class CGI < ::CGI
66
+ #* def initialize(request, *args)
67
+ #* ::CGI.remove_params
68
+ #* @request = request
69
+ #* super(*args)
70
+ #* @args = *args
71
+ #* end
72
+ #* def args
73
+ #* @args
74
+ #* end
75
+ #* def env_table
76
+ #* @request.env
77
+ #* end
78
+ #* def stdinput
79
+ #* @request.in
80
+ #* end
81
+ #* def stdoutput
82
+ #* @request.out
83
+ #* end
84
+ #* end # FCGI::CGI class
85
+ #* end # FCGI class
86
+ #* EOS
87
+ #*
88
+ #* if FCGI::is_cgi?
89
+ #* yield ::CGI.new(*args)
90
+ #* else
91
+ #* exit_requested = false
92
+ #* FCGI::each {|request|
93
+ #* $stdout, $stderr = request.out, request.err
94
+ #*
95
+ #* yield CGI.new(request, *args)
96
+ #*
97
+ #* request.finish
98
+ #* }
99
+ #* end
100
+ #* end
101
+ #*end
102
+ #*** /original
@@ -0,0 +1,561 @@
1
+ ##
2
+ ## $Rev: 33 $
3
+ ## $Release: 0.0.2 $
4
+ ## copyright(c) 2007 kuwata-lab.com all rights reserved.
5
+ ##
6
+
7
+ =begin
8
+
9
+ fcgi.rb 0.8.5 - fcgi.so compatible pure-ruby FastCGI library
10
+
11
+ fastcgi.rb Copyright (C) 2001 Eli Green
12
+ fcgi.rb Copyright (C) 2002-2003 MoonWolf <moonwolf@moonwolf.com>
13
+ fcgi.rb Copyright (C) 2004 Minero Aoki
14
+
15
+ =end
16
+
17
+
18
+ require 'socket'
19
+ require 'stringio'
20
+
21
+ class FCGI
22
+
23
+ def self::is_cgi?
24
+ begin
25
+ s = Socket.for_fd($stdin.fileno)
26
+ s.getpeername
27
+ false
28
+ rescue Errno::ENOTCONN
29
+ false
30
+ rescue Errno::ENOTSOCK, Errno::EINVAL
31
+ true
32
+ end
33
+ end
34
+
35
+ def self::each(&block)
36
+ f = default_connection()
37
+ Server.new(f).each_request(&block)
38
+ ensure
39
+ f.close if f
40
+ end
41
+
42
+ def self::each_request(&block)
43
+ f = default_connection()
44
+ Server.new(f).each_request(&block)
45
+ ensure
46
+ f.close if f
47
+ end
48
+
49
+ def self::default_connection
50
+ ::Socket.for_fd($stdin.fileno)
51
+ end
52
+
53
+
54
+
55
+ ProtocolVersion = 1
56
+
57
+ # Record types
58
+ FCGI_BEGIN_REQUEST = 1
59
+ FCGI_ABORT_REQUEST = 2
60
+ FCGI_END_REQUEST = 3
61
+ FCGI_PARAMS = 4
62
+ FCGI_STDIN = 5
63
+ FCGI_STDOUT = 6
64
+ FCGI_STDERR = 7
65
+ FCGI_DATA = 8
66
+ FCGI_GET_VALUES = 9
67
+ FCGI_GET_VALUES_RESULT = 10
68
+ FCGI_UNKNOWN_TYPE = 11
69
+ FCGI_MAXTYPE = FCGI_UNKNOWN_TYPE
70
+
71
+ FCGI_NULL_REQUEST_ID = 0
72
+
73
+ # FCGI_BEGIN_REQUSET.role
74
+ FCGI_RESPONDER = 1
75
+ FCGI_AUTHORIZER = 2
76
+ FCGI_FILTER = 3
77
+
78
+ # FCGI_BEGIN_REQUEST.flags
79
+ FCGI_KEEP_CONN = 1
80
+
81
+ # FCGI_END_REQUEST.protocolStatus
82
+ FCGI_REQUEST_COMPLETE = 0
83
+ FCGI_CANT_MPX_CONN = 1
84
+ FCGI_OVERLOADED = 2
85
+ FCGI_UNKNOWN_ROLE = 3
86
+
87
+
88
+ class Server
89
+
90
+ def initialize(server)
91
+ @server = server
92
+ @buffers = {}
93
+ @default_parameters = {
94
+ "FCGI_MAX_CONNS" => 1,
95
+ "FCGI_MAX_REQS" => 1,
96
+ "FCGI_MPX_CONNS" => true
97
+ }
98
+ end
99
+
100
+ def each_request(&block)
101
+ graceful = false
102
+ trap("SIGUSR1") { graceful = true }
103
+ while true
104
+ begin
105
+ session(&block)
106
+ rescue Errno::EPIPE, EOFError
107
+ # HTTP request is canceled by the remote user
108
+ end
109
+ exit 0 if graceful
110
+ end
111
+ end
112
+
113
+ def session
114
+ sock, addr = *@server.accept
115
+ return unless sock
116
+ fsock = FastCGISocket.new(sock)
117
+ req = next_request(fsock)
118
+ yield req
119
+ respond_to req, fsock, FCGI_REQUEST_COMPLETE
120
+ ensure
121
+ sock.close if sock and not sock.closed?
122
+ end
123
+
124
+ private
125
+
126
+ def next_request(sock)
127
+ while rec = sock.read_record
128
+ if rec.management_record?
129
+ case rec.type
130
+ when FCGI_GET_VALUES
131
+ sock.send_record handle_GET_VALUES(rec)
132
+ else
133
+ sock.send_record UnknownTypeRecord.new(rec.request_id, rec.type)
134
+ end
135
+ else
136
+ case rec.type
137
+ when FCGI_BEGIN_REQUEST
138
+ @buffers[rec.request_id] = RecordBuffer.new(rec)
139
+ when FCGI_ABORT_REQUEST
140
+ raise "got ABORT_REQUEST" # FIXME
141
+ else
142
+ buf = @buffers[rec.request_id] or next # inactive request
143
+ buf.push rec
144
+ if buf.ready?
145
+ @buffers.delete rec.request_id
146
+ return buf.new_request
147
+ end
148
+ end
149
+ end
150
+ end
151
+ raise "must not happen: FCGI socket unexpected EOF"
152
+ end
153
+
154
+ def handle_GET_VALUES(rec)
155
+ h = {}
156
+ rec.values.each_key do |name|
157
+ h[name] = @default_parameters[name]
158
+ end
159
+ ValuesRecord.new(FCGI_GET_VALUES_RESULT, rec.request_id, h)
160
+ end
161
+
162
+ def respond_to(req, sock, status)
163
+ split_data(FCGI_STDOUT, req.id, req.out) do |rec|
164
+ sock.send_record rec
165
+ end
166
+ split_data(FCGI_STDERR, req.id, req.err) do |rec|
167
+ sock.send_record rec
168
+ end if req.err.length > 0
169
+ sock.send_record EndRequestRecord.new(req.id, 0, status)
170
+ end
171
+
172
+ DATA_UNIT = 16384
173
+
174
+ def split_data(type, id, f)
175
+ unless f.length == 0
176
+ f.rewind
177
+ while s = f.read(DATA_UNIT)
178
+ yield GenericDataRecord.new(type, id, s)
179
+ end
180
+ end
181
+ yield GenericDataRecord.new(type, id, '')
182
+ end
183
+
184
+ end
185
+
186
+
187
+ class FastCGISocket
188
+ def initialize(sock)
189
+ @socket = sock
190
+ end
191
+
192
+ def read_record
193
+ header = @socket.read(Record::HEADER_LENGTH) or return nil
194
+ return nil unless header.size == Record::HEADER_LENGTH
195
+ version, type, reqid, clen, padlen, reserved = *Record.parse_header(header)
196
+ Record.class_for(type).parse(reqid, read_record_body(clen, padlen))
197
+ end
198
+
199
+ def read_record_body(clen, padlen)
200
+ buf = ''
201
+ while buf.length < clen
202
+ buf << @socket.read([1024, clen - buf.length].min)
203
+ end
204
+ @socket.read padlen if padlen
205
+ buf
206
+ end
207
+ private :read_record_body
208
+
209
+ def send_record(rec)
210
+ @socket.write rec.serialize
211
+ @socket.flush
212
+ end
213
+ end
214
+
215
+
216
+ class RecordBuffer
217
+ def initialize(rec)
218
+ @begin_request = rec
219
+ @envs = []
220
+ @stdins = []
221
+ @datas = []
222
+ end
223
+
224
+ def push(rec)
225
+ case rec
226
+ when ParamsRecord
227
+ @envs.push rec
228
+ when StdinDataRecord
229
+ @stdins.push rec
230
+ when DataRecord
231
+ @datas.push rec
232
+ else
233
+ raise "got unknown record: #{rec.class}"
234
+ end
235
+ end
236
+
237
+ def ready?
238
+ case @begin_request.role
239
+ when FCGI_RESPONDER
240
+ completed?(@envs) and
241
+ completed?(@stdins)
242
+ when FCGI_AUTHORIZER
243
+ completed?(@envs)
244
+ when FCGI_FILTER
245
+ completed?(@envs) and
246
+ completed?(@stdins) and
247
+ completed?(@datas)
248
+ else
249
+ raise "unknown role: #{@begin_request.role}"
250
+ end
251
+ end
252
+
253
+ def completed?(records)
254
+ records.last and records.last.empty?
255
+ end
256
+ private :completed?
257
+
258
+ def new_request
259
+ Request.new(@begin_request.request_id, env(), stdin(), nil, nil, data())
260
+ end
261
+
262
+ def env
263
+ h = {}
264
+ @envs.each {|rec| h.update rec.values }
265
+ h
266
+ end
267
+
268
+ def stdin
269
+ StringIO.new(@stdins.inject('') {|buf, rec| buf << rec.flagment })
270
+ end
271
+
272
+ def data
273
+ StringIO.new(@datas.inject('') {|buf, rec| buf << rec.flagment })
274
+ end
275
+ end
276
+
277
+
278
+ class Request
279
+ def initialize(id, env, stdin, stdout = nil, stderr = nil, data = nil)
280
+ @id = id
281
+ @env = env
282
+ @in = stdin
283
+ @out = stdout || StringIO.new
284
+ @err = stderr || StringIO.new
285
+ @data = data || StringIO.new
286
+ end
287
+
288
+ attr_reader :id
289
+ attr_reader :env
290
+ attr_reader :in
291
+ attr_reader :out
292
+ attr_reader :err
293
+ attr_reader :data
294
+
295
+ def finish # for backword compatibility
296
+ end
297
+ end
298
+
299
+
300
+ class Record
301
+ # uint8_t protocol_version;
302
+ # uint8_t record_type;
303
+ # uint16_t request_id; (big endian)
304
+ # uint16_t content_length; (big endian)
305
+ # uint8_t padding_length;
306
+ # uint8_t reserved;
307
+ HEADER_FORMAT = 'CCnnCC'
308
+ HEADER_LENGTH = 8
309
+
310
+ def self::parse_header(buf)
311
+ return *buf.unpack(HEADER_FORMAT)
312
+ end
313
+
314
+ def self::class_for(type)
315
+ RECORD_CLASS[type]
316
+ end
317
+
318
+ def initialize(type, reqid)
319
+ @type = type
320
+ @request_id = reqid
321
+ end
322
+
323
+ def version
324
+ ::FCGI::ProtocolVersion
325
+ end
326
+
327
+ attr_reader :type
328
+ attr_reader :request_id
329
+
330
+ def management_record?
331
+ @request_id == FCGI_NULL_REQUEST_ID
332
+ end
333
+
334
+ def serialize
335
+ body = make_body()
336
+ padlen = body.length % 8
337
+ header = make_header(body.length, padlen)
338
+ header + body + "\000" * padlen
339
+ end
340
+
341
+ private
342
+
343
+ def make_header(clen, padlen)
344
+ [version(), @type, @request_id, clen, padlen, 0].pack(HEADER_FORMAT)
345
+ end
346
+ end
347
+
348
+ class BeginRequestRecord < Record
349
+ # uint16_t role; (big endian)
350
+ # uint8_t flags;
351
+ # uint8_t reserved[5];
352
+ BODY_FORMAT = 'nCC5'
353
+
354
+ def BeginRequestRecord.parse(id, body)
355
+ role, flags, *reserved = *body.unpack(BODY_FORMAT)
356
+ new(id, role, flags)
357
+ end
358
+
359
+ def initialize(id, role, flags)
360
+ super FCGI_BEGIN_REQUEST, id
361
+ @role = role
362
+ @flags = flags
363
+ end
364
+
365
+ attr_reader :role
366
+ attr_reader :flags
367
+
368
+ def make_body
369
+ [@role, @flags, 0, 0, 0, 0, 0].pack(BODY_FORMAT)
370
+ end
371
+ end
372
+
373
+ class AbortRequestRecord < Record
374
+ def AbortRequestRecord.parse(id, body)
375
+ new(id)
376
+ end
377
+
378
+ def initialize(id)
379
+ super FCGI_ABORT_REQUEST, id
380
+ end
381
+ end
382
+
383
+ class EndRequestRecord < Record
384
+ # uint32_t appStatus; (big endian)
385
+ # uint8_t protocolStatus;
386
+ # uint8_t reserved[3];
387
+ BODY_FORMAT = 'NCC3'
388
+
389
+ def self::parse(id, body)
390
+ appstatus, protostatus, *reserved = *body.unpack(BODY_FORMAT)
391
+ new(id, appstatus, protostatus)
392
+ end
393
+
394
+ def initialize(id, appstatus, protostatus)
395
+ super FCGI_END_REQUEST, id
396
+ @application_status = appstatus
397
+ @protocol_status = protostatus
398
+ end
399
+
400
+ attr_reader :application_status
401
+ attr_reader :protocol_status
402
+
403
+ private
404
+
405
+ def make_body
406
+ [@application_status, @protocol_status, 0, 0, 0].pack(BODY_FORMAT)
407
+ end
408
+ end
409
+
410
+ class UnknownTypeRecord < Record
411
+ # uint8_t type;
412
+ # uint8_t reserved[7];
413
+ BODY_FORMAT = 'CC7'
414
+
415
+ def self::parse(id, body)
416
+ type, *reserved = *body.unpack(BODY_FORMAT)
417
+ new(id, type)
418
+ end
419
+
420
+ def initialize(id, t)
421
+ super FCGI_UNKNOWN_TYPE, id
422
+ @unknown_type = t
423
+ end
424
+
425
+ attr_reader :unknown_type
426
+
427
+ private
428
+
429
+ def make_body
430
+ [@unknown_type, 0, 0, 0, 0, 0, 0, 0].pack(BODY_FORMAT)
431
+ end
432
+ end
433
+
434
+ class ValuesRecord < Record
435
+ def self::parse(id, body)
436
+ new(id, parse_values(body))
437
+ end
438
+
439
+ def self::parse_values(buf)
440
+ result = {}
441
+ until buf.empty?
442
+ name, value = *read_pair(buf)
443
+ result[name] = value
444
+ end
445
+ result
446
+ end
447
+
448
+ def self::read_pair(buf)
449
+ nlen = read_length(buf)
450
+ vlen = read_length(buf)
451
+ return buf.slice!(0, nlen), buf.slice!(0, vlen)
452
+ end
453
+
454
+ def self::read_length(buf)
455
+ if buf[0] >> 7 == 0
456
+ then buf.slice!(0,1)[0]
457
+ else buf.slice!(0,4).unpack('N')[0] & ((1<<31) - 1)
458
+ end
459
+ end
460
+
461
+ def initialize(type, id, values)
462
+ super type, id
463
+ @values = values
464
+ end
465
+
466
+ attr_reader :values
467
+
468
+ private
469
+
470
+ def make_body
471
+ buf = ''
472
+ @values.each do |name, value|
473
+ buf << serialize_length(name.length)
474
+ buf << serialize_length(value.length)
475
+ buf << name
476
+ buf << value
477
+ end
478
+ buf
479
+ end
480
+
481
+ def serialize_length(len)
482
+ if len < 0x80
483
+ then len.chr
484
+ else [len | (1<<31)].pack('N')
485
+ end
486
+ end
487
+ end
488
+
489
+ class GetValuesRecord < ValuesRecord
490
+ def initialize(id, values)
491
+ super FCGI_GET_VALUES, id, values
492
+ end
493
+ end
494
+
495
+ class ParamsRecord < ValuesRecord
496
+ def initialize(id, values)
497
+ super FCGI_PARAMS, id, values
498
+ end
499
+
500
+ def empty?
501
+ @values.empty?
502
+ end
503
+ end
504
+
505
+ class GenericDataRecord < Record
506
+ def self::parse(id, body)
507
+ new(id, body)
508
+ end
509
+
510
+ def initialize(type, id, flagment)
511
+ super type, id
512
+ @flagment = flagment
513
+ end
514
+
515
+ attr_reader :flagment
516
+
517
+ def empty?
518
+ @flagment.empty?
519
+ end
520
+
521
+ private
522
+
523
+ def make_body
524
+ @flagment
525
+ end
526
+ end
527
+
528
+ class StdinDataRecord < GenericDataRecord
529
+ def initialize(id, flagment)
530
+ super FCGI_STDIN, id, flagment
531
+ end
532
+ end
533
+
534
+ class StdoutDataRecord < GenericDataRecord
535
+ def initialize(id, flagment)
536
+ super FCGI_STDOUT, id, flagment
537
+ end
538
+ end
539
+
540
+ class DataRecord < GenericDataRecord
541
+ def initialize(id, flagment)
542
+ super FCGI_DATA, id, flagment
543
+ end
544
+ end
545
+
546
+ class Record # redefine
547
+ RECORD_CLASS = {
548
+ FCGI_GET_VALUES => GetValuesRecord,
549
+
550
+ FCGI_BEGIN_REQUEST => BeginRequestRecord,
551
+ FCGI_ABORT_REQUEST => AbortRequestRecord,
552
+ FCGI_PARAMS => ParamsRecord,
553
+ FCGI_STDIN => StdinDataRecord,
554
+ FCGI_DATA => DataRecord,
555
+ FCGI_STDOUT => StdoutDataRecord,
556
+ FCGI_END_REQUEST => EndRequestRecord
557
+ }
558
+ end
559
+
560
+ end # FCGI class
561
+
@@ -0,0 +1,28 @@
1
+ ##
2
+ ## $Rev: 33 $
3
+ ## $Release: 0.0.2 $
4
+ ## copyright(c) 2007 kuwata-lab.com all rights reserved.
5
+ ##
6
+
7
+ =begin
8
+
9
+ fcgi.rb 0.8.5 - fcgi.so compatible pure-ruby FastCGI library
10
+
11
+ fastcgi.rb Copyright (C) 2001 Eli Green
12
+ fcgi.rb Copyright (C) 2002-2003 MoonWolf <moonwolf@moonwolf.com>
13
+ fcgi.rb Copyright (C) 2004 Minero Aoki
14
+
15
+ =end
16
+
17
+
18
+ trap('SIGTERM') { exit }
19
+ trap('SIGPIPE', 'IGNORE')
20
+
21
+ begin
22
+ raise LoadError if defined?(FCGI_PURE_RUBY) && FCGI_PURE_RUBY
23
+ require 'fcgi.so'
24
+ rescue LoadError
25
+ require 'cgialt/fcgi/core'
26
+ end
27
+
28
+ require 'cgialt/fcgi/cgi_helper' if defined?(CGI)
data/lib/cgialt.rb CHANGED
@@ -31,7 +31,7 @@
31
31
  # protocol.
32
32
 
33
33
  class CGI
34
- RELEASE = ('$Release: 0.0.1 $' =~ /[.\d]+/) && $&
34
+ RELEASE = ('$Release: 0.0.2 $' =~ /[.\d]+/) && $&
35
35
  if $DEBUG || ENV['DEBUG']
36
36
  $stderr.puts "*** CGIAlt: release #{RELEASE}"
37
37
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: cgialt
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.0.1
7
- date: 2007-12-09 00:00:00 +09:00
6
+ version: 0.0.2
7
+ date: 2007-12-11 00:00:00 +09:00
8
8
  summary: an alternative of 'cgi.rb' in pure Ruby
9
9
  require_paths:
10
10
  - lib
@@ -32,6 +32,10 @@ files:
32
32
  - lib/cgialt
33
33
  - lib/cgialt/cookie.rb
34
34
  - lib/cgialt/core.rb
35
+ - lib/cgialt/fcgi
36
+ - lib/cgialt/fcgi/cgi_helper.rb
37
+ - lib/cgialt/fcgi/core.rb
38
+ - lib/cgialt/fcgi.rb
35
39
  - lib/cgialt/html.rb
36
40
  - lib/cgialt/util.rb
37
41
  - lib/cgialt.rb
@@ -47,6 +51,7 @@ files:
47
51
  - README.txt
48
52
  - bench.rb
49
53
  - setup.rb
54
+ - CHANGES.txt
50
55
  test_files: []
51
56
 
52
57
  rdoc_options: []