bossan 0.4.3 → 0.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e969be8e7c6867dcf66c449d02c4972699230b18
4
- data.tar.gz: 2ac87fd5dc7533b0d48ef502223c6bb3f4406033
3
+ metadata.gz: 1f63887612e549dc1e027b914db6cbc429fa2ff8
4
+ data.tar.gz: ee4fd5453fc575eb810518206f448f295c46045c
5
5
  SHA512:
6
- metadata.gz: 09880b9fd1622640b6f1eaada5e2b6d62c1f282fa5f0e0810495bc7a7bd4cfa8362318bc753b9c679c6466f26dea164e0dd3fae5d5d5df1cf1c5c1cea929aed8
7
- data.tar.gz: 9c042fb1d4d6593a237883af46d14bbeb72e03a4ef095295420a62ae310a4f77c5a0969f61b38b5b4e9feb5a36b65d322122d0f4f540c167ca6c1e3a43dc7dbf
6
+ metadata.gz: f8ed1e66372a702c38443a2496f7ae620b915ae98480912dbba4fbaca4cb6c10852b430bd26705783dad1e9b7a0fc333b94c5a02ad3bc356e23730dee29ec6f0
7
+ data.tar.gz: e7eef7ca48ed92bacc789ccbf6b260b65dad39f381532160c2ffd9bbadf2928001c2a48003ab5c74b01d7e8d8d996aa6e5ab7e60c71dce9e456832a0bd020f50
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### v0.4.4
4
+
5
+ (Bug release. release 2013-08-30)
6
+
7
+ * return BadRequest when invalid encoded url
8
+
9
+ * fix rack::handler
10
+
3
11
  ### v0.4.3
4
12
 
5
13
  (Bug release. release 2013-07-27)
data/Rakefile CHANGED
@@ -5,18 +5,21 @@ require "rbconfig"
5
5
  task :default => [:compile, :clean, :test]
6
6
 
7
7
  task :compile do
8
+ pwd = Dir.pwd
8
9
  Dir.chdir File.expand_path("../ext/bossan", __FILE__)
9
10
  sh "ruby extconf.rb"
10
11
  sh "make"
11
12
  sh "mv bossan_ext.#{RbConfig::CONFIG['DLEXT']} ../../lib/bossan/"
13
+ Dir.chdir pwd
12
14
  end
13
15
 
14
16
  task :clean do
17
+ pwd = Dir.pwd
15
18
  Dir.chdir File.expand_path("../ext/bossan", __FILE__)
16
19
  sh "rm -f *.o Makefile mkmf.log"
20
+ Dir.chdir pwd
17
21
  end
18
22
 
19
23
  task :test do
20
- Dir.chdir File.expand_path("../test", __FILE__)
21
- sh "ruby test_rack_spec.rb"
24
+ sh "ruby test/driver.rb"
22
25
  end
@@ -23,7 +23,7 @@
23
23
  #define CRLF "\r\n"
24
24
  #define DELIM ": "
25
25
 
26
- #define SERVER "bossan/0.4.3"
26
+ #define SERVER "bossan/0.4.4"
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
 
@@ -133,6 +133,7 @@ static ID i_write;
133
133
  static ID i_seek;
134
134
  static ID i_toa;
135
135
  static ID i_next;
136
+ static ID i_join;
136
137
 
137
138
  static VALUE default_path_string;
138
139
 
@@ -741,50 +742,52 @@ processs_write(client_t *client)
741
742
  DEBUG("process_write start");
742
743
  iterator = client->response_iter;
743
744
 
744
- while ( (item = rb_rescue(rb_body_iterator, iterator, ret_qnil, NULL)) != Qnil ) {
745
+ if (client->response_body_type != T_ARRAY) {
746
+ while ( (item = rb_rescue(rb_body_iterator, iterator, ret_qnil, NULL)) != Qnil ) {
745
747
 
746
- buf = StringValuePtr(item);
747
- buflen = RSTRING_LEN(item);
748
+ buf = StringValuePtr(item);
749
+ buflen = RSTRING_LEN(item);
748
750
 
749
- //write
750
- if(client->chunked_response){
751
- bucket = new_write_bucket(client->fd, 4);
752
- if(bucket == NULL){
753
- return STATUS_ERROR;
754
- }
755
- char *lendata = NULL;
756
- ssize_t len = 0;
751
+ //write
752
+ if(client->chunked_response){
753
+ bucket = new_write_bucket(client->fd, 4);
754
+ if(bucket == NULL){
755
+ return STATUS_ERROR;
756
+ }
757
+ char *lendata = NULL;
758
+ ssize_t len = 0;
757
759
 
758
- VALUE chunk_data = get_chunk_data(buflen);
759
- //TODO CHECK ERROR
760
- lendata = StringValuePtr(chunk_data);
761
- len = RSTRING_LEN(chunk_data);
760
+ VALUE chunk_data = get_chunk_data(buflen);
761
+ //TODO CHECK ERROR
762
+ lendata = StringValuePtr(chunk_data);
763
+ len = RSTRING_LEN(chunk_data);
762
764
 
763
- set_chunked_data(bucket, lendata, len, buf, buflen);
764
- bucket->chunk_data = chunk_data;
765
- } else {
766
- bucket = new_write_bucket(client->fd, 1);
767
- if(bucket == NULL){
768
- return STATUS_ERROR;
765
+ set_chunked_data(bucket, lendata, len, buf, buflen);
766
+ bucket->chunk_data = chunk_data;
767
+ } else {
768
+ bucket = new_write_bucket(client->fd, 1);
769
+ if(bucket == NULL){
770
+ return STATUS_ERROR;
771
+ }
772
+ set2bucket(bucket, buf, buflen);
769
773
  }
770
- set2bucket(bucket, buf, buflen);
771
- }
772
- bucket->temp1 = item;
774
+ bucket->temp1 = item;
773
775
 
774
- ret = writev_bucket(bucket);
775
- if(ret != STATUS_OK){
776
- client->bucket = bucket;
777
- return ret;
778
- }
776
+ ret = writev_bucket(bucket);
777
+ if(ret != STATUS_OK){
778
+ client->bucket = bucket;
779
+ return ret;
780
+ }
779
781
 
780
- free_write_bucket(bucket);
781
- //mark
782
- client->write_bytes += buflen;
783
- //check write_bytes/content_length
784
- if(client->content_length_set){
785
- if(client->content_length <= client->write_bytes){
786
- // all done
787
- break;
782
+ free_write_bucket(bucket);
783
+ //mark
784
+ client->write_bytes += buflen;
785
+ //check write_bytes/content_length
786
+ if(client->content_length_set){
787
+ if(client->content_length <= client->write_bytes){
788
+ // all done
789
+ break;
790
+ }
788
791
  }
789
792
  }
790
793
  }
@@ -838,14 +841,20 @@ start_response_write(client_t *client)
838
841
  VALUE item;
839
842
  char *buf = NULL;
840
843
  ssize_t buflen = NULL;
841
-
842
- item = rb_rescue(rb_body_iterator, client->response_iter, ret_qnil, NULL);
843
- DEBUG("client %p :fd %d", client, client->fd);
844
844
 
845
- if (item != Qnil) {
846
- //write string only
845
+ if (client->response_body_type == T_ARRAY) {
846
+ item = client->response_iter;
847
847
  buf = StringValuePtr(item);
848
848
  buflen = RSTRING_LEN(item);
849
+ } else {
850
+ item = rb_rescue(rb_body_iterator, client->response_iter, ret_qnil, NULL);
851
+ DEBUG("client %p :fd %d", client, client->fd);
852
+
853
+ if (item != Qnil) {
854
+ //write string only
855
+ buf = StringValuePtr(item);
856
+ buflen = RSTRING_LEN(item);
857
+ }
849
858
  }
850
859
 
851
860
  /* DEBUG("status_code %d body:%.*s", client->status_code, (int)buflen, buf); */
@@ -980,17 +989,25 @@ hex2int(int i)
980
989
 
981
990
 
982
991
  static int
983
- urldecode(char *buf, int len)
992
+ urldecode(char *buf)
984
993
  {
985
- int c, c1;
986
- char *s0, *t;
994
+ int len;
995
+ char c, c1, *s0, *t;
996
+
987
997
  t = s0 = buf;
988
- while(len >0){
998
+ len = strlen(buf);
999
+ while(len > 0){
989
1000
  c = *buf++;
990
1001
  if(c == '%' && len > 2){
991
1002
  c = *buf++;
1003
+ if (!isxdigit(c)) {
1004
+ return -1;
1005
+ }
992
1006
  c1 = c;
993
1007
  c = *buf++;
1008
+ if (!isxdigit(c)) {
1009
+ return -1;
1010
+ }
994
1011
  c = hex2int(c1) * 16 + hex2int(c);
995
1012
  len -= 2;
996
1013
  }
@@ -1095,7 +1112,9 @@ set_path(VALUE env, char *buf, int len)
1095
1112
  len--;
1096
1113
  }
1097
1114
  slen = t - s0;
1098
- slen = urldecode(s0, slen);
1115
+ if (urldecode(s0) == -1) {
1116
+ return -1;
1117
+ }
1099
1118
 
1100
1119
  obj = rb_str_new(s0, slen);
1101
1120
 
@@ -1195,6 +1214,7 @@ header_field_cb(http_parser *p, const char *buf, size_t len)
1195
1214
  }
1196
1215
 
1197
1216
  req->field = obj;
1217
+ rb_gc_register_address(&req->field);
1198
1218
  req->last_header_element = FIELD;
1199
1219
  return 0;
1200
1220
  }
@@ -1221,6 +1241,7 @@ header_value_cb(http_parser *p, const char *buf, size_t len)
1221
1241
  return -1;
1222
1242
  }
1223
1243
  req->value = obj;
1244
+ rb_gc_register_address(&req->value);
1224
1245
  req->last_header_element = VAL;
1225
1246
  return 0;
1226
1247
  }
@@ -1335,7 +1356,6 @@ headers_complete_cb(http_parser *p)
1335
1356
  //Last header
1336
1357
  if(likely(req->field && req->value)){
1337
1358
  rb_hash_aset(env, req->field, req->value);
1338
-
1339
1359
  req->field = NULL;
1340
1360
  req->value = NULL;
1341
1361
  }
@@ -1832,7 +1852,14 @@ process_rack_app(client_t *cli)
1832
1852
 
1833
1853
  cli->status_code = NUM2INT(status_code);
1834
1854
  cli->headers = headers;
1835
- cli->response_iter = rb_funcall(response_body, i_toenum, 0);
1855
+
1856
+ if (TYPE(response_body) == T_ARRAY) {
1857
+ cli->response_body_type = T_ARRAY;
1858
+ cli->response_iter = rb_ary_join(response_body, rb_str_new2(""));
1859
+ } else {
1860
+ cli->response_body_type = 0; // TODO: fix
1861
+ cli->response_iter = rb_funcall(response_body, i_toenum, 0);
1862
+ }
1836
1863
 
1837
1864
  rb_gc_register_address(&cli->headers);
1838
1865
  rb_gc_register_address(&cli->response_iter);
@@ -1849,7 +1876,7 @@ process_rack_app(client_t *cli)
1849
1876
  char* reason_phrase;
1850
1877
  reason_phrase = get_reason_phrase(cli->status_code);
1851
1878
 
1852
- char buff[256];
1879
+ char buff[64];
1853
1880
  sprintf(buff, "HTTP/1.%d %d %s\r\n", cli->http_parser->http_minor, cli->status_code, reason_phrase);
1854
1881
  cli->http_status = rb_str_new(buff, strlen(buff));
1855
1882
  rb_gc_register_address(&cli->http_status);
@@ -2462,6 +2489,9 @@ bossan_run_loop(VALUE self, VALUE args)
2462
2489
  if(unix_sock_name){
2463
2490
  unlink(unix_sock_name);
2464
2491
  }
2492
+ if(listen_sock){
2493
+ close(listen_sock);
2494
+ }
2465
2495
  printf("Bye.\n");
2466
2496
  return Qnil;
2467
2497
  }
@@ -2621,15 +2651,6 @@ Init_bossan_ext(void)
2621
2651
  empty_string = rb_obj_freeze(rb_str_new2(""));
2622
2652
  rb_gc_register_address(&empty_string);
2623
2653
 
2624
- rb_gc_register_address(&i_keys);
2625
- rb_gc_register_address(&i_call);
2626
- rb_gc_register_address(&i_new);
2627
- rb_gc_register_address(&i_each);
2628
- rb_gc_register_address(&i_toenum);
2629
- rb_gc_register_address(&i_close);
2630
- rb_gc_register_address(&i_write);
2631
- rb_gc_register_address(&i_seek);
2632
-
2633
2654
  rb_gc_register_address(&rack_app); //rack app
2634
2655
 
2635
2656
  i_new = rb_intern("new");
@@ -2642,6 +2663,7 @@ Init_bossan_ext(void)
2642
2663
  i_seek = rb_intern("seek");
2643
2664
  i_toa = rb_intern("to_a");
2644
2665
  i_next = rb_intern("next");
2666
+ i_join = rb_intern("join");
2645
2667
 
2646
2668
  server = rb_define_module("Bossan");
2647
2669
  rb_gc_register_address(&server);
data/ext/bossan/client.h CHANGED
@@ -29,6 +29,8 @@ typedef struct _client {
29
29
  uint32_t write_bytes; // send body length
30
30
  void *bucket; //write_data
31
31
  uint8_t response_closed; //response closed flag
32
+
33
+ int response_body_type; // response body type
32
34
  } client_t;
33
35
 
34
36
  #endif
@@ -1,3 +1,3 @@
1
1
  module Bossan
2
- VERSION = "0.4.3"
2
+ VERSION = "0.4.4"
3
3
  end
@@ -15,7 +15,7 @@ module Rack
15
15
  options = DEFAULT_OPTIONS.merge(options)
16
16
  puts "* Listening on tcp://#{options[:Host]}:#{options[:Port]}"
17
17
 
18
- ::Bossan.listen(options[:Host], options[:Port])
18
+ ::Bossan.listen(options[:Host], options[:Port].to_i)
19
19
  ::Bossan.run(app)
20
20
  end
21
21
 
@@ -0,0 +1,93 @@
1
+ require_relative '../lib/bossan'
2
+ require 'minitest/unit'
3
+ require 'test/unit/testcase'
4
+ require 'net/http'
5
+ require 'tempfile'
6
+
7
+ module Bossan::Test
8
+ class TestCase < Test::Unit::TestCase
9
+ def setup
10
+ super
11
+ check_app
12
+ start_server
13
+ end
14
+
15
+ def teardown
16
+ super
17
+ stop_server
18
+ check_output_log
19
+ end
20
+
21
+ def host
22
+ "localhost"
23
+ end
24
+
25
+ def port
26
+ 8000
27
+ end
28
+
29
+ def app
30
+ raise("app must override")
31
+ end
32
+
33
+ private
34
+ def check_app
35
+ app
36
+ end
37
+
38
+ def check_output_log
39
+ @mocked_stdout.rewind
40
+ server_stdout_log = @mocked_stdout.read
41
+ server_stdout_log.sub!("Bye.\n", "")
42
+ unless server_stdout_log.empty?
43
+ puts "! Something wrong on server. stdout:"
44
+ puts server_stdout_log
45
+ end
46
+
47
+ @mocked_stderr.rewind
48
+ server_stderr_log = @mocked_stderr.read
49
+ unless server_stderr_log.empty?
50
+ puts "! Something wrong on server. stderr:"
51
+ print server_stderr_log
52
+ end
53
+ end
54
+
55
+ def start_server
56
+ @mocked_stdout = Tempfile.new("bossan.out")
57
+ @mocked_stderr = Tempfile.new("bossan.err")
58
+
59
+ @pid = fork do
60
+ STDOUT.reopen(@mocked_stdout)
61
+ STDERR.reopen(@mocked_stderr)
62
+ trap(:INT) { Bossan.stop }
63
+ Bossan.listen(host, port)
64
+ Bossan.run(app)
65
+ @mocked_stdout.close
66
+ @mocked_stderr.close
67
+ end
68
+
69
+ Process.detach @pid
70
+
71
+ unless server_is_wake_up?
72
+ $stderr.puts "bossan won't wake up until you love it ..."
73
+ exit 1
74
+ end
75
+ end
76
+
77
+ def stop_server
78
+ Process.kill(:INT, @pid)
79
+ end
80
+
81
+ def server_is_wake_up? n=100
82
+ n.times {
83
+ begin
84
+ Net::HTTP.start(host, port)
85
+ rescue
86
+ next
87
+ end
88
+ return true
89
+ }
90
+ return false
91
+ end
92
+ end
93
+ end
data/test/driver.rb ADDED
@@ -0,0 +1,8 @@
1
+ require './test/test_rack_spec'
2
+ require './test/test_rack_err_spec'
3
+ require './test/test_rack_evil'
4
+ require './test/test_rack_chunk_response'
5
+ require './test/test_rack_env_big_message_body'
6
+ require './test/test_rack_env_simple_get'
7
+ require './test/test_rack_env_simple_query'
8
+ require './test/test_rack_each_response'
@@ -1,62 +1,30 @@
1
- require_relative '../lib/bossan'
2
- require_relative './util'
3
- require 'minitest/unit'
4
- require 'test/unit/testcase'
5
- require 'uri'
6
-
7
-
8
- DEFAULT_HOST = "localhost"
9
- DEFAULT_PORT = 8000
10
- ASSERT_RESPONSE = "Hello world!"
11
- RESPONSE = ["Hello ", "world!"].freeze
12
-
13
-
14
- class App
15
- def call env
16
- body = RESPONSE
17
- [200,
18
- {'Content-type'=> 'text/plain'},
19
- body
20
- ]
1
+ require_relative './bossan_test'
2
+ require 'minitest/autorun'
3
+
4
+ class RackChunkResponseTest < Bossan::Test::TestCase
5
+ class App
6
+ def call env
7
+ body = ["Hello ", "World!"]
8
+ [200,
9
+ {'Content-type'=> 'text/plain'},
10
+ body
11
+ ]
12
+ end
21
13
  end
22
- end
23
14
 
24
- class RackChunkResponseTest < Test::Unit::TestCase
15
+ def app
16
+ App.new
17
+ end
25
18
 
26
19
  def test_chunk_response
27
- response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
20
+ response = Net::HTTP.start(host(), port()) {|http|
28
21
  http.get("/")
29
22
  }
30
23
 
31
24
  headers = response.header
32
25
  assert_equal("200", response.code)
33
- assert_equal(ASSERT_RESPONSE, response.body)
26
+ assert_equal("Hello World!", response.body)
34
27
  assert_equal("chunked", headers["transfer-encoding"])
35
28
  assert_equal("close", headers["connection"])
36
29
  end
37
-
38
- end
39
-
40
-
41
- begin
42
- $stderr.puts RUBY_DESCRIPTION
43
-
44
- pid = fork do
45
- trap(:INT) { Bossan.stop }
46
- Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
47
- Bossan.run(App.new)
48
- end
49
-
50
- Process.detach pid
51
-
52
- unless server_is_wake_up?
53
- $stderr.puts "bossan won't wake up until you love it ..."
54
- exit 1
55
- end
56
-
57
- err = MiniTest::Unit.new.run(ARGV)
58
- exit false if err && err != 0
59
-
60
- ensure
61
- Process.kill(:INT, pid)
62
30
  end
@@ -0,0 +1,38 @@
1
+ require_relative './bossan_test'
2
+ require 'minitest/autorun'
3
+ require 'uri'
4
+
5
+ class RackEachResponseTest < Bossan::Test::TestCase
6
+ class EachResponse
7
+ def each
8
+ yield "Hello"
9
+ yield " "
10
+ yield "World!"
11
+ end
12
+ end
13
+
14
+ class App
15
+ def call env
16
+ body = EachResponse.new
17
+ [200,
18
+ {
19
+ 'Content-type'=> 'text/plain',
20
+ 'Content-length'=> "Hello World".size.to_s
21
+ },
22
+ body
23
+ ]
24
+ end
25
+ end
26
+
27
+ def app
28
+ App.new
29
+ end
30
+
31
+ def test_each_response
32
+ response = Net::HTTP.start(host(), port()) {|http|
33
+ http.get("/")
34
+ }
35
+ assert_equal("200", response.code)
36
+ assert_equal("Hello World", response.body)
37
+ end
38
+ end
@@ -1,45 +1,31 @@
1
- require 'test/unit'
1
+ require_relative './bossan_test'
2
2
  require "uri"
3
- require 'net/http'
4
- require_relative '../lib/bossan'
3
+ require 'minitest/autorun'
5
4
 
6
-
7
- class RackEnvBigMessageBodyTest < Test::Unit::TestCase
8
-
9
- RESPONSE = ["Hello ", "world!"].freeze
10
- DEFAULT_HOST = "localhost"
11
- DEFAULT_PORT = 8000
5
+ class RackEnvBigMessageBodyTest < Bossan::Test::TestCase
6
+ def app
7
+ proc {|env|
8
+ @env = env.dup
9
+ body = @env["rack.input"].class.to_s
10
+ [200,
11
+ {
12
+ 'Content-type'=> 'text/plain',
13
+ 'Content-length'=> body.size.to_s
14
+ },
15
+ [ body ]
16
+ ]
17
+ }
18
+ end
12
19
 
13
20
  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/")
21
+ uri = URI.parse("http://#{host()}:#{port()}/")
34
22
  Net::HTTP.start(uri.host, uri.port){|http|
35
23
  header = {
36
24
  "user-agent" => "Ruby/#{RUBY_VERSION} MyHttpClient"
37
25
  }
38
26
  body = "A" * 1024 * 513 # 513K
39
27
  response = http.post(uri.path, body, header)
28
+ assert_equal("IO", response.body)
40
29
  }
41
- ensure
42
- Process.kill(:INT, pid)
43
30
  end
44
-
45
31
  end
@@ -1,59 +1,40 @@
1
1
  # -*- coding: utf-8 -*-
2
- require 'test/unit'
3
- require 'pp'
2
+ require_relative './bossan_test'
4
3
  require 'net/http'
5
- require_relative '../lib/bossan'
6
-
7
-
8
- class RackEnvSimpleGetTest < Test::Unit::TestCase
9
-
10
- RESPONSE = ["Hello ", "world!"].freeze
11
- DEFAULT_HOST = "localhost"
12
- DEFAULT_PORT = 8000
4
+ require 'json'
5
+ require 'minitest/autorun'
6
+
7
+ class RackEnvSimpleGetTest < Bossan::Test::TestCase
8
+ def app
9
+ proc {|env|
10
+ @env = env.dup
11
+ # I have no idea how to check this two values..
12
+ @env.delete "rack.input"
13
+ @env.delete "rack.errors"
14
+ body = [JSON.dump(@env)]
15
+ [200,
16
+ {
17
+ 'Content-type'=> 'application/json',
18
+ 'Content-length'=> body.join.size.to_s
19
+ },
20
+ body
21
+ ]
22
+ }
23
+ end
13
24
 
14
25
  def test_simple_app
15
- r, w = IO.pipe
16
- pid = fork do
17
- r.close
18
- trap(:INT) { Bossan.stop }
19
- Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
20
- Bossan.run(proc {|env|
21
- @env = env.dup
22
- # I have no idea how to check this two values..
23
- @env.delete "rack.input"
24
- @env.delete "rack.errors"
25
- w.write Marshal.dump(@env)
26
- w.close
27
- body = RESPONSE
28
- [200,
29
- {
30
- 'Content-type'=> 'text/plain',
31
- 'Content-length'=> RESPONSE.join.size.to_s
32
- },
33
- body
34
- ]
35
- })
36
- end
37
- Process.detach pid
38
- sleep 2
39
-
40
- Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT){|http|
26
+ response = Net::HTTP.start(host(), port()){|http|
41
27
  http.get("/")
42
28
  }
43
29
 
44
- w.close
45
- env = Marshal.load(r.read)
46
- r.close
30
+ env = JSON.parse(response.body)
47
31
 
48
- assert_equal(env["PATH_INFO"], "/")
49
- assert_equal(env["SCRIPT_NAME"], "")
50
- assert_equal(env["QUERY_STRING"], "")
51
- assert_equal(env["REQUEST_METHOD"], "GET")
52
- assert_equal(env["SERVER_NAME"], "localhost")
53
- assert_equal(env["SERVER_PORT"], "8000")
54
- assert_not_equal(env["HTTP_USER_AGENT"], "")
55
- ensure
56
- Process.kill(:INT, pid)
32
+ assert_equal("/", env["PATH_INFO"])
33
+ assert_equal("", env["SCRIPT_NAME"])
34
+ assert_equal("", env["QUERY_STRING"])
35
+ assert_equal("GET", env["REQUEST_METHOD"])
36
+ assert_equal("localhost", env["SERVER_NAME"])
37
+ assert_equal("8000", env["SERVER_PORT"])
38
+ assert_not_equal("", env["HTTP_USER_AGENT"])
57
39
  end
58
-
59
40
  end
@@ -1,54 +1,36 @@
1
1
  # -*- coding: utf-8 -*-
2
- require 'test/unit'
3
- require 'pp'
2
+ require_relative './bossan_test'
4
3
  require 'net/http'
5
- require_relative '../lib/bossan'
6
-
7
-
8
- class RackEnvSimpleQueryTest < Test::Unit::TestCase
9
-
10
- RESPONSE = ["Hello ", "world!"].freeze
11
- DEFAULT_HOST = "localhost"
12
- DEFAULT_PORT = 8000
4
+ require 'json'
5
+ require 'minitest/autorun'
6
+
7
+ class RackEnvSimpleQueryTest < Bossan::Test::TestCase
8
+ def app
9
+ proc {|env|
10
+ @env = env.dup
11
+ # I have no idea how to check this two values..
12
+ @env.delete "rack.input"
13
+ @env.delete "rack.errors"
14
+
15
+ body = [JSON.dump(@env)]
16
+ [200,
17
+ {
18
+ 'Content-type'=> 'application/json',
19
+ 'Content-length'=> body.join.size.to_s
20
+ },
21
+ body
22
+ ]
23
+ }
24
+ end
13
25
 
14
26
  def test_query_app
15
- r, w = IO.pipe
16
- pid = fork do
17
- r.close
18
- trap(:INT) { Bossan.stop }
19
- Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
20
- Bossan.run(proc {|env|
21
- @env = env.dup
22
- # I have no idea how to check this two values..
23
- @env.delete "rack.input"
24
- @env.delete "rack.errors"
25
- w.write Marshal.dump(@env)
26
- w.close
27
- body = RESPONSE
28
- [200,
29
- {
30
- 'Content-type'=> 'text/plain',
31
- 'Content-length'=> RESPONSE.join.size.to_s
32
- },
33
- body
34
- ]
35
- })
36
- end
37
- Process.detach pid
38
- sleep 2
39
-
40
- Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT){|http|
27
+ response = Net::HTTP.start(host(), port()){|http|
41
28
  http.get("/ABC/DEF?a=1234&bbbb=ccc")
42
29
  }
43
30
 
44
- w.close
45
- env = Marshal.load(r.read)
46
- r.close
31
+ env = JSON.parse(response.body)
47
32
 
48
- assert_equal(env["PATH_INFO"], "/ABC/DEF")
49
- assert_equal(env["QUERY_STRING"], "a=1234&bbbb=ccc")
50
- ensure
51
- Process.kill(:INT, pid)
33
+ assert_equal("/ABC/DEF", env["PATH_INFO"])
34
+ assert_equal("a=1234&bbbb=ccc", env["QUERY_STRING"])
52
35
  end
53
-
54
36
  end
@@ -1,57 +1,31 @@
1
- require_relative '../lib/bossan'
2
- require_relative './util'
3
- require 'minitest/unit'
4
- require 'test/unit/testcase'
1
+ require_relative './bossan_test'
2
+ require 'minitest/autorun'
5
3
 
6
-
7
- DEFAULT_HOST = "localhost"
8
- DEFAULT_PORT = 8000
9
4
  ASSERT_RESPONSE = "Hello world!"
10
5
  RESPONSE = ["Hello ", "world!"].freeze
11
6
 
12
-
13
- class ErrApp
14
- def call env
15
- body = RESPONSE
16
- [500,
17
- {
18
- 'Content-type'=> 'text/html',
19
- },
20
- RESPONSE
21
- ]
7
+ class RackErrSpecTest < Bossan::Test::TestCase
8
+ class ErrApp
9
+ def call env
10
+ body = RESPONSE
11
+ [500,
12
+ {
13
+ 'Content-type'=> 'text/html',
14
+ },
15
+ RESPONSE
16
+ ]
17
+ end
22
18
  end
23
- end
24
19
 
20
+ def app
21
+ ErrApp.new
22
+ end
25
23
 
26
- class RackErrSpecTest < Test::Unit::TestCase
27
24
  def test_error
28
- response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
25
+ response = Net::HTTP.start(host(), port()) {|http|
29
26
  http.get("/")
30
27
  }
31
28
  assert_equal("500", response.code)
32
29
  assert_equal(ASSERT_RESPONSE, response.body)
33
30
  end
34
31
  end
35
-
36
-
37
- begin
38
- $stderr.puts RUBY_DESCRIPTION
39
- pid = fork do
40
- trap(:INT) { Bossan.stop }
41
- Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
42
- Bossan.run(ErrApp.new)
43
- end
44
-
45
- Process.detach pid
46
-
47
- unless server_is_wake_up?
48
- $stderr.puts "bossan won't wake up until you love it ..."
49
- exit 1
50
- end
51
-
52
- err = MiniTest::Unit.new.run(ARGV)
53
- exit false if err && err != 0
54
-
55
- ensure
56
- Process.kill(:INT, pid)
57
- end
@@ -1,81 +1,108 @@
1
- require_relative '../lib/bossan'
2
- require_relative './util'
3
- require 'minitest/unit'
4
- require 'test/unit/testcase'
1
+ require_relative './bossan_test'
5
2
  require 'socket'
6
-
7
-
8
- ASSERT_RESPONSE = "Hello world!"
9
- RESPONSE = ["Hello ", "world!"].freeze
10
- DEFAULT_HOST = "localhost"
11
- DEFAULT_PORT = 8000
12
- DEFAULT_PATH = "/PATH?ket=value"
13
- DEFAULT_VERSION = "HTTP/1.0"
14
- DEFAULT_HEADER = {
15
- "User-Agent"=> "Mozilla/5.0 (X11; U; Linux i686; ja; rv:1.9.2.7) Gecko/20100715 Ubuntu/10.04 (lucid) Firefox/3.6.7",
16
- "Accept"=> "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
17
- "Accept-Language"=> "ja,en-us;q=0.7,en;q=0.3",
18
- "Accept-Encoding"=> "gzip,deflate",
19
- "Accept-Charset"=> "Shift_JIS,utf-8;q=0.7,*;q=0.7",
20
- "Keep-Alive"=> "115",
21
- "Connection"=> "keep-alive",
22
- "Cache-Control"=> "max-age=0",
23
- }
24
-
25
- ERR_400 = "HTTP/1.0 400 Bad Request"
26
-
27
- class App
28
- def call env
29
- body = RESPONSE
30
- [200,
31
- {
32
- 'Content-type'=> 'text/plain',
33
- 'Content-length'=> RESPONSE.join.size.to_s
34
- },
35
- body
36
- ]
3
+ require 'minitest/autorun'
4
+
5
+ class BadHttpMethodTest < Bossan::Test::TestCase
6
+ ASSERT_RESPONSE = "Hello world!"
7
+ RESPONSE = ["Hello ", "world!"].freeze
8
+ DEFAULT_PATH = "/PATH?ket=value"
9
+ DEFAULT_VERSION = "HTTP/1.0"
10
+ DEFAULT_HEADER = {
11
+ "User-Agent"=> "Mozilla/5.0 (X11; U; Linux i686; ja; rv:1.9.2.7) Gecko/20100715 Ubuntu/10.04 (lucid) Firefox/3.6.7",
12
+ "Accept"=> "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
13
+ "Accept-Language"=> "ja,en-us;q=0.7,en;q=0.3",
14
+ "Accept-Encoding"=> "gzip,deflate",
15
+ "Accept-Charset"=> "Shift_JIS,utf-8;q=0.7,*;q=0.7",
16
+ "Keep-Alive"=> "115",
17
+ "Connection"=> "keep-alive",
18
+ "Cache-Control"=> "max-age=0",
19
+ }
20
+ ERR_400 = "HTTP/1.0 400 Bad Request"
21
+
22
+ class App
23
+ def call env
24
+ body = RESPONSE
25
+ [200,
26
+ {
27
+ 'Content-type'=> 'text/plain',
28
+ 'Content-length'=> RESPONSE.join.size.to_s
29
+ },
30
+ body
31
+ ]
32
+ end
37
33
  end
38
- end
39
-
40
-
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
34
 
52
- data = sock.recv(1024 * 2)
53
- return data
54
- rescue
55
- raise
35
+ def app
36
+ App.new
56
37
  end
57
- end
58
38
 
59
-
60
- class BadHttpMethodTest < Test::Unit::TestCase
39
+ def send_data method
40
+ begin
41
+ sock = TCPSocket.new(host(), port())
42
+ sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
43
+ sock.send("#{method} #{DEFAULT_PATH} #{DEFAULT_VERSION}\r\n", 0)
44
+ sock.send("Host: #{host()}\r\n", 0)
45
+ DEFAULT_HEADER.each_pair {|k, v|
46
+ sock.send("#{k}: #{v}\r\n", 0)
47
+ }
48
+ sock.send("\r\n", 0)
49
+
50
+ data = sock.recv(1024 * 2)
51
+ return data
52
+ rescue
53
+ raise
54
+ end
55
+ end
61
56
 
62
57
  def test_bad_method1
63
- response = send_data("")
64
- assert_equal(ERR_400, response.split("\r\n").first)
58
+ begin
59
+ response = send_data("")
60
+ assert_equal(ERR_400, response.split("\r\n").first)
61
+ rescue Errno::EPIPE => e
62
+ assert(true)
63
+ rescue Errno::ECONNRESET => e
64
+ assert(true)
65
+ rescue
66
+ assert(false)
67
+ end
65
68
  end
66
69
 
67
70
  def test_bad_method2
68
- response = send_data("GET" * 100)
69
- assert_equal(ERR_400, response.split("\r\n").first)
71
+ begin
72
+ response = send_data("GET" * 100)
73
+ assert_equal(ERR_400, response.split("\r\n").first)
74
+ rescue Errno::EPIPE => e
75
+ assert(true)
76
+ rescue Errno::ECONNRESET => e
77
+ assert(true)
78
+ rescue
79
+ assert(false)
80
+ end
70
81
  end
71
82
 
72
83
  def test_bad_path
73
- response = send_data("..")
74
- assert_equal(ERR_400, response.split("\r\n").first)
84
+ begin
85
+ response = send_data("..")
86
+ assert_equal(ERR_400, response.split("\r\n").first)
87
+ rescue Errno::EPIPE => e
88
+ assert(true)
89
+ rescue Errno::ECONNRESET => e
90
+ assert(true)
91
+ rescue
92
+ assert(false)
93
+ end
94
+ end
95
+
96
+ def test_invalid_encoded_url
97
+ response = Net::HTTP.start(host(), port()) {|http|
98
+ query = "?q=%XY"
99
+ http.get("/#{query}")
100
+ }
101
+ assert_equal("400", response.code)
75
102
  end
76
103
 
77
104
  def test_long_url1
78
- response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
105
+ response = Net::HTTP.start(host(), port()) {|http|
79
106
  query = "A" * 4095
80
107
  http.get("/#{query}")
81
108
  }
@@ -83,35 +110,10 @@ class BadHttpMethodTest < Test::Unit::TestCase
83
110
  end
84
111
 
85
112
  def test_long_url2
86
- response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
113
+ response = Net::HTTP.start(host(), port()) {|http|
87
114
  query = "A" * 4096
88
115
  http.get("/#{query}")
89
116
  }
90
117
  assert_equal("400", response.code)
91
118
  end
92
-
93
- end
94
-
95
-
96
- begin
97
- $stderr.puts RUBY_DESCRIPTION
98
-
99
- pid = fork do
100
- trap(:INT) { Bossan.stop }
101
- Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
102
- Bossan.run(App.new)
103
- end
104
-
105
- Process.detach pid
106
-
107
- unless server_is_wake_up?
108
- $stderr.puts "bossan won't wake up until you love it ..."
109
- exit 1
110
- end
111
-
112
- err = MiniTest::Unit.new.run(ARGV)
113
- exit false if err && err != 0
114
-
115
- ensure
116
- Process.kill(:INT, pid)
117
119
  end
@@ -0,0 +1,69 @@
1
+ require_relative '../lib/rack/handler/bossan'
2
+ require_relative './util'
3
+ require 'minitest/unit'
4
+ require 'test/unit/testcase'
5
+ require 'uri'
6
+
7
+
8
+ DEFAULT_HOST = "localhost"
9
+ DEFAULT_PORT = "8000"
10
+ ASSERT_RESPONSE = "Hello world!"
11
+ RESPONSE = ["Hello ", "world!"].freeze
12
+
13
+
14
+ class App
15
+ def call env
16
+ # p env
17
+ body = RESPONSE
18
+ [200,
19
+ {
20
+ 'Content-type'=> 'text/plain',
21
+ 'Content-length'=> RESPONSE.join.size.to_s
22
+ },
23
+ body
24
+ ]
25
+ end
26
+ end
27
+
28
+
29
+ class RackSpecTest < Test::Unit::TestCase
30
+
31
+ def test_get
32
+ response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
33
+ http.get("/")
34
+ }
35
+ assert_equal("200", response.code)
36
+ assert_equal(ASSERT_RESPONSE, response.body)
37
+ end
38
+
39
+ def test_post
40
+ response = Net::HTTP.post_form(URI.parse("http://#{DEFAULT_HOST}:#{DEFAULT_PORT}/"),
41
+ {'key1'=> 'value1', 'key2'=> 'value2'})
42
+ assert_equal("200", response.code)
43
+ assert_equal(ASSERT_RESPONSE, response.body)
44
+ end
45
+ end
46
+
47
+
48
+ begin
49
+ $stderr.puts RUBY_DESCRIPTION
50
+ pid = fork do
51
+ trap(:INT) { Rack::Handler::Bossan.stop }
52
+ Rack::Handler::Bossan.run(App.new, {
53
+ :Host => DEFAULT_HOST, :Port => DEFAULT_PORT
54
+ })
55
+ end
56
+
57
+ Process.detach pid
58
+
59
+ unless server_is_wake_up?
60
+ $stderr.puts "bossan won't wake up until you love it ..."
61
+ exit 1
62
+ end
63
+
64
+ err = MiniTest::Unit.new.run(ARGV)
65
+ exit false if err && err != 0
66
+
67
+ ensure
68
+ Process.kill(:INT, pid)
69
+ end
@@ -1,35 +1,30 @@
1
- require_relative '../lib/bossan'
2
- require_relative './util'
3
- require 'minitest/unit'
4
- require 'test/unit/testcase'
1
+ require_relative './bossan_test'
2
+ require 'minitest/autorun'
5
3
  require 'uri'
6
4
 
7
-
8
- DEFAULT_HOST = "localhost"
9
- DEFAULT_PORT = 8000
10
- ASSERT_RESPONSE = "Hello world!"
11
- RESPONSE = ["Hello ", "world!"].freeze
12
-
13
-
14
- class App
15
- def call env
16
- # p env
17
- body = RESPONSE
18
- [200,
19
- {
20
- 'Content-type'=> 'text/plain',
21
- 'Content-length'=> RESPONSE.join.size.to_s
22
- },
23
- body
24
- ]
5
+ class RackSpecTest < Bossan::Test::TestCase
6
+ ASSERT_RESPONSE = "Hello world!"
7
+ RESPONSE = ["Hello ", "world!"].freeze
8
+
9
+ class App
10
+ def call env
11
+ body = RESPONSE
12
+ [200,
13
+ {
14
+ 'Content-type'=> 'text/plain',
15
+ 'Content-length'=> RESPONSE.join.size.to_s
16
+ },
17
+ body
18
+ ]
19
+ end
25
20
  end
26
- end
27
21
 
28
-
29
- class RackSpecTest < Test::Unit::TestCase
22
+ def app
23
+ App.new
24
+ end
30
25
 
31
26
  def test_get
32
- response = Net::HTTP.start(DEFAULT_HOST, DEFAULT_PORT) {|http|
27
+ response = Net::HTTP.start(host(), port()) {|http|
33
28
  http.get("/")
34
29
  }
35
30
  assert_equal("200", response.code)
@@ -37,32 +32,10 @@ class RackSpecTest < Test::Unit::TestCase
37
32
  end
38
33
 
39
34
  def test_post
40
- response = Net::HTTP.post_form(URI.parse("http://#{DEFAULT_HOST}:#{DEFAULT_PORT}/"),
35
+ response = Net::HTTP.post_form(URI.parse("http://#{host()}:#{port()}/"),
41
36
  {'key1'=> 'value1', 'key2'=> 'value2'})
42
37
  assert_equal("200", response.code)
43
38
  assert_equal(ASSERT_RESPONSE, response.body)
44
39
  end
45
40
  end
46
41
 
47
-
48
- begin
49
- $stderr.puts RUBY_DESCRIPTION
50
- pid = fork do
51
- trap(:INT) { Bossan.stop }
52
- Bossan.listen(DEFAULT_HOST, DEFAULT_PORT)
53
- Bossan.run(App.new)
54
- end
55
-
56
- Process.detach pid
57
-
58
- unless server_is_wake_up?
59
- $stderr.puts "bossan won't wake up until you love it ..."
60
- exit 1
61
- end
62
-
63
- err = MiniTest::Unit.new.run(ARGV)
64
- exit false if err && err != 0
65
-
66
- ensure
67
- Process.kill(:INT, pid)
68
- end
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.3
4
+ version: 0.4.4
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-27 00:00:00.000000000 Z
11
+ date: 2013-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -49,7 +49,6 @@ files:
49
49
  - examples/config.ru
50
50
  - examples/fork_sample.rb
51
51
  - examples/hello.rb
52
- - examples/inifinity.rb
53
52
  - examples/sinatra_app.rb
54
53
  - examples/views/index.haml
55
54
  - examples/views_sample.rb
@@ -71,12 +70,16 @@ files:
71
70
  - lib/bossan.rb
72
71
  - lib/bossan/version.rb
73
72
  - lib/rack/handler/bossan.rb
73
+ - test/bossan_test.rb
74
+ - test/driver.rb
74
75
  - test/test_rack_chunk_response.rb
76
+ - test/test_rack_each_response.rb
75
77
  - test/test_rack_env_big_message_body.rb
76
78
  - test/test_rack_env_simple_get.rb
77
79
  - test/test_rack_env_simple_query.rb
78
80
  - test/test_rack_err_spec.rb
79
81
  - test/test_rack_evil.rb
82
+ - test/test_rack_handler.rb
80
83
  - test/test_rack_spec.rb
81
84
  - test/util.rb
82
85
  homepage: https://github.com/kubo39/bossan
@@ -1,17 +0,0 @@
1
- require_relative '../lib/bossan'
2
-
3
-
4
- app = lambda do |env|
5
- body = (1..Float::INFINITY).lazy.map(&:to_s)
6
- [
7
- 200, # Status code
8
- { # Response headers
9
- 'Content-Type' => 'text/html',
10
- },
11
- body # Response body
12
- ]
13
- end
14
-
15
- Bossan.set_keepalive(10)
16
- Bossan.listen('127.0.0.1', 8000)
17
- Bossan.run(app)