httpkit 0.6.0.pre.3 → 0.6.0.pre.5
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 +15 -0
- data/.rspec +0 -1
- data/.travis.yml +5 -4
- data/Gemfile +0 -2
- data/Gemfile.devtools +27 -22
- data/README.md +11 -13
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/reek.yml +11 -5
- data/config/rubocop.yml +47 -5
- data/examples/echo_server.rb +2 -2
- data/examples/getting_started.rb +16 -10
- data/httpkit.gemspec +5 -4
- data/lib/httpkit.rb +15 -5
- data/lib/httpkit/body.rb +44 -33
- data/lib/httpkit/client.rb +52 -23
- data/lib/httpkit/client/body_handler.rb +21 -0
- data/lib/httpkit/client/{keep_alive.rb → keep_alive_handler.rb} +1 -1
- data/lib/httpkit/client/mandatory_handler.rb +29 -0
- data/lib/httpkit/client/{timeouts.rb → timeouts_handler.rb} +1 -1
- data/lib/httpkit/connection/eventmachine.rb +4 -4
- data/lib/httpkit/request.rb +46 -10
- data/lib/httpkit/response.rb +37 -5
- data/lib/httpkit/serializer.rb +33 -25
- data/lib/httpkit/server.rb +14 -19
- data/lib/httpkit/server/body_handler.rb +25 -0
- data/lib/httpkit/server/{keep_alive.rb → keep_alive_handler.rb} +22 -13
- data/lib/httpkit/server/mandatory_handler.rb +23 -0
- data/lib/httpkit/server/{timeouts.rb → timeouts_handler.rb} +1 -1
- data/lib/httpkit/support/handler_manager.rb +8 -5
- data/lib/httpkit/support/message.rb +28 -15
- data/lib/httpkit/version.rb +1 -1
- data/spec/integration/keep_alive_spec.rb +6 -7
- data/spec/integration/smoke_spec.rb +4 -4
- data/spec/integration/streaming_spec.rb +2 -3
- data/spec/integration/timeouts_spec.rb +6 -6
- data/spec/shared/integration/server_client_pair.rb +1 -1
- data/spec/spec_helper.rb +3 -2
- data/spec/support/handler.rb +1 -1
- data/spec/support/helper.rb +6 -4
- data/spec/unit/body_spec.rb +6 -0
- data/spec/unit/client/keep_alive_handler_spec.rb +6 -0
- data/spec/unit/client/mandatory_handler_spec.rb +31 -0
- data/spec/unit/client/timeouts_handler_spec.rb +6 -0
- data/spec/unit/client_spec.rb +83 -34
- data/spec/unit/connection/eventmachine_spec.rb +12 -13
- data/spec/unit/httpkit_spec.rb +65 -24
- data/spec/unit/promise_spec.rb +1 -1
- data/spec/unit/request_spec.rb +2 -10
- data/spec/unit/response_spec.rb +7 -15
- data/spec/unit/serializer_spec.rb +83 -0
- data/spec/unit/server/{keep_alive_spec.rb → keep_alive_handler_spec.rb} +5 -2
- data/spec/unit/server/mandatory_handler_spec.rb +30 -0
- data/spec/unit/server/timeouts_handler_spec.rb +6 -0
- data/spec/unit/server_spec.rb +26 -32
- data/spec/unit/support/handler_manager_spec.rb +38 -7
- data/spec/unit/support/message_spec.rb +45 -20
- metadata +57 -36
- data/lib/httpkit/serializer/encoding.rb +0 -43
data/spec/unit/promise_spec.rb
CHANGED
data/spec/unit/request_spec.rb
CHANGED
@@ -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.
|
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.
|
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
|
data/spec/unit/response_spec.rb
CHANGED
@@ -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.
|
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.
|
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
|
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
|
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
|
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
|
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
|
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::
|
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
|
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
|
data/spec/unit/server_spec.rb
CHANGED
@@ -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
|
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
|
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)
|
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)
|
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 '
|
89
|
-
expect(
|
90
|
-
|
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(:
|
7
|
+
let(:handler2) { double('handler2', message: nil) }
|
8
|
+
let(:manager) { described_class.new([handler, handler2]) }
|
8
9
|
|
9
|
-
describe '#
|
10
|
+
describe '#invoke' do
|
10
11
|
let(:args) { [double, double] }
|
12
|
+
let(:args2) { [double, double] }
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
18
|
-
|
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 '
|
67
|
-
|
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
|
-
|
70
|
-
|
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
|
-
|
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
|
90
|
-
expect(
|
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
|
-
|
108
|
-
|
109
|
-
.to receive(:new).with(*args).and_return(
|
110
|
-
|
111
|
-
|
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
|