hatetepe 0.5.0.pre.1 → 0.5.0.pre.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/hatetepe/body.rb CHANGED
@@ -71,6 +71,17 @@ module Hatetepe
71
71
  #
72
72
  # @return [undefined]
73
73
  def rewind
74
+ sync
75
+ rewind!
76
+ end
77
+
78
+ # Rewinds underlying IO without blocking
79
+ #
80
+ # TODO this is a hack. the whole blocking/rewinding stuff needs to be
81
+ # more though out.
82
+ #
83
+ # @api protected
84
+ def rewind!
74
85
  io.rewind
75
86
  end
76
87
 
@@ -56,7 +56,7 @@ module Hatetepe::Client
56
56
 
57
57
  @queue = []
58
58
 
59
- @app = method(:send_request)
59
+ @app = proc {|request| send_request(request) }
60
60
 
61
61
  self.comm_inactivity_timeout = config[:timeout]
62
62
  self.pending_connect_timeout = config[:connect_timeout]
@@ -104,7 +104,9 @@ module Hatetepe::Client
104
104
  response.body.close_write
105
105
  end
106
106
 
107
- if !response || response.failure?
107
+ if !response
108
+ request.fail(nil, self)
109
+ elsif response.failure?
108
110
  request.fail(response)
109
111
  else
110
112
  request.succeed(response)
@@ -128,7 +130,7 @@ module Hatetepe::Client
128
130
  #
129
131
  # @api public
130
132
  def request(verb, uri, headers = {}, body = [])
131
- request = Hatetepe::Request.new(verb, uri, headers, body)
133
+ request = Hatetepe::Request.new(verb, URI(uri), headers, body)
132
134
  self << request
133
135
  EM::Synchrony.sync(request)
134
136
  end
@@ -182,6 +184,11 @@ module Hatetepe::Client
182
184
 
183
185
  # @api public
184
186
  def self.request(verb, uri, headers = {}, body = [])
187
+ uri = URI(uri)
188
+ client = start(host: uri.host, port: uri.port)
189
+ client.request(verb, uri, headers, body)
190
+ ensure
191
+ client.stop
185
192
  end
186
193
 
187
194
  # Feeds the request into the builder and blocks while waiting for the
@@ -248,4 +255,17 @@ module Hatetepe::Client
248
255
  raise "Received response but didn't expect one: #{response.status}"
249
256
  end
250
257
  end
258
+
259
+ module VerbMethods
260
+ [
261
+ :get, :head, :options, :put, :post, :delete, :patch, :connect
262
+ ].each do |verb|
263
+ define_method(verb) do |uri, headers = {}, body = []|
264
+ request(verb, uri, headers, body)
265
+ end
266
+ end
267
+ end
268
+
269
+ include VerbMethods
270
+ extend VerbMethods
251
271
  end
@@ -57,7 +57,7 @@ module Hatetepe
57
57
  end
58
58
 
59
59
  def complete
60
- message.body.rewind
60
+ message.body.rewind!
61
61
  message.body.close_write unless message.body.closed_write?
62
62
  event! :complete
63
63
  end
@@ -1,3 +1,3 @@
1
1
  module Hatetepe
2
- VERSION = "0.5.0.pre.1"
2
+ VERSION = "0.5.0.pre.2"
3
3
  end
@@ -88,11 +88,10 @@ describe Hatetepe::Body do
88
88
  end
89
89
 
90
90
  context "#rewind" do
91
- let(:rewind) { stub "rewind" }
92
-
93
- it "forwards to io#rewind" do
94
- body.io.stub :rewind => rewind
95
- body.rewind.should equal(rewind)
91
+ it "blocks and forwards to io#rewind" do
92
+ body.should_receive(:sync).ordered
93
+ body.io.should_receive(:rewind).ordered
94
+ body.rewind
96
95
  end
97
96
  end
98
97
 
@@ -1,74 +1,165 @@
1
1
  require "spec_helper"
2
2
  require "hatetepe/client"
3
3
 
4
- describe Hatetepe::Client, "(public API)" do
5
- describe ".start"
4
+ describe Hatetepe::Client do
5
+ let :config do
6
+ {
7
+ :host => "127.0.0.1",
8
+ :port => 4242
9
+ }
10
+ end
6
11
 
7
- describe "#stop"
12
+ let :client do
13
+ Object.new.tap do |client|
14
+ client.extend(Hatetepe::Client)
15
+ client.stub(:send_data)
16
+ client.stub(:comm_inactivity_timeout=)
17
+ client.stub(:pending_connect_timeout=)
18
+ client.stub(:send_request) { response }
8
19
 
9
- describe "#stop!"
20
+ client.send(:initialize, config)
21
+ client.post_init
22
+ end
23
+ end
10
24
 
11
- describe "#wait"
25
+ describe ".start" do
26
+ it "starts a new client" do
27
+ EM.should_receive(:connect).
28
+ with(config[:host], config[:port], Hatetepe::Client, config).
29
+ and_return(client)
30
+ Hatetepe::Client.start(config).should equal(client)
31
+ end
32
+ end
12
33
 
13
- describe ".request"
34
+ describe "#stop" do
35
+ it "waits for all requests to finish and closes the connection" do
36
+ client.should_receive(:wait).ordered
37
+ client.should_receive(:stop!).ordered
38
+ client.stop
39
+ end
40
+ end
14
41
 
15
- describe "#request"
42
+ describe "#stop!" do
43
+ it "closes the connection" do
44
+ client.should_receive(:close_connection)
45
+ client.stop!
46
+ end
47
+ end
16
48
 
17
- describe "#<<" do
18
- let :config do
19
- {
20
- :host => "127.0.0.1",
21
- :port => 4242
22
- }
49
+ describe "#wait" do
50
+ let :requests do
51
+ [ Hatetepe::Request.new(:get, "/"), Hatetepe::Request.new(:post, "/") ]
23
52
  end
24
53
 
25
- let :subject do
26
- client = Object.new.extend(Hatetepe::Client)
27
- client.stub(:send_data)
28
- client.stub(:comm_inactivity_timeout=)
29
- client.stub(:pending_connect_timeout=)
30
- client.send(:initialize, config)
31
- client.post_init
32
- client
54
+ before do
55
+ client.unstub(:send_request)
56
+ client << requests[0]
57
+ client << requests[1]
33
58
  end
34
59
 
35
- let :request do
36
- Hatetepe::Request.new :head, "/test"
60
+ it "waits for all requests to finish" do
61
+ returned = false
62
+ Fiber.new do
63
+ client.wait
64
+ returned = true
65
+ end.resume
66
+
67
+ returned.should be_false
68
+
69
+ requests.each(&:succeed)
70
+ returned.should be_true
37
71
  end
72
+ end
73
+
74
+ describe ".request" do
75
+ let(:client) { stub("client", request: res, stop: nil) }
76
+ let(:headers) { stub("headers") }
77
+ let(:body) { stub("body") }
78
+ let(:res) { stub("response") }
79
+ let(:response) { Hatetepe::Client.request(:put, "/test", headers, body) }
80
+
81
+ before { Hatetepe::Client.stub(start: client) }
82
+
83
+ it "it returns the response" do
84
+ client.should_receive(:request).with(:put, URI("/test"), headers, body)
85
+ response.should equal(res)
86
+ end
87
+
88
+ it "stops the client afterwards" do
89
+ client.should_receive(:stop)
90
+ response
91
+ end
92
+ end
93
+
94
+ describe "#request" do
95
+ let(:body) { [ "Hello,", " world!" ] }
96
+ let(:headers) { { "Content-Type" => "text/plain" } }
97
+ let(:request) { stub("request") }
98
+ let(:response) { stub("response") }
99
+
100
+ before do
101
+ client.stub(:<<)
102
+ Hatetepe::Request.stub(:new => request)
103
+ end
104
+
105
+ it "sends the request" do
106
+ Hatetepe::Request.should_receive(:new) do |verb, uri, headers, body|
107
+ verb.should eq(:head)
108
+ uri.path.should eq("/test")
109
+ uri.query.should eq("key=value")
110
+ headers["Content-Type"].should eq("text/plain")
111
+ Enumerator.new(body).to_a.join.should eq("Hello, world!")
38
112
 
39
- it "calls the app in a Fiber" do
40
- fiber = Fiber.current
41
- subject.app.should_receive :call do
42
- Fiber.current.should_not equal(fiber)
113
+ request
43
114
  end
44
115
 
45
- subject << request
116
+ client.should_receive(:<<).with(request)
117
+ EM::Synchrony.should_receive(:sync).with(request)
118
+
119
+ client.request(:head, "/test?key=value", headers, body)
120
+ end
121
+
122
+ it "returns the response" do
123
+ EM::Synchrony.stub(:sync => response)
124
+ client.request(:get, "/").should equal(response)
125
+ end
126
+ end
127
+
128
+ describe "#<<" do
129
+ let :request do
130
+ Hatetepe::Request.new :head, "/test"
46
131
  end
47
132
 
48
- it "fails the request if the response is a failure" do
49
- subject.app.stub :call => Hatetepe::Response.new(400)
50
- request.should_receive(:fail).with(subject.app.call)
133
+ describe "if the response is a success" do
134
+ let(:response) { Hatetepe::Response.new(307) }
51
135
 
52
- subject << request
136
+ it "succeeds the request" do
137
+ request.should_receive(:succeed).with(response)
138
+ client << request
139
+ end
53
140
  end
54
141
 
55
- it "fails the request if there is no response (yet)" do
56
- subject.app.stub :call => nil
57
- request.should_receive(:fail).with(nil)
142
+ describe "if the response is a failure" do
143
+ let(:response) { Hatetepe::Response.new(502) }
58
144
 
59
- subject << request
145
+ it "fails the request" do
146
+ request.should_receive(:fail).with(response)
147
+ client << request
148
+ end
60
149
  end
61
150
 
62
- it "succeeds the request if the response is a success" do
63
- subject.app.stub :call => Hatetepe::Response.new(303)
64
- request.should_receive(:succeed).with(subject.app.call)
151
+ describe "if there is no response" do
152
+ let(:response) { nil }
65
153
 
66
- subject << request
154
+ it "fails the request" do
155
+ request.should_receive(:fail).with(nil, client)
156
+ client << request
157
+ end
67
158
  end
68
159
  end
69
160
  end
70
161
 
71
- describe Hatetepe::Client, "EventMachine API" do
162
+ describe Hatetepe::Client, "(EventMachine API)" do
72
163
  describe "#initialize"
73
164
 
74
165
  describe "#post_init"
@@ -78,7 +169,7 @@ describe Hatetepe::Client, "EventMachine API" do
78
169
  describe "#unbind"
79
170
  end
80
171
 
81
- describe Hatetepe::Client, "private API" do
172
+ describe Hatetepe::Client, "(private API)" do
82
173
  describe "#send_request"
83
174
 
84
175
  describe "#receive_response"
@@ -209,7 +209,7 @@ describe Hatetepe::Parser do
209
209
 
210
210
  it "finishes the body" do
211
211
  parser.on_body {|body|
212
- body.should_receive :rewind
212
+ body.should_receive :rewind!
213
213
  body.should_receive :close_write
214
214
  }
215
215
  do_request
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
  require "hatetepe/server"
5
+ require "rack/lint"
5
6
 
6
7
  describe Hatetepe::Server, "(public API)" do
7
8
  describe ".start(config, &app)" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hatetepe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.pre.1
4
+ version: 0.5.0.pre.2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-01 00:00:00.000000000 Z
12
+ date: 2012-06-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http_parser.rb
@@ -206,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
206
206
  version: 1.3.1
207
207
  requirements: []
208
208
  rubyforge_project:
209
- rubygems_version: 1.8.21
209
+ rubygems_version: 1.8.24
210
210
  signing_key:
211
211
  specification_version: 3
212
212
  summary: The HTTP toolkit