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

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.
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