cgialt 0.0.1 → 0.0.2

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.
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: []