httpkit 0.6.0.pre.3 → 0.6.0.pre.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +15 -0
  2. data/.rspec +0 -1
  3. data/.travis.yml +5 -4
  4. data/Gemfile +0 -2
  5. data/Gemfile.devtools +27 -22
  6. data/README.md +11 -13
  7. data/config/flay.yml +2 -2
  8. data/config/flog.yml +1 -1
  9. data/config/reek.yml +11 -5
  10. data/config/rubocop.yml +47 -5
  11. data/examples/echo_server.rb +2 -2
  12. data/examples/getting_started.rb +16 -10
  13. data/httpkit.gemspec +5 -4
  14. data/lib/httpkit.rb +15 -5
  15. data/lib/httpkit/body.rb +44 -33
  16. data/lib/httpkit/client.rb +52 -23
  17. data/lib/httpkit/client/body_handler.rb +21 -0
  18. data/lib/httpkit/client/{keep_alive.rb → keep_alive_handler.rb} +1 -1
  19. data/lib/httpkit/client/mandatory_handler.rb +29 -0
  20. data/lib/httpkit/client/{timeouts.rb → timeouts_handler.rb} +1 -1
  21. data/lib/httpkit/connection/eventmachine.rb +4 -4
  22. data/lib/httpkit/request.rb +46 -10
  23. data/lib/httpkit/response.rb +37 -5
  24. data/lib/httpkit/serializer.rb +33 -25
  25. data/lib/httpkit/server.rb +14 -19
  26. data/lib/httpkit/server/body_handler.rb +25 -0
  27. data/lib/httpkit/server/{keep_alive.rb → keep_alive_handler.rb} +22 -13
  28. data/lib/httpkit/server/mandatory_handler.rb +23 -0
  29. data/lib/httpkit/server/{timeouts.rb → timeouts_handler.rb} +1 -1
  30. data/lib/httpkit/support/handler_manager.rb +8 -5
  31. data/lib/httpkit/support/message.rb +28 -15
  32. data/lib/httpkit/version.rb +1 -1
  33. data/spec/integration/keep_alive_spec.rb +6 -7
  34. data/spec/integration/smoke_spec.rb +4 -4
  35. data/spec/integration/streaming_spec.rb +2 -3
  36. data/spec/integration/timeouts_spec.rb +6 -6
  37. data/spec/shared/integration/server_client_pair.rb +1 -1
  38. data/spec/spec_helper.rb +3 -2
  39. data/spec/support/handler.rb +1 -1
  40. data/spec/support/helper.rb +6 -4
  41. data/spec/unit/body_spec.rb +6 -0
  42. data/spec/unit/client/keep_alive_handler_spec.rb +6 -0
  43. data/spec/unit/client/mandatory_handler_spec.rb +31 -0
  44. data/spec/unit/client/timeouts_handler_spec.rb +6 -0
  45. data/spec/unit/client_spec.rb +83 -34
  46. data/spec/unit/connection/eventmachine_spec.rb +12 -13
  47. data/spec/unit/httpkit_spec.rb +65 -24
  48. data/spec/unit/promise_spec.rb +1 -1
  49. data/spec/unit/request_spec.rb +2 -10
  50. data/spec/unit/response_spec.rb +7 -15
  51. data/spec/unit/serializer_spec.rb +83 -0
  52. data/spec/unit/server/{keep_alive_spec.rb → keep_alive_handler_spec.rb} +5 -2
  53. data/spec/unit/server/mandatory_handler_spec.rb +30 -0
  54. data/spec/unit/server/timeouts_handler_spec.rb +6 -0
  55. data/spec/unit/server_spec.rb +26 -32
  56. data/spec/unit/support/handler_manager_spec.rb +38 -7
  57. data/spec/unit/support/message_spec.rb +45 -20
  58. metadata +57 -36
  59. data/lib/httpkit/serializer/encoding.rb +0 -43
@@ -50,7 +50,7 @@ describe HTTPkit::Promise do
50
50
 
51
51
  it 'suspends the fiber until the promise state changes' do
52
52
  expect(@fulfilled).to be(true)
53
- expect(@rejected).to be(true)
53
+ expect(@rejected).to be(true)
54
54
  end
55
55
  end
56
56
  end
@@ -13,7 +13,7 @@ describe HTTPkit::Request do
13
13
  its(:uri) { should eq('/a?b=c') }
14
14
  its(:headers) { should eq('Key' => 'value') }
15
15
 
16
- specify { expect(subject.body.read).to eq('hello') }
16
+ specify { expect(subject.body.to_s).to eq('hello') }
17
17
 
18
18
  describe 'defaults' do
19
19
  subject { HTTPkit::Request.new(:get, '/') }
@@ -21,15 +21,7 @@ describe HTTPkit::Request do
21
21
  its(:headers) { should eq({}) }
22
22
  its(:http_version) { should eq(1.1) }
23
23
 
24
- specify { expect(subject.body.read).to be_empty }
24
+ specify { expect(subject.body.to_s).to be_empty }
25
25
  end
26
26
  end
27
-
28
- describe '#http_version=' do
29
- subject { HTTPkit::Request.new(:get, '/') }
30
-
31
- before { subject.http_version = 1.0 }
32
-
33
- its(:http_version) { should eq(1.0) }
34
- end
35
27
  end
@@ -11,7 +11,7 @@ describe HTTPkit::Response do
11
11
  its(:status) { should be(200) }
12
12
  its(:headers) { should eq('Key' => 'value') }
13
13
 
14
- specify { expect(subject.body.read).to eq('hello') }
14
+ specify { expect(subject.body.to_s).to eq('hello') }
15
15
 
16
16
  its(:status_name) { should eq('OK') }
17
17
 
@@ -21,7 +21,7 @@ describe HTTPkit::Response do
21
21
  its(:headers) { should eq({}) }
22
22
  its(:http_version) { should eq(1.1) }
23
23
 
24
- specify { expect(subject.body.read).to be_empty }
24
+ specify { expect(subject.body.to_s).to be_empty }
25
25
  end
26
26
 
27
27
  describe 'unknown status' do
@@ -32,20 +32,12 @@ describe HTTPkit::Response do
32
32
  end
33
33
  end
34
34
 
35
- describe '#http_version=' do
36
- subject { HTTPkit::Response.new(200) }
37
-
38
- before { subject.http_version = 1.0 }
39
-
40
- its(:http_version) { should eq(1.0) }
41
- end
42
-
43
35
  describe 'with 1xx status' do
44
36
  subject { HTTPkit::Response.new(100) }
45
37
 
46
38
  its(:status_class) { should be(1) }
47
39
 
48
- it { should be_informational }
40
+ it { should be_informational }
49
41
  it { should_not be_successful }
50
42
  it { should_not be_redirection }
51
43
  it { should_not be_client_error }
@@ -64,7 +56,7 @@ describe HTTPkit::Response do
64
56
  its(:status_class) { should be(2) }
65
57
 
66
58
  it { should_not be_informational }
67
- it { should be_successful }
59
+ it { should be_successful }
68
60
  it { should_not be_redirection }
69
61
  it { should_not be_client_error }
70
62
  it { should_not be_server_error }
@@ -77,7 +69,7 @@ describe HTTPkit::Response do
77
69
 
78
70
  it { should_not be_informational }
79
71
  it { should_not be_successful }
80
- it { should be_redirection }
72
+ it { should be_redirection }
81
73
  it { should_not be_client_error }
82
74
  it { should_not be_server_error }
83
75
  end
@@ -90,7 +82,7 @@ describe HTTPkit::Response do
90
82
  it { should_not be_informational }
91
83
  it { should_not be_successful }
92
84
  it { should_not be_redirection }
93
- it { should be_client_error }
85
+ it { should be_client_error }
94
86
  it { should_not be_server_error }
95
87
  end
96
88
 
@@ -103,6 +95,6 @@ describe HTTPkit::Response do
103
95
  it { should_not be_successful }
104
96
  it { should_not be_redirection }
105
97
  it { should_not be_client_error }
106
- it { should be_server_error }
98
+ it { should be_server_error }
107
99
  end
108
100
  end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe HTTPkit::Serializer do
6
+ shared_context :serializer do
7
+ let(:yielded_chunks) { [] }
8
+ let(:writer) { proc { |chunk| yielded_chunks << chunk } }
9
+
10
+ subject! { described_class.new(message, writer).serialize }
11
+
12
+ it 'serializes' do
13
+ expect(yielded_chunks).to eq(chunks)
14
+ end
15
+ end
16
+
17
+ describe 'with simple request' do
18
+ let(:message) do
19
+ HTTPkit::Request.new(:get, '/asd?k=v', { 'Key' => 'value' }, 'hello')
20
+ end
21
+
22
+ let(:chunks) do
23
+ ["GET /asd?k=v HTTP/1.1\r\n",
24
+ "Key: value\r\n\r\n",
25
+ 'hello']
26
+ end
27
+
28
+ include_context :serializer
29
+ end
30
+
31
+ describe 'with simple response' do
32
+ let(:message) do
33
+ HTTPkit::Response.new(200, { 'Key' => 'value' }, 'hello')
34
+ end
35
+
36
+ let(:chunks) do
37
+ ["HTTP/1.1 200 OK\r\n",
38
+ "Key: value\r\n\r\n",
39
+ 'hello']
40
+ end
41
+
42
+ include_context :serializer
43
+ end
44
+
45
+ describe 'with empty body' do
46
+ let(:message) do
47
+ HTTPkit::Response.new(200, 'Key' => 'value')
48
+ end
49
+
50
+ let(:chunks) do
51
+ ["HTTP/1.1 200 OK\r\n",
52
+ "Key: value\r\n\r\n",
53
+ '']
54
+ end
55
+
56
+ include_context :serializer
57
+ end
58
+
59
+ describe 'with unbounded body', reactor: true do
60
+ let(:message) do
61
+ HTTPkit::Response.new(200, {}, HTTPkit::Body.new)
62
+ end
63
+
64
+ # With a smaller body it's more difficult to test the base 16 conversion.
65
+ let(:hello) { 'hello' * 204 }
66
+
67
+ let(:chunks) do
68
+ ["HTTP/1.1 200 OK\r\n",
69
+ "\r\n",
70
+ "3fc\r\n#{hello}\r\n",
71
+ "0\r\n\r\n"]
72
+ end
73
+
74
+ before do
75
+ EM.next_tick do
76
+ message.body.write(hello)
77
+ message.close
78
+ end
79
+ end
80
+
81
+ include_context :serializer
82
+ end
83
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe HTTPkit::Server::KeepAlive do
5
+ describe HTTPkit::Server::KeepAliveHandler do
6
6
  let(:config) { double('config') }
7
7
  let(:server) { double('server') }
8
8
  let(:connection) { double('connection') }
@@ -18,7 +18,10 @@ describe HTTPkit::Server::KeepAlive do
18
18
  before { object.setup(config, server, connection) }
19
19
 
20
20
  describe '#close_connection?' do
21
- before { object.serve(request, served) }
21
+ before do
22
+ allow(request).to receive(:sequence).with(server) { 1 }
23
+ object.serve(request, served)
24
+ end
22
25
 
23
26
  let(:subject) { object.send(:close_connection?, request) }
24
27
 
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe HTTPkit::Server::MandatoryHandler do
6
+ describe '#respond' do
7
+ let(:handler) { described_class.new }
8
+ let(:response) { HTTPkit::Response.new(200, headers) }
9
+ let(:headers) { {} }
10
+
11
+ subject! do
12
+ handler.respond(nil, response) { |_, res| @response = res }
13
+ end
14
+
15
+ # XXX: remove time-dependence
16
+ it 'sets Server and Date headers' do
17
+ expect(@response.headers['Server']).to eq("httpkit/#{HTTPkit::VERSION}")
18
+ expect(@response.headers['Date']).to eq(Time.now.httpdate)
19
+ end
20
+
21
+ describe 'with Server or Date header set to anything' do
22
+ let(:headers) { { 'Server' => nil, 'Date' => nil } }
23
+
24
+ it 'does not override' do
25
+ expect(@response.headers['Server']).to be(nil)
26
+ expect(@response.headers['Date']).to be(nil)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe HTTPkit::Server::TimeoutsHandler do
6
+ end
@@ -40,6 +40,18 @@ describe HTTPkit::Server do
40
40
 
41
41
  it 'sets up handlers' do
42
42
  expect(handler).to have_received(:setup).with(config, server, connection)
43
+ expect(config[:handlers].first).to be(handler)
44
+ end
45
+
46
+ describe 'without handlers' do
47
+ let(:config) { {} }
48
+
49
+ it 'adds the mandatory and body handlers' do
50
+ expect(config[:handlers][0])
51
+ .to be_a(HTTPkit::Server::MandatoryHandler)
52
+ expect(config[:handlers][1])
53
+ .to be_a(HTTPkit::Server::BodyHandler)
54
+ end
43
55
  end
44
56
  end
45
57
 
@@ -48,7 +60,7 @@ describe HTTPkit::Server do
48
60
  let(:response) { open_response }
49
61
 
50
62
  before do
51
- allow(server).to receive(:respond)
63
+ allow(server).to receive(:respond)
52
64
  allow(handler).to receive(:serve) { |_, served|
53
65
  @served = served
54
66
  @fiber = Fiber.current
@@ -64,7 +76,7 @@ describe HTTPkit::Server do
64
76
  end
65
77
 
66
78
  it 'notifies the handlers' do
67
- expect(handler).to have_received(:serve)
79
+ expect(handler).to have_received(:serve)
68
80
  .with(request, kind_of(HTTPkit::Promise))
69
81
  expect(@fiber).not_to be(Fiber.current)
70
82
  end
@@ -75,44 +87,24 @@ describe HTTPkit::Server do
75
87
  let(:request) { open_request }
76
88
  let(:response) { open_response(200, headers) }
77
89
 
90
+ before { allow(server).to receive(:finish) }
91
+
78
92
  subject! { server.respond(request, response) }
79
93
 
80
94
  it 'writes response to underlying connection' do
81
- expect(connection).to have_received(:serialize).with(response)
95
+ expect(connection)
96
+ .to have_received(:serialize).with(kind_of(response.class))
82
97
  end
83
98
 
84
99
  it 'notifies the handlers' do
85
- expect(handler).to have_received(:respond).with(request, response)
100
+ expect(handler)
101
+ .to have_received(:respond).with(kind_of(request.class),
102
+ kind_of(response.class))
86
103
  end
87
104
 
88
- it 'sets Server and Date headers' do
89
- expect(headers['Server']).to eq("httpkit/#{HTTPkit::VERSION}")
90
- expect(headers['Date']).to eq(Time.now.httpdate)
91
- end
92
-
93
- describe 'with Server or Date header set to anything' do
94
- let(:headers) { { 'Server' => nil, 'Date' => nil } }
95
-
96
- it 'does not override' do
97
- expect(headers['Server']).to be(nil)
98
- expect(headers['Date']).to be(nil)
99
- end
100
- end
101
-
102
- describe 'wiring', reactor: true do
103
- let(:request) { closed_request }
104
- let(:response) { open_response }
105
-
106
- before do
107
- allow(server).to receive(:finish)
108
-
109
- response.close
110
- tick
111
- end
112
-
113
- it 'wires up #finish' do
114
- expect(server).to have_received(:finish).with(request)
115
- end
105
+ it 'wires up #finish' do
106
+ expect(server)
107
+ .to have_received(:finish).with(kind_of(request.class))
116
108
  end
117
109
  end
118
110
 
@@ -125,4 +117,6 @@ describe HTTPkit::Server do
125
117
  expect(handler).to have_received(:finish).with(request)
126
118
  end
127
119
  end
120
+
121
+ describe '#setup_connection'
128
122
  end
@@ -4,18 +4,49 @@ require 'spec_helper'
4
4
 
5
5
  describe HTTPkit::Support::HandlerManager do
6
6
  let(:handler) { double('handler', message: nil) }
7
- let(:manager) { described_class.new([handler]) }
7
+ let(:handler2) { double('handler2', message: nil) }
8
+ let(:manager) { described_class.new([handler, handler2]) }
8
9
 
9
- describe '#notify' do
10
+ describe '#invoke' do
10
11
  let(:args) { [double, double] }
12
+ let(:args2) { [double, double] }
11
13
 
12
- subject! do
13
- manager.notify(:message, *args)
14
- manager.notify(:nope)
14
+ describe 'with arguments' do
15
+ subject! do
16
+ manager.invoke(:nonexisting)
17
+ manager.invoke(:message, *args)
18
+ end
19
+
20
+ it 'sends message to the handlers' do
21
+ expect(handler).to have_received(:message).with(*args)
22
+ expect(handler2).to have_received(:message).with(*args)
23
+ end
24
+
25
+ it 'returns the arguments' do
26
+ expect(subject).to eq(args)
27
+ end
15
28
  end
16
29
 
17
- it 'notifies the handlers' do
18
- expect(handler).to have_received(:message).with(*args)
30
+ describe 'with yielding handler' do
31
+ let(:non_array) { double }
32
+
33
+ before do
34
+ allow(handler).to receive(:message).and_yield(*args2)
35
+ allow(handler2).to receive(:message).and_yield(non_array)
36
+ end
37
+
38
+ subject! do
39
+ manager.invoke(:message, *args)
40
+ end
41
+
42
+ it 'updates arguments for next handler' do
43
+ expect(handler).to have_received(:message).with(*args)
44
+ expect(handler2).to have_received(:message).with(*args2)
45
+ end
46
+
47
+ it 'returns the updated arguments' do
48
+ expect(subject).to eq([non_array])
49
+ end
19
50
  end
20
51
  end
21
52
  end
@@ -63,15 +63,34 @@ describe HTTPkit::Support::Message do
63
63
  end
64
64
  end
65
65
 
66
- describe '#add_extra_headers' do
67
- subject! { message.add_extra_headers(foo: '456', bar: '789') }
66
+ describe '.build' do
67
+ before do
68
+ allow(message).to receive(:body_present?) { true }
69
+ allow(message).to receive(:body_included?) { true }
70
+ end
71
+
72
+ shared_context :message do
73
+ describe 'without body present' do
74
+ before do
75
+ allow(message).to receive(:body_present?) { false }
76
+ end
68
77
 
69
- it 'adds the headers that do not exist yet' do
70
- expect(message.headers).to eq(foo: '456', bar: '123')
78
+ it 'closes the message' do
79
+ expect(subject).to be_closed
80
+ end
81
+ end
82
+
83
+ describe 'without body included' do
84
+ before do
85
+ allow(message).to receive(:body_included?) { false }
86
+ end
87
+
88
+ it 'closes the message' do
89
+ expect(subject).to be_closed
90
+ end
91
+ end
71
92
  end
72
- end
73
93
 
74
- describe '.build' do
75
94
  before do
76
95
  allow(HTTPkit::Body).to receive(:new) { body }
77
96
  end
@@ -81,17 +100,20 @@ describe HTTPkit::Support::Message do
81
100
  Struct.new(:http_method, :request_url, :headers, :http_version)
82
101
  .new('GET', '/', { 'Key' => 'value' }, [1, 1])
83
102
  end
84
- let(:args) { [:get, '/', { 'Key' => 'value' }, body] }
85
- let(:request) { double }
103
+ let(:args) { [:get, '/', { 'Key' => 'value' }, body, 1.1] }
104
+
105
+ before do
106
+ allow(HTTPkit::Request)
107
+ .to receive(:new).with(*args).and_return(message)
108
+ end
86
109
 
87
110
  subject { HTTPkit::Support::Message.build(parser) }
88
111
 
89
- it 'returns a Request object' do
90
- expect(HTTPkit::Request)
91
- .to receive(:new).with(*args).and_return(request)
92
- expect(request).to receive(:http_version=).with(1.1)
93
- expect(subject).to be(request)
112
+ it 'returns the Request object' do
113
+ expect(subject).to be(message)
94
114
  end
115
+
116
+ include_context :message
95
117
  end
96
118
 
97
119
  describe 'given a parser holding a response' do
@@ -99,17 +121,20 @@ describe HTTPkit::Support::Message do
99
121
  Struct.new(:http_method, :status_code, :headers, :http_version)
100
122
  .new(nil, 200, { 'Key' => 'value' }, [1, 0])
101
123
  end
102
- let(:args) { [200, { 'Key' => 'value' }, body] }
103
- let(:response) { double }
124
+ let(:args) { [200, { 'Key' => 'value' }, body, 1.0] }
104
125
 
105
126
  subject { HTTPkit::Support::Message.build(parser) }
106
127
 
107
- it 'returns a Response object' do
108
- expect(HTTPkit::Response)
109
- .to receive(:new).with(*args).and_return(response)
110
- expect(response).to receive(:http_version=).with(1.0)
111
- expect(subject).to be(response)
128
+ before do
129
+ allow(HTTPkit::Response)
130
+ .to receive(:new).with(*args).and_return(message)
131
+ end
132
+
133
+ it 'returns the Response object' do
134
+ expect(subject).to be(message)
112
135
  end
136
+
137
+ include_context :message
113
138
  end
114
139
  end
115
140
  end