fcgi 0.8.5 → 0.9.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/{README → README.rdoc} +9 -12
- data/README.signals +76 -0
- data/VERSION +1 -0
- data/{MANIFEST → ext/fcgi/MANIFEST} +0 -2
- data/ext/fcgi/Makefile +1 -0
- data/ext/fcgi/extconf.rb +7 -0
- data/{fcgi.c → ext/fcgi/fcgi.c} +166 -55
- data/fcgi.gemspec +31 -13
- data/lib/fcgi.rb +69 -36
- data/test/helper.rb +9 -0
- data/test/test_fcgi.rb +7 -0
- metadata +60 -40
- data/extconf.rb +0 -9
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bb36e2d30016bac819a6aec9d30890bcca7750ec82862e099f89ae341049ed7c
|
4
|
+
data.tar.gz: af9e34e45aa8cb7673f721439e765e82e31ed8fd910987d294801335ce17fa0d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 79f085764709841d49d4c6e91fc8188a5ba952a7e11f544addde2602d7a8e325bc346613d6c12bf3ade8cb09e0269d79c28a49a71ed369ef833542c3da2ff736
|
7
|
+
data.tar.gz: 0c02df774067bab5dcc11f065bee1f55e941900f5602ce60deceef24df78c1588cbefd1cae67926d3335c4e1aa1e360c25ffc3c2daeffe19e973ee5f9b98d912
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2009 saks
|
2
|
+
Copyright (c) 2013 mva
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/{README → README.rdoc}
RENAMED
@@ -1,22 +1,18 @@
|
|
1
|
-
= fcgi - FastCGI library for Ruby
|
1
|
+
= fcgi - The New generation of FastCGI library for Ruby.
|
2
2
|
|
3
|
-
Version 0.
|
3
|
+
Version 0.9.2.1
|
4
4
|
|
5
5
|
== Depends
|
6
6
|
|
7
7
|
=== C version
|
8
|
-
* http://www.fastcgi.com/#TheDevKit
|
8
|
+
* ((<libfcgi|URL:http://www.fastcgi.com/#TheDevKit>))(FastCGI Developer's Kit)
|
9
9
|
|
10
10
|
=== Pure Ruby Version
|
11
11
|
* StringIO
|
12
12
|
|
13
13
|
== Install
|
14
14
|
|
15
|
-
$
|
16
|
-
(Pure Ruby Version: ruby install.rb config --without-ext)
|
17
|
-
(Some systems need: ruby install.rb config -- --with-fcgi-include=/usr/local/include --with-fcgi-lib=/usr/local/lib)
|
18
|
-
$ ruby install.rb setup
|
19
|
-
# ruby install.rb install
|
15
|
+
$ gem install fcgi
|
20
16
|
|
21
17
|
== Usage
|
22
18
|
=== Class Method
|
@@ -42,7 +38,6 @@ Version 0.8.5
|
|
42
38
|
used in this way, as it dynamically adds a large number of methods
|
43
39
|
to itself each time a new instance is created.
|
44
40
|
|
45
|
-
|
46
41
|
=== Instance Method
|
47
42
|
--- FCGI#finish
|
48
43
|
Finish
|
@@ -60,11 +55,12 @@ Version 0.8.5
|
|
60
55
|
Returns Environment(Hash)
|
61
56
|
|
62
57
|
== Sample
|
58
|
+
|
63
59
|
Using the FastCGI native interface:
|
64
60
|
|
65
61
|
#!/usr/bin/ruby
|
66
62
|
require "fcgi"
|
67
|
-
|
63
|
+
|
68
64
|
FCGI.each {|request|
|
69
65
|
out = request.out
|
70
66
|
out.print "Content-Type: text/plain\r\n"
|
@@ -97,13 +93,14 @@ standard CGI library.
|
|
97
93
|
|
98
94
|
== License
|
99
95
|
|
100
|
-
* http://www.ruby-lang.org/ja/LICENSE.txt (Japanese)
|
101
|
-
* http://www.ruby-lang.org/en/LICENSE.txt (English)
|
96
|
+
* ((<URL:http://www.ruby-lang.org/ja/LICENSE.txt>)) (Japanese)
|
97
|
+
* ((<URL:http://www.ruby-lang.org/en/LICENSE.txt>)) (English)
|
102
98
|
|
103
99
|
== Copyright
|
104
100
|
|
105
101
|
fcgi.c 0.1 Copyright (C) 1998-1999 Network Applied Communication Laboratory, Inc.
|
106
102
|
0.8 Copyright (C) 2002 MoonWolf <moonwolf@moonwolf.com>
|
103
|
+
0.9 Copyright (C) 2013 mva <mva@mva.name> Alpha, LLC
|
107
104
|
|
108
105
|
fastcgi.rb 0.7 Copyright (C) 2001 Eli Green
|
109
106
|
fcgi.rb 0.8 Copyright (C) 2002 MoonWolf <moonwolf@moonwolf.com>
|
data/README.signals
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
= Handling of SIGUSR1
|
2
|
+
|
3
|
+
When you request a 'graceful' restart of Apache, mod_fastcgi sends a SIGUSR1
|
4
|
+
to each of the fastcgi worker processes. The intention is that each one
|
5
|
+
should finish the current request, and then exit, at which point Apache will
|
6
|
+
restart it. Of course, if the worker isn't doing anything, it should die
|
7
|
+
immediately.
|
8
|
+
|
9
|
+
This is implemented in the fcgi C library as follows:
|
10
|
+
|
11
|
+
- a signal handler is installed for SIGUSR1, which just sets a flag
|
12
|
+
(shutdownPending) and returns
|
13
|
+
- fcgi sits inside an accept() call waiting for a new request
|
14
|
+
- if this accept() call terminates with EINTR, and this flag is set, then
|
15
|
+
it returns with no request
|
16
|
+
|
17
|
+
Unfortunately, Ruby defeats this mechanism in at least two ways:
|
18
|
+
|
19
|
+
1. Ruby installs its own signal handlers for a host of common signals,
|
20
|
+
including USR1. The fcgi library will not install its own handler if it
|
21
|
+
detects that a handler has already been set (i.e. the current handler is not
|
22
|
+
SIG_DFL)
|
23
|
+
|
24
|
+
2. When Ruby installs its own signal handlers, it does so with SA_RESTART
|
25
|
+
set. This means that the accept() call does not terminate with EINTR; it is
|
26
|
+
restarted automatically by the OS.
|
27
|
+
|
28
|
+
When a signal comes in during the accept(), Ruby's own handler does nothing
|
29
|
+
except store it in a queue to be processed later. It is only when the
|
30
|
+
accept() call completes, i.e. when a genuine new request comes in, that Ruby
|
31
|
+
takes action. Unfortunately it's too late by then, and if that
|
32
|
+
already-accepted request is not honoured, a 500 Internal Error will be
|
33
|
+
returned to the client.
|
34
|
+
|
35
|
+
The simplest solution to this would be to remove Ruby's SIGUSR1 handler
|
36
|
+
before initialising the FastCGI library.
|
37
|
+
|
38
|
+
However, a cleaner solution is to call rb_thread_select before going into
|
39
|
+
FastCGI's accept loop. If a signal happens during the select, it can be
|
40
|
+
handled using Ruby's normal mechanisms. This also gives a very useful
|
41
|
+
side-benefit, which is that FCGI::accept no longer blocks out other Ruby
|
42
|
+
threads. The program below demonstrates this problem; its background logging
|
43
|
+
thread is supposed to write a message every 10 seconds, but under older
|
44
|
+
versions of ruby-fcgi it does not do so if it is waiting for a new request.
|
45
|
+
|
46
|
+
#!/usr/local/bin/ruby
|
47
|
+
require "fcgi"
|
48
|
+
|
49
|
+
Thread.new do
|
50
|
+
f = File.new("/tmp/fcgi.log","a")
|
51
|
+
f.sync=true
|
52
|
+
while true
|
53
|
+
f.puts "#{Time.now.to_s} pid #{$$}"
|
54
|
+
sleep 10
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
FCGI.each_cgi {|cgi|
|
59
|
+
name = cgi['name'][0]
|
60
|
+
puts cgi.header
|
61
|
+
puts "Hey! You are #{name} " if name
|
62
|
+
puts "Connecting from #{cgi.remote_addr}"
|
63
|
+
}
|
64
|
+
|
65
|
+
Having protected the accept() with a ruby select(), you can then handle
|
66
|
+
signals as follows:
|
67
|
+
|
68
|
+
- call FCGI::accept (it will raise an exception if USR1 is called)
|
69
|
+
- install a USR1 handler
|
70
|
+
- process the request
|
71
|
+
- remove the USR1 handler
|
72
|
+
|
73
|
+
The USR1 handler should set a flag to note if a USR1 signal came in while
|
74
|
+
the request was being processed; you terminate the loop if it was set. The
|
75
|
+
overall effect is that USR1 will cause the process to terminate, but without
|
76
|
+
causing a half-completed request.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.9.2.1
|
data/ext/fcgi/Makefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Use ruby extconf.rb to generate makefile
|
data/ext/fcgi/extconf.rb
ADDED
data/{fcgi.c → ext/fcgi/fcgi.c}
RENAMED
@@ -1,15 +1,34 @@
|
|
1
1
|
/*
|
2
2
|
* fcgi.c
|
3
3
|
* Copyright (C) 1998-1999 Network Applied Communication Laboratory, Inc.
|
4
|
-
* Copyright (C) 2002
|
4
|
+
* Copyright (C) 2002-2006 MoonWolf <moonwolf@moonwolf.com>
|
5
|
+
* Copyright (C) 2012-2014 mva <mva@mva.name>
|
5
6
|
*/
|
6
7
|
|
7
8
|
#include <stdio.h>
|
8
9
|
#include <sys/types.h>
|
9
10
|
#include <unistd.h>
|
11
|
+
#include <errno.h>
|
12
|
+
#include <fcntl.h>
|
10
13
|
|
11
14
|
#include "ruby.h"
|
15
|
+
#ifdef HAVE_RUBY_VERSION_H
|
16
|
+
#include "ruby/version.h"
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#ifndef RSTRING_PTR
|
20
|
+
#define RSTRING_PTR(str) (RSTRING(str)->ptr)
|
21
|
+
#endif
|
22
|
+
#ifndef RSTRING_LEN
|
23
|
+
#define RSTRING_LEN(str) (RSTRING(str)->len)
|
24
|
+
#endif
|
25
|
+
|
26
|
+
#ifdef HAVE_FASTCGI_FCGIAPP_H
|
27
|
+
#include <fastcgi/fcgiapp.h>
|
28
|
+
#else
|
12
29
|
#include "fcgiapp.h"
|
30
|
+
#endif
|
31
|
+
|
13
32
|
|
14
33
|
static VALUE cFCGI;
|
15
34
|
static VALUE eFCGIError;
|
@@ -20,6 +39,11 @@ static VALUE eFCGIStreamProtocolError;
|
|
20
39
|
static VALUE eFCGIStreamParamsError;
|
21
40
|
static VALUE eFCGIStreamCallSeqError;
|
22
41
|
|
42
|
+
typedef struct fcgi_stream_data {
|
43
|
+
VALUE req;
|
44
|
+
FCGX_Stream *stream;
|
45
|
+
} fcgi_stream_data;
|
46
|
+
|
23
47
|
typedef struct fcgi_data {
|
24
48
|
FCGX_Request *req;
|
25
49
|
VALUE in;
|
@@ -28,50 +52,82 @@ typedef struct fcgi_data {
|
|
28
52
|
VALUE env;
|
29
53
|
} fcgi_data;
|
30
54
|
|
55
|
+
static void fcgi_stream_mark(fcgi_stream_data *stream_data)
|
56
|
+
{
|
57
|
+
rb_gc_mark(stream_data->req);
|
58
|
+
}
|
59
|
+
|
60
|
+
static void fcgi_stream_free(fcgi_stream_data *stream_data)
|
61
|
+
{
|
62
|
+
free(stream_data);
|
63
|
+
}
|
64
|
+
|
31
65
|
static void fcgi_mark(fcgi_data *data)
|
32
66
|
{
|
33
|
-
/* rb_gc_mark(data->req); */
|
34
67
|
rb_gc_mark(data->in);
|
35
68
|
rb_gc_mark(data->out);
|
36
69
|
rb_gc_mark(data->err);
|
37
70
|
rb_gc_mark(data->env);
|
38
71
|
}
|
39
72
|
|
73
|
+
static void fcgi_free_req(fcgi_data *data)
|
74
|
+
{
|
75
|
+
FCGX_Free(data->req, 1);
|
76
|
+
free(data->req);
|
77
|
+
free(data);
|
78
|
+
}
|
79
|
+
|
40
80
|
static VALUE fcgi_s_accept(VALUE self)
|
41
81
|
{
|
42
82
|
int status;
|
43
83
|
FCGX_Request *req;
|
44
|
-
|
45
|
-
|
84
|
+
rb_fdset_t readfds;
|
85
|
+
|
46
86
|
req = ALLOC(FCGX_Request);
|
47
|
-
|
87
|
+
|
48
88
|
status = FCGX_InitRequest(req,0,0);
|
49
89
|
if (status != 0) {
|
50
90
|
rb_raise(eFCGIError, "FCGX_Init() failed");
|
51
91
|
return Qnil;
|
52
92
|
}
|
53
93
|
|
54
|
-
|
55
|
-
|
56
|
-
if (
|
94
|
+
rb_fd_init(&readfds);
|
95
|
+
rb_fd_set(req->listen_sock, &readfds);
|
96
|
+
if (rb_thread_fd_select(readfds.maxfd, &readfds, NULL, NULL, NULL) < 1) {
|
57
97
|
return Qnil;
|
58
98
|
}
|
59
|
-
|
99
|
+
|
60
100
|
status = FCGX_Accept_r(req);
|
61
101
|
if (status >= 0) {
|
62
102
|
fcgi_data *data;
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
103
|
+
fcgi_stream_data *stream_data;
|
104
|
+
char **env;
|
105
|
+
VALUE obj,key, value;
|
106
|
+
char *pkey,*pvalue;
|
107
|
+
int flags, fd;
|
108
|
+
|
109
|
+
/* Unset NONBLOCKING */
|
110
|
+
fd = ((FCGX_Request*) req)->ipcFd;
|
111
|
+
flags = fcntl(fd, F_GETFL);
|
112
|
+
|
113
|
+
if (flags & O_NONBLOCK) {
|
114
|
+
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
115
|
+
}
|
116
|
+
|
117
|
+
obj = Data_Make_Struct(self, fcgi_data, fcgi_mark, fcgi_free_req, data);
|
68
118
|
data->req = req;
|
69
|
-
data->in
|
70
|
-
|
71
|
-
|
119
|
+
data->in = Data_Make_Struct(cFCGIStream, fcgi_stream_data, fcgi_stream_mark, fcgi_stream_free, stream_data);
|
120
|
+
stream_data->stream = req->in;
|
121
|
+
stream_data->req = obj;
|
122
|
+
data->out = Data_Make_Struct(cFCGIStream, fcgi_stream_data, fcgi_stream_mark, fcgi_stream_free, stream_data);
|
123
|
+
stream_data->stream = req->out;
|
124
|
+
stream_data->req = obj;
|
125
|
+
data->err = Data_Make_Struct(cFCGIStream, fcgi_stream_data, fcgi_stream_mark, fcgi_stream_free, stream_data);
|
126
|
+
stream_data->stream = req->err;
|
127
|
+
stream_data->req = obj;
|
72
128
|
data->env = rb_hash_new();
|
73
129
|
env = req->envp;
|
74
|
-
for (
|
130
|
+
for (; *env; env++) {
|
75
131
|
int size = 0;
|
76
132
|
pkey = *env;
|
77
133
|
pvalue = pkey;
|
@@ -82,9 +138,11 @@ static VALUE fcgi_s_accept(VALUE self)
|
|
82
138
|
OBJ_TAINT(value);
|
83
139
|
rb_hash_aset(data->env, key, value);
|
84
140
|
}
|
85
|
-
|
141
|
+
|
86
142
|
return obj;
|
87
143
|
} else {
|
144
|
+
FCGX_Free(req, 1);
|
145
|
+
free(req);
|
88
146
|
return Qnil;
|
89
147
|
}
|
90
148
|
}
|
@@ -92,7 +150,7 @@ static VALUE fcgi_s_accept(VALUE self)
|
|
92
150
|
static VALUE fcgi_s_each(VALUE self)
|
93
151
|
{
|
94
152
|
VALUE fcgi;
|
95
|
-
|
153
|
+
|
96
154
|
while ((fcgi = fcgi_s_accept(self)) != Qnil) {
|
97
155
|
rb_yield(fcgi);
|
98
156
|
}
|
@@ -143,19 +201,35 @@ static VALUE fcgi_env(VALUE self)
|
|
143
201
|
static VALUE fcgi_finish(VALUE self)
|
144
202
|
{
|
145
203
|
fcgi_data *data;
|
146
|
-
|
204
|
+
fcgi_stream_data *stream_data;
|
205
|
+
|
147
206
|
Data_Get_Struct(self, fcgi_data, data);
|
148
|
-
|
207
|
+
|
208
|
+
if (Qnil != data->in) {
|
209
|
+
Data_Get_Struct(data->in, fcgi_stream_data, stream_data);
|
210
|
+
stream_data->req = Qnil; stream_data->stream = NULL;
|
211
|
+
}
|
212
|
+
if (Qnil != data->out) {
|
213
|
+
Data_Get_Struct(data->out, fcgi_stream_data, stream_data);
|
214
|
+
stream_data->req = Qnil; stream_data->stream = NULL;
|
215
|
+
}
|
216
|
+
if (Qnil != data->err) {
|
217
|
+
Data_Get_Struct(data->err, fcgi_stream_data, stream_data);
|
218
|
+
stream_data->req = Qnil; stream_data->stream = NULL;
|
219
|
+
}
|
220
|
+
|
221
|
+
data->in = data->out = data->err = Qnil;
|
149
222
|
FCGX_Finish_r(data->req);
|
150
|
-
|
223
|
+
|
151
224
|
return Qtrue;
|
152
225
|
}
|
153
226
|
|
154
227
|
#define CHECK_STREAM_ERROR(stream) {\
|
155
228
|
int err = FCGX_GetError(stream);\
|
229
|
+
extern int errno; \
|
156
230
|
if (err) {\
|
157
231
|
if (err > 0) {\
|
158
|
-
|
232
|
+
rb_raise(eFCGIStreamError, "unknown error (syscall error)");\
|
159
233
|
}\
|
160
234
|
else {\
|
161
235
|
switch (err) {\
|
@@ -179,13 +253,22 @@ static VALUE fcgi_finish(VALUE self)
|
|
179
253
|
}\
|
180
254
|
}
|
181
255
|
|
256
|
+
#define Data_Get_Stream(value, stream) do {\
|
257
|
+
fcgi_stream_data* _fsd;\
|
258
|
+
Data_Get_Struct(value, fcgi_stream_data, _fsd);\
|
259
|
+
if (NULL == (stream = _fsd->stream))\
|
260
|
+
rb_raise(eFCGIStreamError, "stream invalid as fastcgi request is already finished");\
|
261
|
+
} while (0)
|
262
|
+
|
182
263
|
static VALUE fcgi_stream_putc(VALUE self, VALUE ch)
|
183
264
|
{
|
184
265
|
FCGX_Stream *stream;
|
185
266
|
int c;
|
186
267
|
|
268
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
187
269
|
rb_secure(4);
|
188
|
-
|
270
|
+
#endif
|
271
|
+
Data_Get_Stream(self, stream);
|
189
272
|
if ((c = FCGX_PutChar(NUM2INT(ch), stream)) == EOF)
|
190
273
|
CHECK_STREAM_ERROR(stream);
|
191
274
|
return INT2NUM(c);
|
@@ -196,10 +279,12 @@ static VALUE fcgi_stream_write(VALUE self, VALUE str)
|
|
196
279
|
FCGX_Stream *stream;
|
197
280
|
int len;
|
198
281
|
|
282
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
199
283
|
rb_secure(4);
|
200
|
-
|
284
|
+
#endif
|
285
|
+
Data_Get_Stream(self, stream);
|
201
286
|
str = rb_obj_as_string(str);
|
202
|
-
len = FCGX_PutStr(
|
287
|
+
len = FCGX_PutStr(RSTRING_PTR(str), RSTRING_LEN(str), stream);
|
203
288
|
if (len == EOF) CHECK_STREAM_ERROR(stream);
|
204
289
|
return INT2NUM(len);
|
205
290
|
}
|
@@ -243,16 +328,19 @@ static VALUE fcgi_stream_printf(int argc, VALUE *argv, VALUE out)
|
|
243
328
|
|
244
329
|
static VALUE fcgi_stream_puts _((int, VALUE*, VALUE));
|
245
330
|
|
246
|
-
static VALUE fcgi_stream_puts_ary(VALUE ary, VALUE out)
|
331
|
+
static VALUE fcgi_stream_puts_ary(VALUE ary, VALUE out, int recur)
|
247
332
|
{
|
248
333
|
VALUE tmp;
|
249
334
|
int i;
|
250
335
|
|
251
|
-
|
252
|
-
tmp =
|
253
|
-
|
254
|
-
|
255
|
-
|
336
|
+
if (recur) {
|
337
|
+
tmp = rb_str_new2("[...]");
|
338
|
+
fcgi_stream_puts(1, &tmp, out);
|
339
|
+
return Qnil;
|
340
|
+
}
|
341
|
+
|
342
|
+
for (i=0; i<RARRAY_LEN(ary); i++) {
|
343
|
+
tmp = RARRAY_PTR(ary)[i];
|
256
344
|
fcgi_stream_puts(1, &tmp, out);
|
257
345
|
}
|
258
346
|
return Qnil;
|
@@ -274,7 +362,7 @@ static VALUE fcgi_stream_puts(int argc, VALUE *argv, VALUE out)
|
|
274
362
|
line = rb_str_new2("nil");
|
275
363
|
break;
|
276
364
|
case T_ARRAY:
|
277
|
-
|
365
|
+
rb_exec_recursive(fcgi_stream_puts_ary, argv[i], out);
|
278
366
|
continue;
|
279
367
|
default:
|
280
368
|
line = argv[i];
|
@@ -282,7 +370,7 @@ static VALUE fcgi_stream_puts(int argc, VALUE *argv, VALUE out)
|
|
282
370
|
}
|
283
371
|
line = rb_obj_as_string(line);
|
284
372
|
fcgi_stream_write(out, line);
|
285
|
-
if (
|
373
|
+
if (RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') {
|
286
374
|
fcgi_stream_write(out, rb_default_rs);
|
287
375
|
}
|
288
376
|
}
|
@@ -300,7 +388,7 @@ static VALUE fcgi_stream_flush(VALUE self)
|
|
300
388
|
{
|
301
389
|
FCGX_Stream *stream;
|
302
390
|
|
303
|
-
|
391
|
+
Data_Get_Stream(self, stream);
|
304
392
|
if (FCGX_FFlush(stream) == EOF)
|
305
393
|
CHECK_STREAM_ERROR(stream);
|
306
394
|
return Qnil;
|
@@ -311,7 +399,7 @@ static VALUE fcgi_stream_getc(VALUE self)
|
|
311
399
|
FCGX_Stream *stream;
|
312
400
|
int c;
|
313
401
|
|
314
|
-
|
402
|
+
Data_Get_Stream(self, stream);
|
315
403
|
if ((c = FCGX_GetChar(stream)) == EOF) {
|
316
404
|
CHECK_STREAM_ERROR(stream);
|
317
405
|
return Qnil;
|
@@ -326,27 +414,30 @@ static VALUE fcgi_stream_ungetc(VALUE self, VALUE ch)
|
|
326
414
|
FCGX_Stream *stream;
|
327
415
|
int c;
|
328
416
|
|
417
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
329
418
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
330
419
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
331
420
|
}
|
332
|
-
|
421
|
+
#endif
|
422
|
+
Data_Get_Stream(self, stream);
|
333
423
|
c = FCGX_UnGetChar(NUM2INT(ch), stream);
|
334
424
|
CHECK_STREAM_ERROR(stream);
|
335
425
|
return INT2NUM(c);
|
336
426
|
}
|
337
427
|
|
338
|
-
static VALUE fcgi_stream_gets(VALUE self)
|
339
|
-
{
|
428
|
+
static VALUE fcgi_stream_gets(VALUE self) {
|
340
429
|
FCGX_Stream *stream;
|
341
430
|
char buff[BUFSIZ];
|
342
|
-
VALUE str = rb_str_new(
|
431
|
+
VALUE str = rb_str_new(0,0);
|
343
432
|
OBJ_TAINT(str);
|
344
433
|
|
434
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
345
435
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
346
436
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
347
437
|
}
|
438
|
+
#endif
|
348
439
|
|
349
|
-
|
440
|
+
Data_Get_Stream(self, stream);
|
350
441
|
|
351
442
|
for (;;) {
|
352
443
|
if (FCGX_GetLine(buff, BUFSIZ, stream) == NULL) {
|
@@ -356,7 +447,7 @@ static VALUE fcgi_stream_gets(VALUE self)
|
|
356
447
|
rb_str_cat(str, buff, strlen(buff));
|
357
448
|
if (strchr(buff, '\n')) break;
|
358
449
|
}
|
359
|
-
if (
|
450
|
+
if (RSTRING_LEN(str) > 0)
|
360
451
|
return str;
|
361
452
|
else
|
362
453
|
return Qnil;
|
@@ -369,29 +460,36 @@ static VALUE fcgi_stream_read(int argc, VALUE *argv, VALUE self)
|
|
369
460
|
char *buff;
|
370
461
|
int n;
|
371
462
|
|
463
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
372
464
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
373
465
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
374
466
|
}
|
467
|
+
#endif
|
375
468
|
|
376
|
-
|
469
|
+
Data_Get_Stream(self, stream);
|
377
470
|
|
378
471
|
if (argc==0) {
|
379
472
|
buff = ALLOC_N(char, 16384);
|
380
473
|
n = FCGX_GetStr(buff, 16384, stream);
|
381
474
|
CHECK_STREAM_ERROR(stream);
|
382
|
-
if (n == 0)
|
475
|
+
if (n == 0) {
|
476
|
+
free(buff);
|
477
|
+
return Qnil;
|
478
|
+
}
|
383
479
|
str = rb_str_new(buff, n);
|
384
480
|
OBJ_TAINT(str);
|
385
|
-
|
481
|
+
|
386
482
|
while(!FCGX_HasSeenEOF(stream)) {
|
387
483
|
n = FCGX_GetStr(buff, 16384, stream);
|
388
484
|
CHECK_STREAM_ERROR(stream);
|
389
485
|
if (n > 0) {
|
390
486
|
rb_str_cat(str, buff, n);
|
391
487
|
} else {
|
488
|
+
free(buff);
|
392
489
|
return Qnil;
|
393
490
|
}
|
394
491
|
}
|
492
|
+
free(buff);
|
395
493
|
return str;
|
396
494
|
}
|
397
495
|
|
@@ -404,9 +502,11 @@ static VALUE fcgi_stream_read(int argc, VALUE *argv, VALUE self)
|
|
404
502
|
if (n > 0) {
|
405
503
|
str = rb_str_new(buff, n);
|
406
504
|
OBJ_TAINT(str);
|
505
|
+
free(buff);
|
407
506
|
return str;
|
408
507
|
}
|
409
508
|
else {
|
509
|
+
free(buff);
|
410
510
|
return Qnil;
|
411
511
|
}
|
412
512
|
}
|
@@ -415,10 +515,12 @@ static VALUE fcgi_stream_eof(VALUE self)
|
|
415
515
|
{
|
416
516
|
FCGX_Stream *stream;
|
417
517
|
|
518
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
418
519
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
419
520
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
420
521
|
}
|
421
|
-
|
522
|
+
#endif
|
523
|
+
Data_Get_Stream(self, stream);
|
422
524
|
return FCGX_HasSeenEOF(stream) ? Qtrue : Qfalse;
|
423
525
|
}
|
424
526
|
|
@@ -426,10 +528,12 @@ static VALUE fcgi_stream_close(VALUE self)
|
|
426
528
|
{
|
427
529
|
FCGX_Stream *stream;
|
428
530
|
|
531
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
429
532
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
430
533
|
rb_raise(rb_eSecurityError, "Insecure: can't close");
|
431
534
|
}
|
432
|
-
|
535
|
+
#endif
|
536
|
+
Data_Get_Stream(self, stream);
|
433
537
|
if (FCGX_FClose(stream) == EOF)
|
434
538
|
CHECK_STREAM_ERROR(stream);
|
435
539
|
return Qnil;
|
@@ -439,61 +543,68 @@ static VALUE fcgi_stream_closed(VALUE self)
|
|
439
543
|
{
|
440
544
|
FCGX_Stream *stream;
|
441
545
|
|
442
|
-
|
546
|
+
Data_Get_Stream(self, stream);
|
443
547
|
return stream->isClosed ? Qtrue : Qfalse;
|
444
548
|
}
|
445
549
|
|
446
550
|
static VALUE fcgi_stream_binmode(VALUE self)
|
447
551
|
{
|
552
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
448
553
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
449
554
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
450
555
|
}
|
556
|
+
#endif
|
451
557
|
return self;
|
452
558
|
}
|
453
559
|
|
454
560
|
static VALUE fcgi_stream_isatty(VALUE self)
|
455
561
|
{
|
562
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
456
563
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
457
564
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
458
565
|
}
|
566
|
+
#endif
|
459
567
|
return Qfalse;
|
460
568
|
}
|
461
569
|
|
462
570
|
static VALUE fcgi_stream_sync(VALUE self)
|
463
571
|
{
|
572
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
464
573
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
465
574
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
466
575
|
}
|
576
|
+
#endif
|
467
577
|
return Qfalse;
|
468
578
|
}
|
469
579
|
|
470
580
|
static VALUE fcgi_stream_setsync(VALUE self,VALUE sync)
|
471
581
|
{
|
582
|
+
#if !defined(RUBY_API_VERSION_MAJOR) || (RUBY_API_VERSION_MAJOR < 3)
|
472
583
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
|
473
584
|
rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
|
474
585
|
}
|
586
|
+
#endif
|
475
587
|
return Qfalse;
|
476
588
|
}
|
477
589
|
|
478
590
|
|
479
591
|
|
480
|
-
void Init_fcgi()
|
481
|
-
|
482
|
-
|
592
|
+
void Init_fcgi() {
|
593
|
+
|
483
594
|
FCGX_Init();
|
484
|
-
|
595
|
+
|
485
596
|
cFCGI = rb_define_class("FCGI", rb_cObject);
|
486
597
|
eFCGIError =rb_define_class_under(cFCGI, "Error", rb_eStandardError);
|
487
598
|
rb_define_singleton_method(cFCGI, "accept", fcgi_s_accept, 0);
|
488
599
|
rb_define_singleton_method(cFCGI, "each", fcgi_s_each, 0);
|
489
600
|
rb_define_singleton_method(cFCGI, "each_request", fcgi_s_each, 0);
|
490
601
|
rb_define_singleton_method(cFCGI, "is_cgi?", fcgi_s_iscgi, 0);
|
491
|
-
rb_define_method(cFCGI, "in",
|
602
|
+
rb_define_method(cFCGI, "in", fcgi_in, 0);
|
492
603
|
rb_define_method(cFCGI, "out", fcgi_out, 0);
|
493
604
|
rb_define_method(cFCGI, "err", fcgi_err, 0);
|
494
605
|
rb_define_method(cFCGI, "env", fcgi_env, 0);
|
495
606
|
rb_define_method(cFCGI, "finish", fcgi_finish, 0);
|
496
|
-
|
607
|
+
|
497
608
|
cFCGIStream = rb_define_class_under(cFCGI, "Stream", rb_cObject);
|
498
609
|
eFCGIStreamError =rb_define_class_under(cFCGIStream, "Error", rb_eStandardError);
|
499
610
|
eFCGIStreamUnsupportedVersionError =
|
data/fcgi.gemspec
CHANGED
@@ -1,16 +1,34 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = %q{fcgi}
|
3
|
-
s.version = "0.
|
4
|
-
s.
|
5
|
-
|
6
|
-
s.
|
7
|
-
s.
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
s.version = "0.9.2.2"
|
4
|
+
s.license = "MIT"
|
5
|
+
|
6
|
+
s.authors = [%q{mva}]
|
7
|
+
s.date = %q{2022-10-17}
|
8
|
+
s.description = %q{FastCGI is a language independent, scalable, open extension to CGI that provides high performance without the limitations of server specific APIs. This version aims to be compatible with both 1.8.x and 1.9.x versions of Ruby, and also will be ported to 2.0.x. It has been hacked to work with Ruby 3.0.x.}
|
9
|
+
s.email = %q{mva@mva.name}
|
10
|
+
s.extensions = [%q{ext/fcgi/extconf.rb}]
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"LICENSE",
|
13
|
+
"README.rdoc",
|
14
|
+
"README.signals"
|
15
|
+
]
|
16
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
17
|
+
s.files = [
|
18
|
+
"VERSION",
|
19
|
+
"ext/fcgi/MANIFEST",
|
20
|
+
"ext/fcgi/Makefile",
|
21
|
+
"ext/fcgi/extconf.rb",
|
22
|
+
"ext/fcgi/fcgi.c",
|
23
|
+
"lib/fcgi.rb",
|
24
|
+
"fcgi.gemspec"
|
25
|
+
]
|
26
|
+
s.test_files = [
|
27
|
+
"test/helper.rb",
|
28
|
+
"test/test_fcgi.rb"
|
29
|
+
]
|
30
|
+
s.homepage = %q{http://github.com/alphallc/ruby-fcgi-ng}
|
31
|
+
s.require_paths = [%q{lib}]
|
32
|
+
s.summary = %q{FastCGI library for Ruby.}
|
16
33
|
end
|
34
|
+
|
data/lib/fcgi.rb
CHANGED
@@ -1,25 +1,30 @@
|
|
1
1
|
=begin
|
2
2
|
|
3
|
-
fcgi.rb 0.
|
3
|
+
fcgi.rb 0.9.2 - fcgi.so compatible pure-ruby FastCGI library
|
4
4
|
|
5
5
|
fastcgi.rb Copyright (C) 2001 Eli Green
|
6
6
|
fcgi.rb Copyright (C) 2002-2003 MoonWolf <moonwolf@moonwolf.com>
|
7
7
|
fcgi.rb Copyright (C) 2004 Minero Aoki
|
8
|
+
fcgi.rb Copyright (C) 2011 saks and Julik Tarkhanov
|
9
|
+
fcgi.rb Copyright (C) 2012-2013 mva
|
8
10
|
|
9
11
|
=end
|
10
12
|
trap('SIGTERM') { exit }
|
11
13
|
trap('SIGPIPE','IGNORE')
|
12
14
|
|
13
15
|
begin
|
14
|
-
raise LoadError if
|
16
|
+
raise LoadError if ENV["USE_PURE_RUBY_FCGI"]
|
15
17
|
require "fcgi.so"
|
16
|
-
rescue LoadError
|
18
|
+
rescue LoadError # Load the pure ruby version instead
|
19
|
+
# At this point we do have STDERR so put it to some good use
|
20
|
+
$stderr.puts "Your FCGI gem does not contain the FCGI shared library, running pure ruby instead"
|
21
|
+
|
17
22
|
require 'socket'
|
18
23
|
require 'stringio'
|
19
24
|
|
20
25
|
class FCGI
|
21
26
|
|
22
|
-
def self
|
27
|
+
def self.is_cgi?
|
23
28
|
begin
|
24
29
|
s = Socket.for_fd($stdin.fileno)
|
25
30
|
s.getpeername
|
@@ -31,21 +36,21 @@ rescue LoadError
|
|
31
36
|
end
|
32
37
|
end
|
33
38
|
|
34
|
-
def self
|
39
|
+
def self.each(&block)
|
35
40
|
f = default_connection()
|
36
41
|
Server.new(f).each_request(&block)
|
37
42
|
ensure
|
38
43
|
f.close if f
|
39
44
|
end
|
40
45
|
|
41
|
-
def self
|
46
|
+
def self.each_request(&block)
|
42
47
|
f = default_connection()
|
43
48
|
Server.new(f).each_request(&block)
|
44
49
|
ensure
|
45
50
|
f.close if f
|
46
51
|
end
|
47
52
|
|
48
|
-
def self
|
53
|
+
def self.default_connection
|
49
54
|
::Socket.for_fd($stdin.fileno)
|
50
55
|
end
|
51
56
|
|
@@ -108,9 +113,9 @@ rescue LoadError
|
|
108
113
|
exit 0 if graceful
|
109
114
|
end
|
110
115
|
end
|
111
|
-
|
116
|
+
|
112
117
|
def session
|
113
|
-
sock,
|
118
|
+
sock, _ = *@server.accept
|
114
119
|
return unless sock
|
115
120
|
fsock = FastCGISocket.new(sock)
|
116
121
|
req = next_request(fsock)
|
@@ -191,7 +196,7 @@ rescue LoadError
|
|
191
196
|
def read_record
|
192
197
|
header = @socket.read(Record::HEADER_LENGTH) or return nil
|
193
198
|
return nil unless header.size == Record::HEADER_LENGTH
|
194
|
-
|
199
|
+
_, type, reqid, clen, padlen, _ = *Record.parse_header(header)
|
195
200
|
Record.class_for(type).parse(reqid, read_record_body(clen, padlen))
|
196
201
|
end
|
197
202
|
|
@@ -306,11 +311,11 @@ rescue LoadError
|
|
306
311
|
HEADER_FORMAT = 'CCnnCC'
|
307
312
|
HEADER_LENGTH = 8
|
308
313
|
|
309
|
-
def self
|
314
|
+
def self.parse_header(buf)
|
310
315
|
return *buf.unpack(HEADER_FORMAT)
|
311
316
|
end
|
312
317
|
|
313
|
-
def self
|
318
|
+
def self.class_for(type)
|
314
319
|
RECORD_CLASS[type]
|
315
320
|
end
|
316
321
|
|
@@ -351,7 +356,7 @@ rescue LoadError
|
|
351
356
|
BODY_FORMAT = 'nCC5'
|
352
357
|
|
353
358
|
def BeginRequestRecord.parse(id, body)
|
354
|
-
role, flags, *
|
359
|
+
role, flags, *_ = *body.unpack(BODY_FORMAT)
|
355
360
|
new(id, role, flags)
|
356
361
|
end
|
357
362
|
|
@@ -363,6 +368,10 @@ rescue LoadError
|
|
363
368
|
|
364
369
|
attr_reader :role
|
365
370
|
attr_reader :flags
|
371
|
+
|
372
|
+
def make_body
|
373
|
+
[@role, @flags, 0, 0, 0, 0, 0].pack(BODY_FORMAT)
|
374
|
+
end
|
366
375
|
end
|
367
376
|
|
368
377
|
class AbortRequestRecord < Record
|
@@ -381,7 +390,7 @@ rescue LoadError
|
|
381
390
|
# uint8_t reserved[3];
|
382
391
|
BODY_FORMAT = 'NCC3'
|
383
392
|
|
384
|
-
def self
|
393
|
+
def self.parse(id, body)
|
385
394
|
appstatus, protostatus, *reserved = *body.unpack(BODY_FORMAT)
|
386
395
|
new(id, appstatus, protostatus)
|
387
396
|
end
|
@@ -407,7 +416,7 @@ rescue LoadError
|
|
407
416
|
# uint8_t reserved[7];
|
408
417
|
BODY_FORMAT = 'CC7'
|
409
418
|
|
410
|
-
def self
|
419
|
+
def self.parse(id, body)
|
411
420
|
type, *reserved = *body.unpack(BODY_FORMAT)
|
412
421
|
new(id, type)
|
413
422
|
end
|
@@ -427,11 +436,11 @@ rescue LoadError
|
|
427
436
|
end
|
428
437
|
|
429
438
|
class ValuesRecord < Record
|
430
|
-
def self
|
439
|
+
def self.parse(id, body)
|
431
440
|
new(id, parse_values(body))
|
432
441
|
end
|
433
442
|
|
434
|
-
def self
|
443
|
+
def self.parse_values(buf)
|
435
444
|
result = {}
|
436
445
|
until buf.empty?
|
437
446
|
name, value = *read_pair(buf)
|
@@ -439,17 +448,29 @@ rescue LoadError
|
|
439
448
|
end
|
440
449
|
result
|
441
450
|
end
|
442
|
-
|
443
|
-
def self
|
451
|
+
|
452
|
+
def self.read_pair(buf)
|
444
453
|
nlen = read_length(buf)
|
445
454
|
vlen = read_length(buf)
|
446
|
-
|
455
|
+
[buf.slice!(0, nlen), buf.slice!(0, vlen)]
|
447
456
|
end
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
457
|
+
|
458
|
+
|
459
|
+
if "".respond_to?(:bytes) # Ruby 1.9 string semantics
|
460
|
+
def self.read_length(buf)
|
461
|
+
if buf[0].bytes.first >> 7 == 0
|
462
|
+
buf.slice!(0,1)[0].bytes.first
|
463
|
+
else
|
464
|
+
buf.slice!(0,4).unpack('N')[0] & ((1<<31) - 1)
|
465
|
+
end
|
466
|
+
end
|
467
|
+
else # Ruby 1.8 string
|
468
|
+
def self.read_length(buf)
|
469
|
+
if buf[0] >> 7 == 0
|
470
|
+
buf.slice!(0,1)[0].bytes.first
|
471
|
+
else
|
472
|
+
buf.slice!(0,4).unpack('N')[0] & ((1<<31) - 1)
|
473
|
+
end
|
453
474
|
end
|
454
475
|
end
|
455
476
|
|
@@ -498,7 +519,7 @@ rescue LoadError
|
|
498
519
|
end
|
499
520
|
|
500
521
|
class GenericDataRecord < Record
|
501
|
-
def self
|
522
|
+
def self.parse(id, body)
|
502
523
|
new(id, body)
|
503
524
|
end
|
504
525
|
|
@@ -516,7 +537,11 @@ rescue LoadError
|
|
516
537
|
private
|
517
538
|
|
518
539
|
def make_body
|
519
|
-
@flagment
|
540
|
+
if @flagment.respond_to? 'force_encoding' then
|
541
|
+
return @flagment.dup.force_encoding('BINARY')
|
542
|
+
else
|
543
|
+
return @flagment
|
544
|
+
end
|
520
545
|
end
|
521
546
|
end
|
522
547
|
|
@@ -526,6 +551,12 @@ rescue LoadError
|
|
526
551
|
end
|
527
552
|
end
|
528
553
|
|
554
|
+
class StdoutDataRecord < GenericDataRecord
|
555
|
+
def initialize(id, flagment)
|
556
|
+
super FCGI_STDOUT, id, flagment
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
529
560
|
class DataRecord < GenericDataRecord
|
530
561
|
def initialize(id, flagment)
|
531
562
|
super FCGI_DATA, id, flagment
|
@@ -540,7 +571,9 @@ rescue LoadError
|
|
540
571
|
FCGI_ABORT_REQUEST => AbortRequestRecord,
|
541
572
|
FCGI_PARAMS => ParamsRecord,
|
542
573
|
FCGI_STDIN => StdinDataRecord,
|
543
|
-
FCGI_DATA => DataRecord
|
574
|
+
FCGI_DATA => DataRecord,
|
575
|
+
FCGI_STDOUT => StdoutDataRecord,
|
576
|
+
FCGI_END_REQUEST => EndRequestRecord
|
544
577
|
}
|
545
578
|
end
|
546
579
|
|
@@ -552,13 +585,13 @@ end # begin
|
|
552
585
|
# are defined within module 'CGI', even if you have subclassed it
|
553
586
|
|
554
587
|
class FCGI
|
555
|
-
def self
|
588
|
+
def self.each_cgi(*args)
|
556
589
|
require 'cgi'
|
557
|
-
|
590
|
+
|
558
591
|
eval(<<-EOS,TOPLEVEL_BINDING)
|
559
592
|
class CGI
|
560
593
|
public :env_table
|
561
|
-
def self
|
594
|
+
def self.remove_params
|
562
595
|
if (const_defined?(:CGI_PARAMS))
|
563
596
|
remove_const(:CGI_PARAMS)
|
564
597
|
remove_const(:CGI_COOKIES)
|
@@ -589,18 +622,18 @@ class FCGI
|
|
589
622
|
end # FCGI::CGI class
|
590
623
|
end # FCGI class
|
591
624
|
EOS
|
592
|
-
|
625
|
+
|
593
626
|
if FCGI::is_cgi?
|
594
627
|
yield ::CGI.new(*args)
|
595
628
|
else
|
596
|
-
|
597
|
-
|
629
|
+
FCGI::each do |request|
|
630
|
+
|
598
631
|
$stdout, $stderr = request.out, request.err
|
599
632
|
|
600
633
|
yield CGI.new(request, *args)
|
601
|
-
|
634
|
+
|
602
635
|
request.finish
|
603
|
-
|
636
|
+
end
|
604
637
|
end
|
605
638
|
end
|
606
639
|
end
|
data/test/helper.rb
ADDED
data/test/test_fcgi.rb
ADDED
metadata
CHANGED
@@ -1,44 +1,64 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: "0.8"
|
3
|
-
specification_version: 1
|
1
|
+
--- !ruby/object:Gem::Specification
|
4
2
|
name: fcgi
|
5
|
-
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2004-10-21
|
8
|
-
summary: FastCGI ruby binding.
|
9
|
-
require_paths:
|
10
|
-
- "."
|
11
|
-
author: "Network Applied Communication Laboratory, Inc., MoonWolf, Eli Green, Minero Aoki"
|
12
|
-
email: moonwolf@moonwolf.com
|
13
|
-
homepage: http://rwiki.moonwolf.com/rw-cgi.cgi?cmd=view;name=fcgi
|
14
|
-
rubyforge_project:
|
15
|
-
description:
|
16
|
-
autorequire: fcgi
|
17
|
-
default_executable:
|
18
|
-
bindir: bin
|
19
|
-
has_rdoc: true
|
20
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
21
|
-
requirements:
|
22
|
-
-
|
23
|
-
- ">"
|
24
|
-
- !ruby/object:Gem::Version
|
25
|
-
version: 0.0.0
|
26
|
-
version:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.2.2
|
27
5
|
platform: ruby
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
6
|
+
authors:
|
7
|
+
- mva
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-10-17 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: FastCGI is a language independent, scalable, open extension to CGI that
|
14
|
+
provides high performance without the limitations of server specific APIs. This
|
15
|
+
version aims to be compatible with both 1.8.x and 1.9.x versions of Ruby, and also
|
16
|
+
will be ported to 2.0.x. It has been hacked to work with Ruby 3.0.x.
|
17
|
+
email: mva@mva.name
|
40
18
|
executables: []
|
41
|
-
extensions:
|
42
|
-
|
19
|
+
extensions:
|
20
|
+
- ext/fcgi/extconf.rb
|
21
|
+
extra_rdoc_files:
|
22
|
+
- LICENSE
|
23
|
+
- README.rdoc
|
24
|
+
- README.signals
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- README.signals
|
29
|
+
- VERSION
|
30
|
+
- ext/fcgi/MANIFEST
|
31
|
+
- ext/fcgi/Makefile
|
32
|
+
- ext/fcgi/extconf.rb
|
33
|
+
- ext/fcgi/fcgi.c
|
34
|
+
- fcgi.gemspec
|
35
|
+
- lib/fcgi.rb
|
36
|
+
- test/helper.rb
|
37
|
+
- test/test_fcgi.rb
|
38
|
+
homepage: http://github.com/alphallc/ruby-fcgi-ng
|
39
|
+
licenses:
|
40
|
+
- MIT
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options:
|
44
|
+
- "--charset=UTF-8"
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
43
57
|
requirements: []
|
44
|
-
|
58
|
+
rubygems_version: 3.3.8
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: FastCGI library for Ruby.
|
62
|
+
test_files:
|
63
|
+
- test/helper.rb
|
64
|
+
- test/test_fcgi.rb
|