bossan 0.4.1 → 0.4.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.
- 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:
|