bossan 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/README.md +50 -0
- data/Rakefile +15 -0
- data/bossan.gemspec +16 -0
- data/examples/hello.rb +12 -0
- data/examples/sinatra_app.rb +11 -0
- data/examples/views/index.haml +10 -0
- data/examples/views_sample.rb +11 -0
- data/ext/bossan/bossan_ext.c +82 -83
- data/lib/bossan.rb +3 -1
- data/lib/bossan/version.rb +1 -1
- data/lib/rack/handler/bossan.rb +20 -0
- metadata +18 -8
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Bossan
|
2
|
+
|
3
|
+
Bossan is a high performance asynchronous rack web server.
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
Bossan requires Ruby 1.9.x.
|
8
|
+
|
9
|
+
Bossan supports Linux only.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'bossan'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install bossan
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
simple rack app:
|
28
|
+
|
29
|
+
``` ruby
|
30
|
+
require 'bossan'
|
31
|
+
|
32
|
+
Bossan.run('127.0.0.1', 8000, proc {|env|
|
33
|
+
[
|
34
|
+
200, # Status code
|
35
|
+
{ # Response headers
|
36
|
+
'Content-Type' => 'text/html',
|
37
|
+
'Content-Length' => '13',
|
38
|
+
},
|
39
|
+
['hello, world!'] # Response body
|
40
|
+
]
|
41
|
+
})
|
42
|
+
```
|
43
|
+
|
44
|
+
## Contributing
|
45
|
+
|
46
|
+
1. Fork it
|
47
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
48
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
49
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
50
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
task :default => [:compile, :clean]
|
5
|
+
|
6
|
+
task :compile do
|
7
|
+
Dir.chdir File.expand_path("../ext/bossan", __FILE__)
|
8
|
+
system "ruby extconf.rb"
|
9
|
+
system "make"
|
10
|
+
end
|
11
|
+
|
12
|
+
task :clean do
|
13
|
+
Dir.chdir File.expand_path("../ext/bossan", __FILE__)
|
14
|
+
system "rm -f *.o Makefile"
|
15
|
+
end
|
data/bossan.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/bossan/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "bossan"
|
6
|
+
gem.version = Bossan::VERSION
|
7
|
+
gem.authors = ["Hiroki Noda"]
|
8
|
+
gem.email = ["kubo39@gmail.com"]
|
9
|
+
gem.description = %q{high performance asynchronous rack web server}
|
10
|
+
gem.summary = gem.description
|
11
|
+
gem.homepage = "https://github.com/kubo39/bossan"
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($/)
|
14
|
+
gem.extensions = ["ext/bossan/extconf.rb"]
|
15
|
+
gem.require_paths = ["lib", "ext"]
|
16
|
+
end
|
data/examples/hello.rb
ADDED
data/ext/bossan/bossan_ext.c
CHANGED
@@ -51,13 +51,13 @@
|
|
51
51
|
#define CRLF "\r\n"
|
52
52
|
#define DELIM ": "
|
53
53
|
|
54
|
-
#define MSG_500 ("HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>500 Internal Server Error</head><h1>Internal Server Error</h1><p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p></html>\n")
|
54
|
+
#define MSG_500 ("HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>500 Internal Server Error</title></head><h1>Internal Server Error</h1><p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p></html>\n")
|
55
55
|
|
56
|
-
#define MSG_400 ("HTTP/1.0 400 Bad Request\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Bad Request</head><body><p>Bad Request.</p></body></html>")
|
56
|
+
#define MSG_400 ("HTTP/1.0 400 Bad Request\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Bad Request</title></head><body><p>Bad Request.</p></body></html>")
|
57
57
|
|
58
|
-
#define MSG_411 ("HTTP/1.0 411 Length Required\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Length Required</head><body><p>Length Required.</p></body></html>")
|
58
|
+
#define MSG_411 ("HTTP/1.0 411 Length Required\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Length Required</title></head><body><p>Length Required.</p></body></html>")
|
59
59
|
|
60
|
-
#define MSG_413 ("HTTP/1.0 413 Request Entity Too Large\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Request Entity Too Large</head><body><p>Request Entity Too Large.</p></body></html>")
|
60
|
+
#define MSG_413 ("HTTP/1.0 413 Request Entity Too Large\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Request Entity Too Large</title></head><body><p>Request Entity Too Large.</p></body></html>")
|
61
61
|
|
62
62
|
#define SERVER "bossan/0.1"
|
63
63
|
|
@@ -94,11 +94,14 @@ static VALUE rb_remote_port;
|
|
94
94
|
static VALUE rack_input;
|
95
95
|
static VALUE http_connection;
|
96
96
|
|
97
|
+
static VALUE empty_string;
|
98
|
+
|
97
99
|
static VALUE http_user_agent;
|
98
100
|
|
99
101
|
static VALUE i_keys;
|
100
102
|
static VALUE i_call;
|
101
103
|
static VALUE i_new;
|
104
|
+
static VALUE i_key;
|
102
105
|
|
103
106
|
static char *server_name = "127.0.0.1";
|
104
107
|
static short server_port = 8000;
|
@@ -132,10 +135,6 @@ typedef struct {
|
|
132
135
|
size_t limit;
|
133
136
|
} buffer;
|
134
137
|
|
135
|
-
typedef struct {
|
136
|
-
VALUE filelike;
|
137
|
-
} FileWrapperObject;
|
138
|
-
|
139
138
|
typedef enum {
|
140
139
|
FIELD,
|
141
140
|
VAL,
|
@@ -526,7 +525,7 @@ writev_bucket(write_bucket *data)
|
|
526
525
|
}
|
527
526
|
|
528
527
|
static inline int
|
529
|
-
write_headers(client_t *client
|
528
|
+
write_headers(client_t *client)
|
530
529
|
{
|
531
530
|
if(client->header_done){
|
532
531
|
return 1;
|
@@ -566,7 +565,10 @@ write_headers(client_t *client, char *data, size_t datalen)
|
|
566
565
|
cache_time_update();
|
567
566
|
add_header(bucket, "Date", 4, (char *)http_time, 29);
|
568
567
|
if(client->keep_alive == 1){
|
569
|
-
|
568
|
+
// Keep-Alive
|
569
|
+
add_header(bucket, "Connection", 10, "Keep-Alive", 10);
|
570
|
+
} else {
|
571
|
+
add_header(bucket, "Connection", 10, "close", 5);
|
570
572
|
}
|
571
573
|
}
|
572
574
|
|
@@ -581,7 +583,7 @@ write_headers(client_t *client, char *data, size_t datalen)
|
|
581
583
|
if (TYPE(client->headers)!=T_HASH){
|
582
584
|
goto error;
|
583
585
|
}
|
584
|
-
VALUE tmp = rb_funcall(client->headers,
|
586
|
+
VALUE tmp = rb_funcall(client->headers, i_key, 1, object1);
|
585
587
|
if (tmp == Qfalse){
|
586
588
|
goto error;
|
587
589
|
}
|
@@ -621,16 +623,10 @@ write_headers(client_t *client, char *data, size_t datalen)
|
|
621
623
|
}
|
622
624
|
set2bucket(bucket, CRLF, 2);
|
623
625
|
|
624
|
-
if(data){
|
625
|
-
set2bucket(bucket, data, datalen);
|
626
|
-
}
|
627
626
|
client->bucket = bucket;
|
628
627
|
int ret = writev_bucket(bucket);
|
629
628
|
if(ret != 0){
|
630
629
|
client->header_done = 1;
|
631
|
-
if(ret > 0 && data){
|
632
|
-
client->write_bytes += datalen;
|
633
|
-
}
|
634
630
|
// clear
|
635
631
|
free_write_bucket(bucket);
|
636
632
|
client->bucket = NULL;
|
@@ -687,8 +683,6 @@ processs_write(client_t *client)
|
|
687
683
|
iterator = client->response_iter;
|
688
684
|
|
689
685
|
if(iterator != NULL){
|
690
|
-
/* Check_Type(iterator, T_ARRAY); */
|
691
|
-
/* assert(3 == RARRAY_LEN(iterator)); */
|
692
686
|
if (TYPE(iterator) != T_ARRAY || RARRAY_LEN(iterator) != 3){
|
693
687
|
return -1;
|
694
688
|
}
|
@@ -698,29 +692,32 @@ processs_write(client_t *client)
|
|
698
692
|
if (TYPE(arr) != T_ARRAY){
|
699
693
|
return -1;
|
700
694
|
}
|
701
|
-
|
702
|
-
item = rb_ary_entry(arr, 0);
|
703
695
|
|
704
|
-
|
705
|
-
return -1;
|
706
|
-
}
|
696
|
+
int hlen = RARRAY_LEN(arr);
|
707
697
|
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
698
|
+
for(int i=0; i<hlen;i++){
|
699
|
+
item = rb_ary_entry(arr, i);
|
700
|
+
if(TYPE(item) != T_STRING) {
|
701
|
+
return -1;
|
702
|
+
}
|
703
|
+
|
704
|
+
buf = StringValuePtr(item);
|
705
|
+
buflen = RSTRING_LEN(item);
|
706
|
+
//write
|
707
|
+
bucket = new_write_bucket(client->fd, 1);
|
708
|
+
set2bucket(bucket, buf, buflen);
|
709
|
+
ret = writev_bucket(bucket);
|
710
|
+
if(ret <= 0){
|
711
|
+
return ret;
|
712
|
+
}
|
713
|
+
//mark
|
714
|
+
client->write_bytes += buflen;
|
715
|
+
//check write_bytes/content_length
|
716
|
+
if(client->content_length_set){
|
717
|
+
if(client->content_length <= client->write_bytes){
|
718
|
+
// all done
|
719
|
+
break;
|
720
|
+
}
|
724
721
|
}
|
725
722
|
}
|
726
723
|
close_response(client);
|
@@ -755,7 +752,7 @@ static inline int
|
|
755
752
|
start_response_write(client_t *client)
|
756
753
|
{
|
757
754
|
VALUE iterator;
|
758
|
-
VALUE
|
755
|
+
VALUE dict;
|
759
756
|
VALUE item;
|
760
757
|
char *buf;
|
761
758
|
ssize_t buflen;
|
@@ -768,24 +765,16 @@ start_response_write(client_t *client)
|
|
768
765
|
}
|
769
766
|
assert(3 == RARRAY_LEN(iterator));
|
770
767
|
|
771
|
-
|
768
|
+
dict = rb_ary_entry(iterator, 1);
|
772
769
|
|
773
|
-
if (TYPE(
|
770
|
+
if (TYPE(dict) != T_HASH){
|
774
771
|
return -1;
|
775
772
|
}
|
776
773
|
|
777
|
-
VALUE v_body = rb_ary_entry(arr, 0);
|
778
|
-
Check_Type(v_body, T_STRING);
|
779
|
-
|
780
|
-
if (v_body) {
|
781
|
-
buf = StringValuePtr(v_body);
|
782
|
-
buflen = RSTRING_LEN(v_body);
|
783
774
|
#ifdef DEBUG
|
784
|
-
|
775
|
+
printf("start_response_write buflen %d \n", buflen);
|
785
776
|
#endif
|
786
|
-
|
787
|
-
}
|
788
|
-
return -1;
|
777
|
+
return write_headers(client);
|
789
778
|
}
|
790
779
|
|
791
780
|
inline int
|
@@ -794,7 +783,7 @@ response_start(client_t *client)
|
|
794
783
|
int ret;
|
795
784
|
enable_cork(client);
|
796
785
|
if(client->status_code == 304){
|
797
|
-
return write_headers(client
|
786
|
+
return write_headers(client);
|
798
787
|
}
|
799
788
|
ret = start_response_write(client);
|
800
789
|
#ifdef DEBUG
|
@@ -1343,10 +1332,15 @@ init_parser(client_t *cli, const char *name, const short port)
|
|
1343
1332
|
rb_hash_aset(cli->environ, server_name_key, server_name_val);
|
1344
1333
|
rb_hash_aset(cli->environ, server_port_key, server_port_val);
|
1345
1334
|
|
1335
|
+
// query_string
|
1336
|
+
rb_hash_aset(cli->environ, query_string, empty_string);
|
1337
|
+
|
1346
1338
|
object = rb_str_new2(cli->remote_addr);
|
1347
1339
|
rb_hash_aset(cli->environ, rb_remote_addr, object);
|
1348
1340
|
|
1349
|
-
|
1341
|
+
char r_port[6];
|
1342
|
+
sprintf(r_port, "%d", cli->remote_port);
|
1343
|
+
object = rb_str_new2(r_port);
|
1350
1344
|
rb_hash_aset(cli->environ, rb_remote_port, object);
|
1351
1345
|
|
1352
1346
|
http_parser_init(cli->http, HTTP_REQUEST);
|
@@ -1371,44 +1365,46 @@ inline void
|
|
1371
1365
|
setup_static_env(char *name, int port)
|
1372
1366
|
{
|
1373
1367
|
version_val = rb_obj_freeze(rb_ary_new3(2, INT2FIX(1), INT2FIX(1)));
|
1374
|
-
version_key = rb_str_new2("rack.version");
|
1368
|
+
version_key = rb_obj_freeze(rb_str_new2("rack.version"));
|
1375
1369
|
|
1376
|
-
scheme_val = rb_str_new2("http");
|
1377
|
-
scheme_key = rb_str_new2("rack.url_scheme");
|
1370
|
+
scheme_val = rb_obj_freeze(rb_str_new2("http"));
|
1371
|
+
scheme_key = rb_obj_freeze(rb_str_new2("rack.url_scheme"));
|
1378
1372
|
|
1379
1373
|
errors_val = rb_stderr;
|
1380
|
-
errors_key = rb_str_new2("rack.errors");
|
1374
|
+
errors_key = rb_obj_freeze(rb_str_new2("rack.errors"));
|
1381
1375
|
|
1382
1376
|
multithread_val = Qfalse;
|
1383
|
-
multithread_key = rb_str_new2("rack.multithread");
|
1377
|
+
multithread_key = rb_obj_freeze(rb_str_new2("rack.multithread"));
|
1384
1378
|
|
1385
1379
|
multiprocess_val = Qfalse; /* or Qtrue? I have no clue.. */
|
1386
|
-
multiprocess_key = rb_str_new2("rack.multiprocess");
|
1380
|
+
multiprocess_key = rb_obj_freeze(rb_str_new2("rack.multiprocess"));
|
1387
1381
|
|
1388
1382
|
run_once_val = Qfalse;
|
1389
|
-
run_once_key = rb_str_new2("rack.run_once");
|
1383
|
+
run_once_key = rb_obj_freeze(rb_str_new2("rack.run_once"));
|
1390
1384
|
|
1391
|
-
script_val =
|
1392
|
-
script_key = rb_str_new2("SCRIPT_NAME");
|
1385
|
+
script_val = empty_string;
|
1386
|
+
script_key = rb_obj_freeze(rb_str_new2("SCRIPT_NAME"));
|
1393
1387
|
|
1394
|
-
server_name_val = rb_str_new2(name);
|
1395
|
-
server_name_key = rb_str_new2("SERVER_NAME");
|
1388
|
+
server_name_val = rb_obj_freeze(rb_str_new2(name));
|
1389
|
+
server_name_key = rb_obj_freeze(rb_str_new2("SERVER_NAME"));
|
1396
1390
|
|
1397
|
-
|
1398
|
-
|
1391
|
+
char vport[6];
|
1392
|
+
sprintf(vport, "%d", port);
|
1393
|
+
server_port_val = rb_obj_freeze(rb_str_new2(vport));
|
1394
|
+
server_port_key = rb_obj_freeze(rb_str_new2("SERVER_PORT"));
|
1399
1395
|
|
1400
|
-
server_protocol = rb_str_new2("SERVER_PROTOCOL");
|
1401
|
-
path_info = rb_str_new2("PATH_INFO");
|
1402
|
-
request_uri = rb_str_new2("REQUEST_URI");
|
1403
|
-
query_string = rb_str_new2("QUERY_STRING");
|
1404
|
-
http_fragment = rb_str_new2("HTTP_FRAGMENT");
|
1405
|
-
request_method = rb_str_new2("REQUEST_METHOD");
|
1406
|
-
rb_remote_addr = rb_str_new2("REMOTE_ADDR");
|
1407
|
-
rb_remote_port = rb_str_new2("REMOTE_PORT");
|
1408
|
-
rack_input = rb_str_new2("rack.input");
|
1409
|
-
http_connection = rb_str_new2("HTTP_CONNECTION");
|
1396
|
+
server_protocol = rb_obj_freeze(rb_str_new2("SERVER_PROTOCOL"));
|
1397
|
+
path_info = rb_obj_freeze(rb_str_new2("PATH_INFO"));
|
1398
|
+
request_uri = rb_obj_freeze(rb_str_new2("REQUEST_URI"));
|
1399
|
+
query_string = rb_obj_freeze(rb_str_new2("QUERY_STRING"));
|
1400
|
+
http_fragment = rb_obj_freeze(rb_str_new2("HTTP_FRAGMENT"));
|
1401
|
+
request_method = rb_obj_freeze(rb_str_new2("REQUEST_METHOD"));
|
1402
|
+
rb_remote_addr = rb_obj_freeze(rb_str_new2("REMOTE_ADDR"));
|
1403
|
+
rb_remote_port = rb_obj_freeze(rb_str_new2("REMOTE_PORT"));
|
1404
|
+
rack_input = rb_obj_freeze(rb_str_new2("rack.input"));
|
1405
|
+
http_connection = rb_obj_freeze(rb_str_new2("HTTP_CONNECTION"));
|
1410
1406
|
|
1411
|
-
http_user_agent = rb_str_new2("HTTP_USER_AGENT");
|
1407
|
+
http_user_agent = rb_obj_freeze(rb_str_new2("HTTP_USER_AGENT"));
|
1412
1408
|
}
|
1413
1409
|
|
1414
1410
|
static inline int
|
@@ -1724,7 +1720,6 @@ r_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
|
|
1724
1720
|
}
|
1725
1721
|
}
|
1726
1722
|
|
1727
|
-
// TODO: use accept4 in linux
|
1728
1723
|
static void
|
1729
1724
|
accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
|
1730
1725
|
{
|
@@ -1737,8 +1732,7 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
|
|
1737
1732
|
return;
|
1738
1733
|
}else if ((events & PICOEV_READ) != 0) {
|
1739
1734
|
socklen_t client_len = sizeof(client_addr);
|
1740
|
-
client_fd =
|
1741
|
-
|
1735
|
+
client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
1742
1736
|
if (client_fd != -1) {
|
1743
1737
|
#ifdef DEBUG
|
1744
1738
|
printf("accept fd %d \n", client_fd);
|
@@ -1878,7 +1872,7 @@ bossan_access_log(VALUE self, VALUE args)
|
|
1878
1872
|
return Qnil;
|
1879
1873
|
}
|
1880
1874
|
|
1881
|
-
// Bossan.run('127.0.0.1', 8000
|
1875
|
+
// Bossan.run('127.0.0.1', 8000, proc do |env|
|
1882
1876
|
// ...
|
1883
1877
|
// end
|
1884
1878
|
static VALUE
|
@@ -1987,15 +1981,20 @@ Init_bossan_ext(void)
|
|
1987
1981
|
|
1988
1982
|
rb_gc_register_address(&http_user_agent);
|
1989
1983
|
|
1984
|
+
empty_string = rb_obj_freeze(rb_str_new2(""));
|
1985
|
+
rb_gc_register_address(&empty_string);
|
1986
|
+
|
1990
1987
|
rb_gc_register_address(&i_keys);
|
1991
1988
|
rb_gc_register_address(&i_call);
|
1992
1989
|
rb_gc_register_address(&i_new);
|
1990
|
+
rb_gc_register_address(&i_key);
|
1993
1991
|
|
1994
1992
|
rb_gc_register_address(&rack_app); //rack app
|
1995
1993
|
|
1996
1994
|
i_new = rb_intern("new");
|
1997
1995
|
i_call = rb_intern("call");
|
1998
1996
|
i_keys = rb_intern("keys");
|
1997
|
+
i_key = rb_intern("key?");
|
1999
1998
|
|
2000
1999
|
server = rb_define_module("Bossan");
|
2001
2000
|
rb_gc_register_address(&server);
|
data/lib/bossan.rb
CHANGED
data/lib/bossan/version.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rack/handler'
|
2
|
+
require 'bossan'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
module Handler
|
6
|
+
module Bossan
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
"Host" => '0.0.0.0',
|
9
|
+
"Port" => 8080,
|
10
|
+
# :Verbose => false
|
11
|
+
}
|
12
|
+
|
13
|
+
def self.run(app, options = {})
|
14
|
+
options = DEFAULT_OPTIONS.merge(options)
|
15
|
+
::Bossan.run(options["Host"], options["Port"], app)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
register :bossan, Bossan
|
19
|
+
end
|
20
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bossan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-30 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: high performance asynchronous rack web server
|
15
15
|
email:
|
@@ -19,17 +19,27 @@ extensions:
|
|
19
19
|
- ext/bossan/extconf.rb
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
22
24
|
- LICENSE.txt
|
23
|
-
-
|
24
|
-
-
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- bossan.gemspec
|
28
|
+
- examples/hello.rb
|
29
|
+
- examples/sinatra_app.rb
|
30
|
+
- examples/views/index.haml
|
31
|
+
- examples/views_sample.rb
|
32
|
+
- ext/bossan/bossan_ext.c
|
33
|
+
- ext/bossan/extconf.rb
|
34
|
+
- ext/bossan/http_parser.c
|
25
35
|
- ext/bossan/http_parser.h
|
36
|
+
- ext/bossan/picoev.h
|
26
37
|
- ext/bossan/picoev_epoll.c
|
27
38
|
- ext/bossan/time_cache.c
|
28
|
-
- ext/bossan/picoev.h
|
29
39
|
- ext/bossan/time_cache.h
|
30
|
-
-
|
31
|
-
-
|
32
|
-
-
|
40
|
+
- lib/bossan.rb
|
41
|
+
- lib/bossan/version.rb
|
42
|
+
- lib/rack/handler/bossan.rb
|
33
43
|
homepage: https://github.com/kubo39/bossan
|
34
44
|
licenses: []
|
35
45
|
post_install_message:
|