rhebok 0.2.3 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changes +4 -0
- data/README.md +1 -1
- data/ext/rhebok/rhebok.c +58 -6
- data/lib/rack/handler/rhebok.rb +59 -15
- data/lib/rhebok/buffered.rb +46 -0
- data/lib/rhebok/version.rb +1 -1
- data/test/spec_06_curl.rb +46 -0
- data/test/testrequest.rb +34 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 454acd81875129e8a6b70d0322faeded5a9b12ab
|
4
|
+
data.tar.gz: c2e879260c7505697b312f7ce07b4b91e137ccbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0233481756e663f30ca815c7320e2bfc0bc88636a2577451dc8717c2e938c76fd68a71eec61c36da06e95d8f7ad985c8cb36fd566f6d92e6fc98191c0ff21066
|
7
|
+
data.tar.gz: a3297edf4bd16b7e331e7c068bb2bb0c1be641d145b9fca70c52b06a68599ce48488ea6d19b997eea69ece63aa46bb18be6ad1c5f625fd8b0a0bad4de993a78e
|
data/Changes
CHANGED
data/README.md
CHANGED
@@ -9,7 +9,7 @@ Rhebok supports following features.
|
|
9
9
|
- uses writev(2) for output responses
|
10
10
|
- prefork and graceful shutdown using [prefork_engine](https://rubygems.org/gems/prefork_engine)
|
11
11
|
- hot deploy using [start_server](https://metacpan.org/release/Server-Starter) ([here](https://github.com/lestrrat/go-server-starter) is golang version by lestrrat-san)
|
12
|
-
-
|
12
|
+
- supports HTTP/1.1. But does not have Keepalive
|
13
13
|
- supports OobGC
|
14
14
|
|
15
15
|
This server is suitable for running HTTP application servers behind a reverse proxy like nginx.
|
data/ext/rhebok/rhebok.c
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
#define MAX_HEADER_NAME_LEN 1024
|
19
19
|
#define MAX_HEADERS 128
|
20
20
|
#define BAD_REQUEST "HTTP/1.0 400 Bad Request\r\nConnection: close\r\n\r\n400 Bad Request\r\n"
|
21
|
+
#define READ_BUF 16384
|
21
22
|
#define TOU(ch) (('a' <= ch && ch <= 'z') ? ch - ('a' - 'A') : ch)
|
22
23
|
|
23
24
|
static const char *DoW[] = {
|
@@ -26,6 +27,8 @@ static const char *DoW[] = {
|
|
26
27
|
static const char *MoY[] = {
|
27
28
|
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
|
28
29
|
};
|
30
|
+
static const char xdigit[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
31
|
+
|
29
32
|
|
30
33
|
/* stolen from HTTP::Status and Feersum */
|
31
34
|
/* Unmarked codes are from RFC 2616 */
|
@@ -377,6 +380,24 @@ void str_i(char * dst, int * dst_len, int src, int fig) {
|
|
377
380
|
*dst_len += fig;
|
378
381
|
}
|
379
382
|
|
383
|
+
static
|
384
|
+
int _chunked_header(char *buf, ssize_t len) {
|
385
|
+
int dlen = 0, i;
|
386
|
+
ssize_t l = len;
|
387
|
+
while ( l > 0 ) {
|
388
|
+
dlen++;
|
389
|
+
l /= 16;
|
390
|
+
}
|
391
|
+
i = dlen;
|
392
|
+
buf[i++] = 13;
|
393
|
+
buf[i++] = 10;
|
394
|
+
while ( len > 0 ) {
|
395
|
+
buf[--dlen] = xdigit[len % 16];
|
396
|
+
len /= 16;
|
397
|
+
}
|
398
|
+
return i;
|
399
|
+
}
|
400
|
+
|
380
401
|
static
|
381
402
|
int _date_line(char * date_line) {
|
382
403
|
struct tm gtm;
|
@@ -436,7 +457,7 @@ int _parse_http_request(char *buf, ssize_t buf_len, VALUE env) {
|
|
436
457
|
rb_hash_aset(env, request_method_key, rb_str_new(method,method_len));
|
437
458
|
rb_hash_aset(env, request_uri_key, rb_str_new(path, path_len));
|
438
459
|
rb_hash_aset(env, script_name_key, vacant_string_val);
|
439
|
-
rb_hash_aset(env, server_protocol_key, (minor_version
|
460
|
+
rb_hash_aset(env, server_protocol_key, (minor_version == 1) ? http11_val : http10_val);
|
440
461
|
|
441
462
|
/* PATH_INFO QUERY_STRING */
|
442
463
|
path_len = find_ch(path, path_len, '#'); /* strip off all text after # after storing request_uri */
|
@@ -582,6 +603,8 @@ VALUE rhe_read_timeout(VALUE self, VALUE filenov, VALUE rbuf, VALUE lenv, VALUE
|
|
582
603
|
timeout = NUM2DBL(timeoutv);
|
583
604
|
offset = NUM2LONG(offsetv);
|
584
605
|
len = NUM2LONG(lenv);
|
606
|
+
if ( len > READ_BUF )
|
607
|
+
len = READ_BUF;
|
585
608
|
d = ALLOC_N(char, len);
|
586
609
|
rv = _read_timeout(fileno, timeout, &d[offset], len);
|
587
610
|
if ( rv > 0 ) {
|
@@ -665,7 +688,7 @@ VALUE rhe_close(VALUE self, VALUE fileno) {
|
|
665
688
|
}
|
666
689
|
|
667
690
|
static
|
668
|
-
VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status_codev, VALUE headers, VALUE body) {
|
691
|
+
VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status_codev, VALUE headers, VALUE body, VALUE use_chunkedv) {
|
669
692
|
ssize_t hlen = 0;
|
670
693
|
ssize_t blen = 0;
|
671
694
|
|
@@ -687,12 +710,15 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
687
710
|
const char * message;
|
688
711
|
|
689
712
|
const char * s;
|
690
|
-
char* d;
|
713
|
+
char * d;
|
691
714
|
ssize_t n;
|
692
715
|
|
716
|
+
char * chunked_header_buf;
|
717
|
+
|
693
718
|
int fileno = NUM2INT(filenov);
|
694
719
|
double timeout = NUM2DBL(timeoutv);
|
695
720
|
int status_code = NUM2INT(status_codev);
|
721
|
+
int use_chunked = NUM2INT(use_chunkedv);
|
696
722
|
|
697
723
|
harr = rb_ary_new();
|
698
724
|
RB_GC_GUARD(harr);
|
@@ -700,6 +726,9 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
700
726
|
hlen = RARRAY_LEN(harr);
|
701
727
|
blen = RARRAY_LEN(body);
|
702
728
|
iovcnt = 10 + (hlen * 2) + blen;
|
729
|
+
if ( use_chunked )
|
730
|
+
iovcnt += blen*2;
|
731
|
+
chunked_header_buf = ALLOC_N(char, 32 * blen);
|
703
732
|
|
704
733
|
{
|
705
734
|
struct iovec v[iovcnt]; // Needs C99 compiler
|
@@ -713,7 +742,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
713
742
|
status_line[i++] = '/';
|
714
743
|
status_line[i++] = '1';
|
715
744
|
status_line[i++] = '.';
|
716
|
-
status_line[i++] = '
|
745
|
+
status_line[i++] = '1';
|
717
746
|
status_line[i++] = ' ';
|
718
747
|
str_i(status_line,&i,status_code,3);
|
719
748
|
status_line[i++] = ' ';
|
@@ -790,15 +819,38 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
790
819
|
v[1].iov_base = date_line;
|
791
820
|
}
|
792
821
|
|
822
|
+
if ( use_chunked ) {
|
823
|
+
v[iovcnt].iov_base = "Transfer-Encoding: chunked\r\n";
|
824
|
+
v[iovcnt].iov_len = sizeof("Transfer-Encoding: chunked\r\n") - 1;
|
825
|
+
iovcnt++;
|
826
|
+
}
|
827
|
+
|
793
828
|
v[iovcnt].iov_base = "Connection: close\r\n\r\n";
|
794
829
|
v[iovcnt].iov_len = sizeof("Connection: close\r\n\r\n") - 1;
|
795
830
|
iovcnt++;
|
796
831
|
|
832
|
+
ssize_t chb_offset = 0;
|
797
833
|
for ( i=0; i<blen; i++) {
|
798
834
|
val_obj = rb_ary_entry(body, i);
|
835
|
+
if ( use_chunked ) {
|
836
|
+
v[iovcnt].iov_len = _chunked_header(&chunked_header_buf[chb_offset],RSTRING_LEN(val_obj));
|
837
|
+
v[iovcnt].iov_base = &chunked_header_buf[chb_offset];
|
838
|
+
chb_offset += v[iovcnt].iov_len;
|
839
|
+
iovcnt++;
|
840
|
+
}
|
799
841
|
v[iovcnt].iov_base = RSTRING_PTR(val_obj);
|
800
842
|
v[iovcnt].iov_len = RSTRING_LEN(val_obj);
|
801
843
|
iovcnt++;
|
844
|
+
if ( use_chunked ) {
|
845
|
+
v[iovcnt].iov_base = "\r\n";
|
846
|
+
v[iovcnt].iov_len = sizeof("\r\n") -1;
|
847
|
+
iovcnt++;
|
848
|
+
}
|
849
|
+
}
|
850
|
+
if ( use_chunked ) {
|
851
|
+
v[iovcnt].iov_base = "0\r\n\r\n";
|
852
|
+
v[iovcnt].iov_len = sizeof("0\r\n\r\n") - 1;
|
853
|
+
iovcnt++;
|
802
854
|
}
|
803
855
|
|
804
856
|
vec_offset = 0;
|
@@ -824,7 +876,7 @@ VALUE rhe_write_response(VALUE self, VALUE filenov, VALUE timeoutv, VALUE status
|
|
824
876
|
}
|
825
877
|
}
|
826
878
|
}
|
827
|
-
|
879
|
+
xfree(chunked_header_buf);
|
828
880
|
if ( rv < 0 ) {
|
829
881
|
return Qnil;
|
830
882
|
}
|
@@ -880,5 +932,5 @@ void Init_rhebok()
|
|
880
932
|
rb_define_module_function(cRhebok, "write_timeout", rhe_write_timeout, 5);
|
881
933
|
rb_define_module_function(cRhebok, "write_all", rhe_write_all, 4);
|
882
934
|
rb_define_module_function(cRhebok, "close_rack", rhe_close, 1);
|
883
|
-
rb_define_module_function(cRhebok, "write_response", rhe_write_response,
|
935
|
+
rb_define_module_function(cRhebok, "write_response", rhe_write_response, 6);
|
884
936
|
}
|
data/lib/rack/handler/rhebok.rb
CHANGED
@@ -11,6 +11,7 @@ require 'io/nonblock'
|
|
11
11
|
require 'prefork_engine'
|
12
12
|
require 'rhebok'
|
13
13
|
require 'rhebok/config'
|
14
|
+
require 'rhebok/buffered'
|
14
15
|
|
15
16
|
$RACK_HANDLER_RHEBOK_GCTOOL = true
|
16
17
|
begin
|
@@ -238,16 +239,15 @@ module Rack
|
|
238
239
|
begin
|
239
240
|
proc_req_count += 1
|
240
241
|
@can_exit = false
|
242
|
+
# expect
|
243
|
+
if env.key?("HTTP_EXPECT") && env.delete("HTTP_EXPECT") == "100-continue"
|
244
|
+
::Rhebok.write_all(connection, "HTTP/1.1 100 Continue\015\012\015\012", 0, @options[:Timeout])
|
245
|
+
end
|
241
246
|
# handle request
|
247
|
+
is_chunked = env.key?("HTTP_TRANSFER_ENCODING") && env.delete("HTTP_TRANSFER_ENCODING") == 'chunked'
|
242
248
|
if env.key?("CONTENT_LENGTH") && env["CONTENT_LENGTH"].to_i > 0
|
243
249
|
cl = env["CONTENT_LENGTH"].to_i
|
244
|
-
|
245
|
-
buffer = Tempfile.open('r')
|
246
|
-
buffer.binmode
|
247
|
-
buffer.set_encoding('BINARY')
|
248
|
-
else
|
249
|
-
buffer = StringIO.new("").set_encoding('BINARY')
|
250
|
-
end
|
250
|
+
buffer = ::Rhebok::Buffered.new(cl,MAX_MEMORY_BUFFER_SIZE)
|
251
251
|
while cl > 0
|
252
252
|
chunk = ""
|
253
253
|
if buf.bytesize > 0
|
@@ -259,30 +259,74 @@ module Rack
|
|
259
259
|
return
|
260
260
|
end
|
261
261
|
end
|
262
|
-
buffer
|
262
|
+
buffer.print(chunk)
|
263
263
|
cl -= chunk.bytesize
|
264
264
|
end
|
265
|
-
buffer.rewind
|
266
|
-
|
265
|
+
env["rack.input"] = buffer.rewind
|
266
|
+
elsif is_chunked
|
267
|
+
buffer = ::Rhebok::Buffered.new(0,MAX_MEMORY_BUFFER_SIZE)
|
268
|
+
chunked_buffer = '';
|
269
|
+
complete = false
|
270
|
+
while !complete
|
271
|
+
chunk = ""
|
272
|
+
if buf.bytesize > 0
|
273
|
+
chunk = buf
|
274
|
+
buf = ""
|
275
|
+
else
|
276
|
+
readed = ::Rhebok.read_timeout(connection, chunk, 16384, 0, @options[:Timeout])
|
277
|
+
if readed == nil
|
278
|
+
return
|
279
|
+
end
|
280
|
+
end
|
281
|
+
chunked_buffer << chunk
|
282
|
+
while chunked_buffer.sub!(/^(([0-9a-fA-F]+).*\015\012)/,"") != nil
|
283
|
+
trailer = $1
|
284
|
+
chunked_len = $2.hex
|
285
|
+
if chunked_len == 0
|
286
|
+
complete = true
|
287
|
+
break
|
288
|
+
elsif chunked_buffer.bytesize < chunked_len + 2
|
289
|
+
chunked_buffer = trailer + chunked_buffer
|
290
|
+
break
|
291
|
+
end
|
292
|
+
buffer.print(chunked_buffer.byteslice(0,chunked_len))
|
293
|
+
chunked_buffer = chunked_buffer.byteslice(chunked_len,chunked_buffer.bytesize-chunked_len)
|
294
|
+
chunked_buffer.sub!(/^\015\012/,"")
|
295
|
+
end
|
296
|
+
break if complete
|
297
|
+
end
|
298
|
+
env["CONTENT_LENGTH"] = buffer.size.to_s
|
299
|
+
env["rack.input"] = buffer.rewind
|
267
300
|
end
|
268
301
|
|
269
302
|
status_code, headers, body = app.call(env)
|
303
|
+
|
304
|
+
use_chunked = env["SERVER_PROTOCOL"] != "HTTP/1.1" ||
|
305
|
+
headers.key?("Transfer-Encoding") ||
|
306
|
+
headers.key?("Content-Length") ? false : true
|
307
|
+
|
270
308
|
if body.instance_of?(Array)
|
271
|
-
::Rhebok.write_response(connection, @options[:Timeout], status_code.to_i, headers, body)
|
309
|
+
::Rhebok.write_response(connection, @options[:Timeout], status_code.to_i, headers, body, use_chunked ? 1 : 0)
|
272
310
|
else
|
273
|
-
::Rhebok.write_response(connection, @options[:Timeout], status_code.to_i, headers, [])
|
311
|
+
::Rhebok.write_response(connection, @options[:Timeout], status_code.to_i, headers, [], use_chunked ? 1 : 0)
|
274
312
|
body.each do |part|
|
275
|
-
ret =
|
313
|
+
ret = nil
|
314
|
+
if use_chunked
|
315
|
+
ret = ::Rhebok.write_all(connection, part.bytesize.to_s(16) + "\015\012" + part + "\015\012", 0, @options[:Timeout])
|
316
|
+
else
|
317
|
+
ret = ::Rhebok.write_all(connection, part, 0, @options[:Timeout])
|
318
|
+
end
|
276
319
|
if ret == nil
|
277
320
|
break
|
278
321
|
end
|
279
322
|
end #body.each
|
323
|
+
::Rhebok.write_all(connection, "0\015\012\015\012", 0, @options[:Timeout]) if use_chunked
|
280
324
|
body.respond_to?(:close) and body.close
|
281
325
|
end
|
282
326
|
#p [env,status_code,headers,body]
|
283
327
|
ensure
|
284
|
-
if buffer
|
285
|
-
buffer.close
|
328
|
+
if buffer != nil
|
329
|
+
buffer.close
|
286
330
|
end
|
287
331
|
::Rhebok.close_rack(connection)
|
288
332
|
# out of band gc
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
class Rhebok
|
5
|
+
class Buffered
|
6
|
+
def initialize(length=0,memory_max=1048576)
|
7
|
+
@length = length
|
8
|
+
@memory_max = memory_max
|
9
|
+
@size = 0
|
10
|
+
if length > memory_max
|
11
|
+
@buffer = Tempfile.open('r')
|
12
|
+
@buffer.binmode
|
13
|
+
@buffer.set_encoding('BINARY')
|
14
|
+
else
|
15
|
+
@buffer = StringIO.new("").set_encoding('BINARY')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def print(buf)
|
20
|
+
if @size + buf.bytesize > @memory_max && @buffer.instance_of?(StringIO)
|
21
|
+
new_buffer = Tempfile.open('r')
|
22
|
+
new_buffer.binmode
|
23
|
+
new_buffer.set_encoding('BINARY')
|
24
|
+
new_buffer << @buffer.string
|
25
|
+
@buffer = new_buffer
|
26
|
+
end
|
27
|
+
@buffer << buf
|
28
|
+
@size += buf.bytesize
|
29
|
+
end
|
30
|
+
|
31
|
+
def size
|
32
|
+
@size
|
33
|
+
end
|
34
|
+
|
35
|
+
def rewind
|
36
|
+
@buffer.rewind
|
37
|
+
@buffer
|
38
|
+
end
|
39
|
+
|
40
|
+
def close
|
41
|
+
if @buffer.instance_of?(Tempfile)
|
42
|
+
@buffer.close!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/rhebok/version.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require File.expand_path('../testrequest', __FILE__)
|
3
|
+
require 'timeout'
|
4
|
+
require 'socket'
|
5
|
+
require 'rack/handler/rhebok'
|
6
|
+
|
7
|
+
describe Rhebok do
|
8
|
+
extend TestRequest::Helpers
|
9
|
+
begin
|
10
|
+
|
11
|
+
@host = '127.0.0.1'
|
12
|
+
@port = 9202
|
13
|
+
#@app = Rack::Lint.new(TestRequest.new) Lint requires Content-Length or Transfer-Eoncoding
|
14
|
+
@app = TestRequest.new
|
15
|
+
@pid = fork
|
16
|
+
if @pid == nil
|
17
|
+
#child
|
18
|
+
Rack::Handler::Rhebok.run(@app, :Host=>'127.0.0.1', :Port=>9202, :MaxWorkers=>1,
|
19
|
+
:BeforeFork => proc { ENV["TEST_FOO"] = "FOO" },
|
20
|
+
:AfterFork => proc { ENV["TEST_BAR"] = "BAR" },
|
21
|
+
)
|
22
|
+
exit!(true)
|
23
|
+
end
|
24
|
+
|
25
|
+
command = 'curl --stderr - -sv -X POST -T "'+File.expand_path('../testrequest.rb', __FILE__)+'" -H "Content-type: text/plain" --header "Transfer-Encoding: chunked" http://127.0.0.1:9202/remove_length'
|
26
|
+
curl_command(command)
|
27
|
+
should "with curl" do
|
28
|
+
@request["Transfer-Encoding"].should.equal "chunked"
|
29
|
+
@request["Expect"].should.equal "100-continue"
|
30
|
+
@response.key?("Transfer-Encoding").should.equal false
|
31
|
+
@response["CONTENT_LENGTH"].should.equal File.stat(File.expand_path('../testrequest.rb', __FILE__)).size.to_s
|
32
|
+
@response["test.postdata"].bytesize.should.equal File.stat(File.expand_path('../testrequest.rb', __FILE__)).size
|
33
|
+
@header["Transfer-Encoding"].should.equal "chunked"
|
34
|
+
@header["Connection"].should.equal "close"
|
35
|
+
@header.key?("HTTP/1.1 100 Continue").should.equal true
|
36
|
+
end
|
37
|
+
|
38
|
+
ensure
|
39
|
+
sleep 1
|
40
|
+
if @pid != nil
|
41
|
+
Process.kill(:TERM, @pid)
|
42
|
+
Process.wait()
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/test/testrequest.rb
CHANGED
@@ -23,7 +23,10 @@ class TestRequest
|
|
23
23
|
ENV.has_key?("TEST_BAR") and minienv["TEST_BAR"] = ENV["TEST_BAR"]
|
24
24
|
body = minienv.to_yaml
|
25
25
|
size = body.respond_to?(:bytesize) ? body.bytesize : body.size
|
26
|
-
res_header = {"Content-
|
26
|
+
res_header = {"Content-Length" => size.to_s, "Content-Type" => "text/yaml", "X-Foo" => "Foo\nBar", "X-Bar"=>"Foo\n\nBar", "X-Baz"=>"\nBaz", "X-Fuga"=>"Fuga\n"}
|
27
|
+
if env["PATH_INFO"] =~ /remove_length/
|
28
|
+
res_header.delete("Content-Length")
|
29
|
+
end
|
27
30
|
[status, res_header.merge(test_header), [body]]
|
28
31
|
end
|
29
32
|
|
@@ -74,6 +77,36 @@ class TestRequest
|
|
74
77
|
}
|
75
78
|
}
|
76
79
|
end
|
80
|
+
|
81
|
+
def curl_command(command)
|
82
|
+
body = ""
|
83
|
+
header = {}
|
84
|
+
request = {}
|
85
|
+
open("|" + command) { |f|
|
86
|
+
while (line = f.gets)
|
87
|
+
next if line.match(/^(\*|}|{) /)
|
88
|
+
if line.match(/^> /)
|
89
|
+
line.sub!(/^> /,"")
|
90
|
+
line.gsub!(/[\r\n]/,"")
|
91
|
+
key,val = line.split(/: /,2)
|
92
|
+
request[key.to_s] = val.to_s
|
93
|
+
next
|
94
|
+
end
|
95
|
+
if line.match(/^< /)
|
96
|
+
line.sub!(/^< /,"")
|
97
|
+
line.gsub!(/[\r\n]/,"")
|
98
|
+
key,val = line.split(/: /,2)
|
99
|
+
header[key.to_s] = val.to_s
|
100
|
+
next
|
101
|
+
end
|
102
|
+
line.sub!(/\* Closing connection #0\n/,"")
|
103
|
+
body += line
|
104
|
+
end
|
105
|
+
}
|
106
|
+
@request = request
|
107
|
+
@response = YAML.load(body)
|
108
|
+
@header = header
|
109
|
+
end
|
77
110
|
end
|
78
111
|
end
|
79
112
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rhebok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro Nagano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -109,6 +109,7 @@ files:
|
|
109
109
|
- ext/rhebok/rhebok.c
|
110
110
|
- lib/rack/handler/rhebok.rb
|
111
111
|
- lib/rhebok.rb
|
112
|
+
- lib/rhebok/buffered.rb
|
112
113
|
- lib/rhebok/config.rb
|
113
114
|
- lib/rhebok/version.rb
|
114
115
|
- rhebok.gemspec
|
@@ -117,6 +118,7 @@ files:
|
|
117
118
|
- test/spec_03_unix.rb
|
118
119
|
- test/spec_04_hook.rb
|
119
120
|
- test/spec_05_config.rb
|
121
|
+
- test/spec_06_curl.rb
|
120
122
|
- test/testconfig.rb
|
121
123
|
- test/testrequest.rb
|
122
124
|
homepage: https://github.com/kazeburo/rhebok
|
@@ -149,5 +151,6 @@ test_files:
|
|
149
151
|
- test/spec_03_unix.rb
|
150
152
|
- test/spec_04_hook.rb
|
151
153
|
- test/spec_05_config.rb
|
154
|
+
- test/spec_06_curl.rb
|
152
155
|
- test/testconfig.rb
|
153
156
|
- test/testrequest.rb
|