bossan 0.1.0 → 0.1.1
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.
- 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:
|