bossan 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
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)