bossan 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/examples/blog/app.rb +1 -1
- data/ext/bossan/bossan_ext.c +68 -29
- data/ext/bossan/picoev.h +3 -1
- data/lib/bossan/version.rb +1 -1
- data/test/test_rack_env_big_message_body.rb +45 -0
- data/test/{test_rack_long_url.rb → test_rack_err_spec.rb} +16 -26
- data/test/{test_rack_bad_http_method.rb → test_rack_evil.rb} +36 -17
- data/test/test_rack_spec.rb +4 -5
- metadata +5 -5
- data/TODO +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 943923d13677bcb0574eae13e2bfe1145af1fd0a
|
4
|
+
data.tar.gz: b16bc4e09fb61dca0f8f84a4f011f744e1a15ed6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfc563ed9e3ba7221fb7099b2ccfdc5cc2e20588b34fbf967a31f7cf2d89423851c60033679a699d2290f1350f9d890caa353ab4bd09bb0bae589c2684d57ca6
|
7
|
+
data.tar.gz: 0164c6c0bee4469c55077a81a1e6457c913fec1c4cb31b1ebba099530b329670f58305482489607de785cdf99011ea86c29deaf24a058c95e2c076709bd0ea44
|
data/CHANGELOG.md
CHANGED
data/examples/blog/app.rb
CHANGED
data/ext/bossan/bossan_ext.c
CHANGED
@@ -23,7 +23,7 @@
|
|
23
23
|
#define CRLF "\r\n"
|
24
24
|
#define DELIM ": "
|
25
25
|
|
26
|
-
#define SERVER "bossan/0.4.
|
26
|
+
#define SERVER "bossan/0.4.2"
|
27
27
|
|
28
28
|
#define H_MSG_500 "HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
|
29
29
|
|
@@ -88,7 +88,7 @@ static VALUE rack_input;
|
|
88
88
|
static VALUE http_connection;
|
89
89
|
|
90
90
|
static VALUE content_type;
|
91
|
-
static VALUE
|
91
|
+
static VALUE content_length_key;
|
92
92
|
|
93
93
|
static VALUE h_content_type;
|
94
94
|
static VALUE h_content_length;
|
@@ -158,6 +158,7 @@ static int keep_alive_timeout = 5;
|
|
158
158
|
static int max_fd = 1024 * 4; // picoev max_fd size
|
159
159
|
static int backlog = 1024; // backlog size
|
160
160
|
int max_content_length = 1024 * 1024 * 16; //max_content_length
|
161
|
+
int client_body_buffer_size = 1024 * 500; //client_body_buffer_size
|
161
162
|
|
162
163
|
static VALUE StringIO;
|
163
164
|
|
@@ -254,7 +255,7 @@ write_log(const char *new_path, int fd, const char *data, size_t len)
|
|
254
255
|
static int
|
255
256
|
write_access_log(client_t *cli, int log_fd, const char *log_path)
|
256
257
|
{
|
257
|
-
request *req =
|
258
|
+
request *req = cli->current_req;
|
258
259
|
|
259
260
|
char buf[1024*4];
|
260
261
|
if(log_fd > 0){
|
@@ -624,10 +625,8 @@ write_headers(client_t *client, char *data, size_t datalen)
|
|
624
625
|
//write header
|
625
626
|
for(i=0; i < hlen; i++){
|
626
627
|
object1 = rb_ary_entry(arr, i);
|
627
|
-
/* Check_Type(object1, T_STRING); */
|
628
628
|
|
629
629
|
object2 = rb_hash_aref(client->headers, object1);
|
630
|
-
/* Check_Type(object2, T_STRING); */
|
631
630
|
|
632
631
|
name = StringValuePtr(object1);
|
633
632
|
namelen = RSTRING_LEN(object1);
|
@@ -834,16 +833,17 @@ static response_status
|
|
834
833
|
start_response_write(client_t *client)
|
835
834
|
{
|
836
835
|
VALUE item;
|
837
|
-
char *buf;
|
838
|
-
ssize_t buflen;
|
836
|
+
char *buf = NULL;
|
837
|
+
ssize_t buflen = NULL;
|
839
838
|
|
840
|
-
item =
|
841
|
-
/* Check_Type(item, T_STRING); */
|
839
|
+
item = rb_rescue(rb_body_iterator, client->response_iter, ret_qnil, NULL);
|
842
840
|
DEBUG("client %p :fd %d", client, client->fd);
|
843
841
|
|
844
|
-
|
845
|
-
|
846
|
-
|
842
|
+
if (item != Qnil) {
|
843
|
+
//write string only
|
844
|
+
buf = StringValuePtr(item);
|
845
|
+
buflen = RSTRING_LEN(item);
|
846
|
+
}
|
847
847
|
|
848
848
|
/* DEBUG("status_code %d body:%.*s", client->status_code, (int)buflen, buf); */
|
849
849
|
return write_headers(client, buf, buflen);
|
@@ -889,6 +889,17 @@ key_upper(char *s, const char *key, size_t len)
|
|
889
889
|
}
|
890
890
|
|
891
891
|
|
892
|
+
static int
|
893
|
+
write_body2file(request *req, const char *buffer, size_t buf_len)
|
894
|
+
{
|
895
|
+
FILE *tmp = (FILE *)req->body;
|
896
|
+
fwrite(buffer, 1, buf_len, tmp);
|
897
|
+
req->body_readed += buf_len;
|
898
|
+
DEBUG("write_body2file %d bytes", (int)buf_len);
|
899
|
+
return req->body_readed;
|
900
|
+
}
|
901
|
+
|
902
|
+
|
892
903
|
static int
|
893
904
|
write_body2mem(request *req, const char *buffer, size_t buf_len)
|
894
905
|
{
|
@@ -902,7 +913,11 @@ write_body2mem(request *req, const char *buffer, size_t buf_len)
|
|
902
913
|
static int
|
903
914
|
write_body(request *req, const char *buffer, size_t buffer_len)
|
904
915
|
{
|
905
|
-
|
916
|
+
if (req->body_type == BODY_TYPE_TMPFILE) {
|
917
|
+
return write_body2file(req, buffer, buffer_len);
|
918
|
+
} else {
|
919
|
+
return write_body2mem(req, buffer, buffer_len);
|
920
|
+
}
|
906
921
|
}
|
907
922
|
|
908
923
|
|
@@ -1009,11 +1024,11 @@ static int
|
|
1009
1024
|
replace_env_key(VALUE dict, VALUE old_key, VALUE new_key)
|
1010
1025
|
{
|
1011
1026
|
int ret = 1;
|
1012
|
-
|
1013
1027
|
VALUE value = rb_hash_aref(dict, old_key);
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1028
|
+
|
1029
|
+
if (value != Qnil) {
|
1030
|
+
rb_hash_delete(dict, old_key);
|
1031
|
+
rb_hash_aset(dict, new_key, value);
|
1017
1032
|
}
|
1018
1033
|
return ret;
|
1019
1034
|
}
|
@@ -1249,11 +1264,23 @@ body_cb(http_parser *p, const char *buf, size_t len)
|
|
1249
1264
|
req->bad_request_code = 411;
|
1250
1265
|
return -1;
|
1251
1266
|
}
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1267
|
+
if(req->body_length > client_body_buffer_size){
|
1268
|
+
//large size request
|
1269
|
+
FILE *tmp = tmpfile();
|
1270
|
+
if(tmp < 0){
|
1271
|
+
req->bad_request_code = 500;
|
1272
|
+
return -1;
|
1273
|
+
}
|
1274
|
+
req->body = tmp;
|
1275
|
+
req->body_type = BODY_TYPE_TMPFILE;
|
1276
|
+
DEBUG("BODY_TYPE_TMPFILE");
|
1277
|
+
}else{
|
1278
|
+
//default memory stream
|
1279
|
+
DEBUG("client->body_length %d \n", req->body_length);
|
1280
|
+
req->body = rb_funcall(StringIO, i_new, 1, rb_str_new2(""));
|
1281
|
+
req->body_type = BODY_TYPE_BUFFER;
|
1282
|
+
DEBUG("BODY_TYPE_BUFFER");
|
1283
|
+
}
|
1257
1284
|
}
|
1258
1285
|
write_body(req, buf, len);
|
1259
1286
|
return 0;
|
@@ -1314,7 +1341,7 @@ headers_complete_cb(http_parser *p)
|
|
1314
1341
|
if(unlikely(ret == -1)){
|
1315
1342
|
return -1;
|
1316
1343
|
}
|
1317
|
-
ret = replace_env_key(env, h_content_length,
|
1344
|
+
ret = replace_env_key(env, h_content_length, content_length_key);
|
1318
1345
|
if(unlikely(ret == -1)){
|
1319
1346
|
return -1;
|
1320
1347
|
}
|
@@ -1483,7 +1510,7 @@ setup_static_env(char *name, int port)
|
|
1483
1510
|
http_connection = rb_obj_freeze(rb_str_new2("HTTP_CONNECTION"));
|
1484
1511
|
|
1485
1512
|
content_type = rb_obj_freeze(rb_str_new2("CONTENT_TYPE"));
|
1486
|
-
|
1513
|
+
content_length_key = rb_obj_freeze(rb_str_new2("CONTENT_LENGTH"));
|
1487
1514
|
|
1488
1515
|
h_content_type = rb_obj_freeze(rb_str_new2("HTTP_CONTENT_TYPE"));
|
1489
1516
|
h_content_length = rb_obj_freeze(rb_str_new2("HTTP_CONTENT_LENGTH"));
|
@@ -1535,7 +1562,6 @@ setup_listen_sock(int fd)
|
|
1535
1562
|
int on = 1, r = -1;
|
1536
1563
|
#ifdef linux
|
1537
1564
|
r = setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on));
|
1538
|
-
assert(r == 0);
|
1539
1565
|
#endif
|
1540
1566
|
r = fcntl(fd, F_SETFL, O_NONBLOCK);
|
1541
1567
|
assert(r == 0);
|
@@ -1823,6 +1849,7 @@ process_rack_app(client_t *cli)
|
|
1823
1849
|
char buff[256];
|
1824
1850
|
sprintf(buff, "HTTP/1.%d %d %s\r\n", cli->http_parser->http_minor, cli->status_code, reason_phrase);
|
1825
1851
|
cli->http_status = rb_str_new(buff, strlen(buff));
|
1852
|
+
rb_gc_register_address(&cli->http_status);
|
1826
1853
|
|
1827
1854
|
//check response
|
1828
1855
|
if(cli->response && cli->response == Qnil){
|
@@ -1955,13 +1982,24 @@ prepare_call_rack(client_t *client)
|
|
1955
1982
|
return;
|
1956
1983
|
}
|
1957
1984
|
|
1958
|
-
if(req->body_type ==
|
1985
|
+
if (req->body_type == BODY_TYPE_TMPFILE) {
|
1986
|
+
int fd;
|
1987
|
+
VALUE io;
|
1988
|
+
request *req = client->current_req;
|
1989
|
+
FILE *tmp = (FILE *)req->body;
|
1990
|
+
|
1991
|
+
fflush(tmp);
|
1992
|
+
rewind(tmp);
|
1993
|
+
|
1994
|
+
fd = fileno(tmp);
|
1995
|
+
io = rb_io_fdopen(fd, O_RDWR, NULL);
|
1996
|
+
rb_hash_aset(req->environ, rack_input, io);
|
1997
|
+
} else if(req->body_type == BODY_TYPE_BUFFER) {
|
1959
1998
|
rb_funcall((VALUE)req->body, i_seek, 1, INT2NUM(0));
|
1960
1999
|
rb_hash_aset(req->environ, rack_input, (VALUE)req->body);
|
1961
2000
|
} else {
|
1962
2001
|
object = rb_str_new2("");
|
1963
2002
|
input = rb_funcall(StringIO, i_new, 1, object);
|
1964
|
-
rb_gc_register_address(&input);
|
1965
2003
|
rb_hash_aset(req->environ, rack_input, input);
|
1966
2004
|
req->body = input;
|
1967
2005
|
}
|
@@ -2136,8 +2174,9 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
|
|
2136
2174
|
// next turn or other process
|
2137
2175
|
return;
|
2138
2176
|
}else if ((events & PICOEV_READ) != 0) {
|
2177
|
+
int i;
|
2139
2178
|
socklen_t client_len = sizeof(client_addr);
|
2140
|
-
for(
|
2179
|
+
for(i=0; i<8; ++i) {
|
2141
2180
|
#ifdef linux
|
2142
2181
|
client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
2143
2182
|
#else
|
@@ -2546,7 +2585,7 @@ Init_bossan_ext(void)
|
|
2546
2585
|
rb_gc_register_address(&h_content_type);
|
2547
2586
|
rb_gc_register_address(&h_content_length);
|
2548
2587
|
rb_gc_register_address(&content_type);
|
2549
|
-
rb_gc_register_address(&
|
2588
|
+
rb_gc_register_address(&content_length_key);
|
2550
2589
|
|
2551
2590
|
rb_gc_register_address(&http_10);
|
2552
2591
|
rb_gc_register_address(&http_11);
|
data/ext/bossan/picoev.h
CHANGED
@@ -217,7 +217,9 @@ extern "C" {
|
|
217
217
|
int picoev_add(picoev_loop* loop, int fd, int events, int timeout_in_secs,
|
218
218
|
picoev_handler* callback, void* cb_arg) {
|
219
219
|
picoev_fd* target;
|
220
|
-
|
220
|
+
if (unlikely(!PICOEV_IS_INITED_AND_FD_IN_RANGE(fd))) {
|
221
|
+
return -1;
|
222
|
+
}
|
221
223
|
target = picoev.fds + fd;
|
222
224
|
assert(target->loop_id == 0);
|
223
225
|
target->callback = callback;
|
data/lib/bossan/version.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require "uri"
|
3
|
+
require 'net/http'
|
4
|
+
require_relative '../lib/bossan'
|
5
|
+
|
6
|
+
|
7
|
+
class RackEnvBigMessageBodyTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
RESPONSE = ["Hello ", "world!"].freeze
|
10
|
+
DEFAULT_HOST = "localhost"
|
11
|
+
DEFAULT_PORT = 8000
|
12
|
+
|
13
|
+
def test_query_app
|
14
|
+
pid = fork do
|
15
|
+
trap(:INT) { Bossan.stop }
|
16
|
+
Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
|
17
|
+
Bossan.run(proc {|env|
|
18
|
+
@env = env.dup
|
19
|
+
assert_equal(IO, @env["rack.input"].class)
|
20
|
+
body = RESPONSE
|
21
|
+
[200,
|
22
|
+
{
|
23
|
+
'Content-type'=> 'text/plain',
|
24
|
+
'Content-length'=> RESPONSE.join.size.to_s
|
25
|
+
},
|
26
|
+
body
|
27
|
+
]
|
28
|
+
})
|
29
|
+
end
|
30
|
+
Process.detach pid
|
31
|
+
sleep 2
|
32
|
+
|
33
|
+
uri = URI.parse("http://0.0.0.0:8000/")
|
34
|
+
Net::HTTP.start(uri.host, uri.port){|http|
|
35
|
+
header = {
|
36
|
+
"user-agent" => "Ruby/#{RUBY_VERSION} MyHttpClient"
|
37
|
+
}
|
38
|
+
body = "A" * 1024 * 513 # 513K
|
39
|
+
response = http.post(uri.path, body, header)
|
40
|
+
}
|
41
|
+
ensure
|
42
|
+
Process.kill(:INT, pid)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -4,44 +4,32 @@ require 'test/unit/testcase'
|
|
4
4
|
require 'net/http'
|
5
5
|
|
6
6
|
|
7
|
-
ASSERT_RESPONSE = "Hello world!"
|
8
|
-
RESPONSE = ["Hello ", "world!"].freeze
|
9
7
|
DEFAULT_HOST = "localhost"
|
10
8
|
DEFAULT_PORT = 8000
|
9
|
+
ASSERT_RESPONSE = "Hello world!"
|
10
|
+
RESPONSE = ["Hello ", "world!"].freeze
|
11
11
|
|
12
12
|
|
13
|
-
class
|
13
|
+
class ErrApp
|
14
14
|
def call env
|
15
15
|
body = RESPONSE
|
16
|
-
[
|
16
|
+
[500,
|
17
17
|
{
|
18
|
-
'Content-type'=> 'text/
|
19
|
-
|
20
|
-
|
21
|
-
body
|
18
|
+
'Content-type'=> 'text/html',
|
19
|
+
},
|
20
|
+
RESPONSE
|
22
21
|
]
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
25
|
|
27
|
-
class
|
28
|
-
|
29
|
-
def test_long_url1
|
26
|
+
class RackErrSpecTest < Test::Unit::TestCase
|
27
|
+
def test_error
|
30
28
|
response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
|
31
|
-
|
32
|
-
http.get("/#{query}")
|
29
|
+
http.get("/")
|
33
30
|
}
|
34
|
-
|
35
|
-
assert_equal(
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_long_url2
|
39
|
-
response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
|
40
|
-
query = "A" * 4096
|
41
|
-
http.get("/#{query}")
|
42
|
-
}
|
43
|
-
|
44
|
-
assert_equal("400", response.code)
|
31
|
+
assert_equal("500", response.code)
|
32
|
+
assert_equal(ASSERT_RESPONSE, response.body)
|
45
33
|
end
|
46
34
|
end
|
47
35
|
|
@@ -60,15 +48,17 @@ def server_is_wake_up? n=100
|
|
60
48
|
end
|
61
49
|
|
62
50
|
|
51
|
+
|
63
52
|
begin
|
64
53
|
$stderr.puts RUBY_DESCRIPTION
|
65
|
-
|
66
54
|
pid = fork do
|
67
55
|
trap(:INT) { Bossan.stop }
|
68
56
|
Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
|
69
|
-
Bossan.run(
|
57
|
+
Bossan.run(ErrApp.new)
|
70
58
|
end
|
59
|
+
|
71
60
|
Process.detach pid
|
61
|
+
|
72
62
|
unless server_is_wake_up?
|
73
63
|
$stderr.puts "bossan won't wake up until you love it ..."
|
74
64
|
exit 1
|
@@ -37,25 +37,27 @@ class App
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
class BadHttpMethodTest < Test::Unit::TestCase
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
41
|
+
def send_data method
|
42
|
+
begin
|
43
|
+
sock = TCPSocket.new DEFAULT_HOST, DEFAULT_PORT
|
44
|
+
sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
45
|
+
sock.send("#{method} #{DEFAULT_PATH} #{DEFAULT_VERSION}\r\n", 0)
|
46
|
+
sock.send("Host: #{DEFAULT_HOST}\r\n", 0)
|
47
|
+
DEFAULT_HEADER.each_pair {|k, v|
|
48
|
+
sock.send("#{k}: #{v}\r\n", 0)
|
49
|
+
}
|
50
|
+
sock.send("\r\n", 0)
|
51
|
+
|
52
|
+
data = sock.recv(1024 * 2)
|
53
|
+
return data
|
54
|
+
rescue
|
55
|
+
raise
|
58
56
|
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
class BadHttpMethodTest < Test::Unit::TestCase
|
59
61
|
|
60
62
|
def test_bad_method1
|
61
63
|
response = send_data("")
|
@@ -71,6 +73,23 @@ class BadHttpMethodTest < Test::Unit::TestCase
|
|
71
73
|
response = send_data("..")
|
72
74
|
assert_equal(ERR_400, response.split("\r\n").first)
|
73
75
|
end
|
76
|
+
|
77
|
+
def test_long_url1
|
78
|
+
response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
|
79
|
+
query = "A" * 4095
|
80
|
+
http.get("/#{query}")
|
81
|
+
}
|
82
|
+
assert_equal("200", response.code)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_long_url2
|
86
|
+
response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
|
87
|
+
query = "A" * 4096
|
88
|
+
http.get("/#{query}")
|
89
|
+
}
|
90
|
+
assert_equal("400", response.code)
|
91
|
+
end
|
92
|
+
|
74
93
|
end
|
75
94
|
|
76
95
|
|
data/test/test_rack_spec.rb
CHANGED
@@ -13,6 +13,7 @@ RESPONSE = ["Hello ", "world!"].freeze
|
|
13
13
|
|
14
14
|
class App
|
15
15
|
def call env
|
16
|
+
# p env
|
16
17
|
body = RESPONSE
|
17
18
|
[200,
|
18
19
|
{
|
@@ -24,21 +25,20 @@ class App
|
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
28
|
+
|
27
29
|
class RackSpecTest < Test::Unit::TestCase
|
28
30
|
|
29
|
-
def
|
31
|
+
def test_get
|
30
32
|
response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
|
31
33
|
http.get("/")
|
32
34
|
}
|
33
|
-
|
34
35
|
assert_equal("200", response.code)
|
35
36
|
assert_equal(ASSERT_RESPONSE, response.body)
|
36
37
|
end
|
37
38
|
|
38
|
-
def
|
39
|
+
def test_post
|
39
40
|
response = Net::HTTP.post_form(URI.parse("http://#{DEFAULT_HOST}:#{DEFAULT_PORT}/"),
|
40
41
|
{'key1'=> 'value1', 'key2'=> 'value2'})
|
41
|
-
|
42
42
|
assert_equal("200", response.code)
|
43
43
|
assert_equal(ASSERT_RESPONSE, response.body)
|
44
44
|
end
|
@@ -61,7 +61,6 @@ end
|
|
61
61
|
|
62
62
|
begin
|
63
63
|
$stderr.puts RUBY_DESCRIPTION
|
64
|
-
|
65
64
|
pid = fork do
|
66
65
|
trap(:INT) { Bossan.stop }
|
67
66
|
Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bossan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroki Noda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-07-
|
11
|
+
date: 2013-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -39,7 +39,6 @@ files:
|
|
39
39
|
- LICENSE.txt
|
40
40
|
- README.md
|
41
41
|
- Rakefile
|
42
|
-
- TODO
|
43
42
|
- bossan.gemspec
|
44
43
|
- examples/blog/README.md
|
45
44
|
- examples/blog/app.rb
|
@@ -72,11 +71,12 @@ files:
|
|
72
71
|
- lib/bossan.rb
|
73
72
|
- lib/bossan/version.rb
|
74
73
|
- lib/rack/handler/bossan.rb
|
75
|
-
- test/test_rack_bad_http_method.rb
|
76
74
|
- test/test_rack_chunk_response.rb
|
75
|
+
- test/test_rack_env_big_message_body.rb
|
77
76
|
- test/test_rack_env_simple_get.rb
|
78
77
|
- test/test_rack_env_simple_query.rb
|
79
|
-
- test/
|
78
|
+
- test/test_rack_err_spec.rb
|
79
|
+
- test/test_rack_evil.rb
|
80
80
|
- test/test_rack_spec.rb
|
81
81
|
homepage: https://github.com/kubo39/bossan
|
82
82
|
licenses:
|