hatetepe 0.2.3 → 0.2.4
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/builder.rb +35 -34
- data/lib/hatetepe/cli.rb +2 -2
- data/lib/hatetepe/client.rb +2 -2
- data/lib/hatetepe/server.rb +4 -2
- data/lib/hatetepe/version.rb +1 -1
- data/spec/unit/builder_spec.rb +372 -0
- data/spec/unit/client_spec.rb +2 -2
- data/spec/unit/server_spec.rb +9 -6
- metadata +22 -20
data/lib/hatetepe/builder.rb
CHANGED
@@ -60,40 +60,42 @@ module Hatetepe
|
|
60
60
|
@chunked
|
61
61
|
end
|
62
62
|
|
63
|
-
def request(
|
63
|
+
def request(req)
|
64
|
+
request_line req[0], req[1]
|
65
|
+
headers req[2]
|
66
|
+
body req[3] if req[3]
|
67
|
+
complete
|
68
|
+
end
|
69
|
+
|
70
|
+
def request_line(verb, uri, version = "1.1")
|
64
71
|
complete unless ready?
|
65
72
|
write "#{verb.upcase} #{uri} HTTP/#{version}\r\n"
|
66
73
|
@state = :writing_headers
|
67
74
|
end
|
68
75
|
|
69
|
-
def response(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
return
|
78
|
-
end
|
79
|
-
|
76
|
+
def response(res)
|
77
|
+
response_line res[0]
|
78
|
+
headers res[1]
|
79
|
+
body res[2] if res[2]
|
80
|
+
complete
|
81
|
+
end
|
82
|
+
|
83
|
+
def response_line(code, version = "1.1")
|
80
84
|
complete unless ready?
|
81
85
|
unless status = STATUS_CODES[code]
|
82
86
|
error "Unknown status code: #{code}"
|
83
87
|
end
|
88
|
+
|
84
89
|
write "HTTP/#{version} #{code} #{status}\r\n"
|
85
90
|
@state = :writing_headers
|
86
91
|
end
|
87
92
|
|
88
|
-
def header(name, value
|
89
|
-
|
90
|
-
raw_header "#{name}: #{value}#{charset}"
|
93
|
+
def header(name, value)
|
94
|
+
raw_header "#{name}: #{value}"
|
91
95
|
end
|
92
96
|
|
93
97
|
def headers(hash)
|
94
|
-
|
95
|
-
#hash.each_pair &method(:header)
|
96
|
-
hash.each_pair {|name, value| header name, value }
|
98
|
+
hash.each {|k, v| header k, v }
|
97
99
|
end
|
98
100
|
|
99
101
|
def raw_header(header)
|
@@ -105,7 +107,7 @@ module Hatetepe
|
|
105
107
|
@state = :writing_trailing_headers
|
106
108
|
end
|
107
109
|
|
108
|
-
if header[0..13] == "Content-Length"
|
110
|
+
if @chunked.nil? && header[0..13] == "Content-Length"
|
109
111
|
@chunked = false
|
110
112
|
elsif @chunked.nil? && header[0..16] == "Transfer-Encoding"
|
111
113
|
@chunked = true
|
@@ -114,12 +116,12 @@ module Hatetepe
|
|
114
116
|
write "#{header}\r\n"
|
115
117
|
end
|
116
118
|
|
117
|
-
def body(
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
119
|
+
def body(body)
|
120
|
+
body.each {|c| body_chunk c }
|
121
|
+
# XXX complete here?
|
122
|
+
end
|
123
|
+
|
124
|
+
def body_chunk(chunk)
|
123
125
|
if ready?
|
124
126
|
error "A request or response line and headers are required before writing body"
|
125
127
|
elsif writing_trailing_headers?
|
@@ -135,29 +137,28 @@ module Hatetepe
|
|
135
137
|
if chunked?
|
136
138
|
write "#{chunk.bytesize.to_s(16)}\r\n#{chunk}\r\n"
|
137
139
|
else
|
138
|
-
write chunk
|
140
|
+
write chunk unless chunk.empty?
|
139
141
|
end
|
140
142
|
end
|
141
143
|
|
142
144
|
def complete
|
143
|
-
|
144
|
-
|
145
|
-
|
145
|
+
if ready?
|
146
|
+
return
|
147
|
+
elsif writing_headers? && @chunked.nil?
|
146
148
|
header "Content-Length", "0"
|
147
149
|
end
|
148
|
-
|
149
|
-
|
150
|
+
body_chunk ""
|
151
|
+
|
150
152
|
on_complete.each {|blk| blk.call }
|
151
153
|
reset
|
152
154
|
end
|
153
155
|
|
154
|
-
def write(
|
155
|
-
on_write.each {|blk| blk.call
|
156
|
+
def write(data)
|
157
|
+
on_write.each {|blk| blk.call data }
|
156
158
|
end
|
157
159
|
|
158
160
|
def error(message)
|
159
161
|
exception = BuilderError.new(message)
|
160
|
-
exception.set_backtrace(caller[1..-1])
|
161
162
|
unless on_error.empty?
|
162
163
|
on_error.each {|blk| blk.call(exception) }
|
163
164
|
else
|
data/lib/hatetepe/cli.rb
CHANGED
@@ -22,8 +22,8 @@ module Hatetepe
|
|
22
22
|
method_option :rackup, :aliases => "-r", :type => :string,
|
23
23
|
:banner => "Load specified rackup (.ru) file (default: config.ru)"
|
24
24
|
def start
|
25
|
-
rackup = options[:rackup] || "config.ru"
|
26
|
-
$stderr << "Booting from #{
|
25
|
+
rackup = File.expand_path(options[:rackup] || "config.ru")
|
26
|
+
$stderr << "Booting from #{rackup}\n"
|
27
27
|
$stderr.flush
|
28
28
|
app = Rack::Builder.parse_file(rackup)[0]
|
29
29
|
|
data/lib/hatetepe/client.rb
CHANGED
@@ -74,7 +74,7 @@ module Hatetepe
|
|
74
74
|
|
75
75
|
requests << request
|
76
76
|
Fiber.new {
|
77
|
-
builder.
|
77
|
+
builder.request_line request.verb, request.uri
|
78
78
|
|
79
79
|
if request.headers["Content-Type"] == "application/x-www-form-urlencoded"
|
80
80
|
if request.body.respond_to? :read
|
@@ -89,7 +89,7 @@ module Hatetepe
|
|
89
89
|
if Body === b || b.respond_to?(:each)
|
90
90
|
builder.body b
|
91
91
|
elsif b.respond_to? :read
|
92
|
-
builder.body b.read
|
92
|
+
builder.body [b.read]
|
93
93
|
else
|
94
94
|
builder.body [b]
|
95
95
|
end
|
data/lib/hatetepe/server.rb
CHANGED
@@ -75,11 +75,13 @@ module Hatetepe
|
|
75
75
|
e["stream.start"] = proc {|response|
|
76
76
|
e.delete "stream.start"
|
77
77
|
EM::Synchrony.sync previous if previous
|
78
|
+
|
79
|
+
builder.response_line response[0]
|
78
80
|
response[1]["Server"] = "hatetepe/#{VERSION}"
|
79
|
-
builder.
|
81
|
+
builder.headers response[1]
|
80
82
|
}
|
81
83
|
|
82
|
-
e["stream.send"] = builder.method(:
|
84
|
+
e["stream.send"] = builder.method(:body_chunk)
|
83
85
|
|
84
86
|
e["stream.close"] = proc {
|
85
87
|
e.delete "stream.send"
|
data/lib/hatetepe/version.rb
CHANGED
@@ -0,0 +1,372 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "hatetepe/builder"
|
3
|
+
|
4
|
+
describe Hatetepe::Builder do
|
5
|
+
let(:builder) { Hatetepe::Builder.allocate }
|
6
|
+
|
7
|
+
describe ".build {|builder| ... }"
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
it "resets the builder" do
|
11
|
+
builder.should_receive :reset
|
12
|
+
builder.send :initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
it "initializes the on_complete, on_write, on_error hooks" do
|
16
|
+
builder.send :initialize
|
17
|
+
[:complete, :write, :error].each do |hook|
|
18
|
+
builder.send(:"on_#{hook}").tap do |h|
|
19
|
+
h.should be_an(Array)
|
20
|
+
h.should be_empty
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#initialize {|builder| ... }" do
|
27
|
+
it "yields the builder" do
|
28
|
+
arg = nil
|
29
|
+
builder.send(:initialize) {|b| arg = b }
|
30
|
+
arg.should equal(builder)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
[:complete, :write, :error].each do |hook|
|
35
|
+
describe "#on_#{hook} {|*| ... }" do
|
36
|
+
let(:block) { proc {} }
|
37
|
+
before { builder.send :initialize }
|
38
|
+
|
39
|
+
it "adds a hook block" do
|
40
|
+
builder.send :"on_#{hook}", &block
|
41
|
+
builder.send(:"on_#{hook}").should include(block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#writing_trailing_headers?" do
|
47
|
+
it "returns true if the builder state is :ready" do
|
48
|
+
builder.stub :state => :ready
|
49
|
+
builder.ready?.should be_true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "returns false otherwise" do
|
53
|
+
builder.stub :state => :something
|
54
|
+
builder.ready?.should be_false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#reset" do
|
59
|
+
before { builder.send :reset }
|
60
|
+
|
61
|
+
# XXX maybe don't test chunked flag
|
62
|
+
it "resets the chunked flag and the builder state" do
|
63
|
+
builder.chunked?.should be_nil
|
64
|
+
builder.ready?.should be_true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# XXX maybe test states and flags where they are being mutated
|
69
|
+
describe "#ready?"
|
70
|
+
describe "#writing_headers?"
|
71
|
+
describe "#writing_body?"
|
72
|
+
describe "#writing_trailing_headers?"
|
73
|
+
describe "#chunked?"
|
74
|
+
|
75
|
+
describe "#request(array)" do
|
76
|
+
let(:req) { [:get, "/foo", {"Key" => "value"}, stub("body")] }
|
77
|
+
|
78
|
+
before { builder.send :initialize }
|
79
|
+
|
80
|
+
it "is a shortcut for #request_line, #headers, #body, #complete" do
|
81
|
+
builder.should_receive(:request_line).with req[0], req[1]
|
82
|
+
builder.should_receive(:headers).with req[2]
|
83
|
+
builder.should_receive(:body).with req[3]
|
84
|
+
builder.should_receive :complete
|
85
|
+
builder.request req
|
86
|
+
end
|
87
|
+
|
88
|
+
it "doesn't require a body (fourth element)" do
|
89
|
+
builder.should_receive(:request_line).with req[0], req[1]
|
90
|
+
builder.should_receive(:headers).with req[2]
|
91
|
+
builder.should_not_receive :body
|
92
|
+
builder.request req[0..2]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#request_line(verb, uri, version)" do
|
97
|
+
before { builder.send :initialize }
|
98
|
+
|
99
|
+
it "writes a request line" do
|
100
|
+
builder.should_receive(:write).with "GET /foo HTTP/1.0\r\n"
|
101
|
+
builder.request_line :get, "/foo", "1.0"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "changes the state to :writing_headers" do
|
105
|
+
builder.request_line :get, "/foo"
|
106
|
+
builder.state.should equal(:writing_headers)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "defaults the version to 1.1" do
|
110
|
+
builder.should_receive(:write).with "GET /foo HTTP/1.1\r\n"
|
111
|
+
builder.request_line :get, "/foo"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#response_line(code, version)" do
|
116
|
+
before { builder.send :initialize }
|
117
|
+
|
118
|
+
it "writes a response line" do
|
119
|
+
builder.should_receive(:write).with "HTTP/1.0 403 Forbidden\r\n"
|
120
|
+
builder.response_line 403, "1.0"
|
121
|
+
end
|
122
|
+
|
123
|
+
it "changes the state to :writing_headers" do
|
124
|
+
builder.response_line 403
|
125
|
+
builder.state.should equal(:writing_headers)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "default the version to 1.1" do
|
129
|
+
builder.should_receive(:write).with "HTTP/1.1 403 Forbidden\r\n"
|
130
|
+
builder.response_line 403
|
131
|
+
end
|
132
|
+
|
133
|
+
it "fails if there's no status message for code" do
|
134
|
+
builder.should_receive :error
|
135
|
+
builder.response_line 666
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#response(array)" do
|
140
|
+
let(:res) { [201, {"Key" => "value"}, stub("body")] }
|
141
|
+
|
142
|
+
before { builder.send :initialize }
|
143
|
+
|
144
|
+
it "is a shortcut for #response_line, #headers, #body, #complete" do
|
145
|
+
builder.should_receive(:response_line).with res[0]
|
146
|
+
builder.should_receive(:headers).with res[1]
|
147
|
+
builder.should_receive(:body).with res[2]
|
148
|
+
builder.should_receive :complete
|
149
|
+
builder.response res
|
150
|
+
end
|
151
|
+
|
152
|
+
it "doesn't require a body (third element)" do
|
153
|
+
builder.should_receive(:response_line).with res[0]
|
154
|
+
builder.should_receive(:headers).with res[1]
|
155
|
+
builder.should_not_receive :body
|
156
|
+
builder.response res[0..1]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "#headers(hash)" do
|
161
|
+
it "writes each of the header pairs" do
|
162
|
+
builder.should_receive(:header).with "Key", "value"
|
163
|
+
builder.should_receive(:header).with "Key2", "value2"
|
164
|
+
builder.headers "Key" => "value", "Key2" => "value2"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#header(name, value)" do
|
169
|
+
it "writes the header pair" do
|
170
|
+
builder.should_receive(:raw_header).with "Key: value"
|
171
|
+
builder.header "Key", "value"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "#raw_header(header)" do
|
176
|
+
before do
|
177
|
+
builder.send :initialize
|
178
|
+
builder.response_line 200
|
179
|
+
end
|
180
|
+
|
181
|
+
it "writes the header line" do
|
182
|
+
builder.should_receive(:write).with "Key: value\r\n"
|
183
|
+
builder.raw_header "Key: value"
|
184
|
+
end
|
185
|
+
|
186
|
+
it "fails if no request or response line has been written" do
|
187
|
+
builder.reset
|
188
|
+
builder.should_receive :error
|
189
|
+
builder.raw_header "Key: value"
|
190
|
+
end
|
191
|
+
|
192
|
+
it "fails if body already started" do
|
193
|
+
builder.header "Content-Length", 5
|
194
|
+
builder.body_chunk "asd"
|
195
|
+
|
196
|
+
builder.should_receive :error
|
197
|
+
builder.raw_header "Key: value"
|
198
|
+
end
|
199
|
+
|
200
|
+
it "writes trailing header if body already started and transfer is chunked" do
|
201
|
+
builder.header "Transfer-Encoding", "chunked"
|
202
|
+
builder.body_chunk "asd"
|
203
|
+
|
204
|
+
builder.should_not_receive :error
|
205
|
+
builder.should_receive(:write).with "0\r\n"
|
206
|
+
builder.should_receive(:write).with "Key: value\r\n"
|
207
|
+
builder.raw_header "Key: value"
|
208
|
+
|
209
|
+
builder.state.should equal(:writing_trailing_headers)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "sets the chunked flag" do
|
213
|
+
builder.header "Transfer-Encoding", "chunked"
|
214
|
+
builder.chunked?.should be_true
|
215
|
+
|
216
|
+
builder.reset
|
217
|
+
builder.response_line 200
|
218
|
+
|
219
|
+
builder.header "Content-Length", "0"
|
220
|
+
builder.chunked?.should be_false
|
221
|
+
end
|
222
|
+
|
223
|
+
it "doesn't set the chunked flag a second time" do
|
224
|
+
builder.header "Transfer-Encoding", "chunked"
|
225
|
+
builder.chunked?.should be_true
|
226
|
+
|
227
|
+
builder.header "Content-Length", "0"
|
228
|
+
builder.chunked?.should be_true
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe "#body(#each)" do
|
233
|
+
let(:body) { [stub("chunk#1"), stub("chunk#2")] }
|
234
|
+
|
235
|
+
it "calls #body_chunk for each element" do
|
236
|
+
builder.should_receive(:body_chunk).with body[0]
|
237
|
+
builder.should_receive(:body_chunk).with body[1]
|
238
|
+
builder.body body
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "#body_chunk(chunk)" do
|
243
|
+
before do
|
244
|
+
builder.send :initialize
|
245
|
+
builder.response_line 200
|
246
|
+
end
|
247
|
+
|
248
|
+
it "fails if no request or response line has been written" do
|
249
|
+
builder.reset
|
250
|
+
builder.should_receive :error
|
251
|
+
builder.body_chunk "asd"
|
252
|
+
end
|
253
|
+
|
254
|
+
it "fails if already writing trailing headers" do
|
255
|
+
builder.body_chunk "asd"
|
256
|
+
builder.header "Key", "value"
|
257
|
+
builder.should_receive :error
|
258
|
+
builder.body_chunk "asd"
|
259
|
+
end
|
260
|
+
|
261
|
+
it "assumes Transfer-Encoding: chunked if chunked flag isn't set" do
|
262
|
+
builder.should_receive(:header).with "Transfer-Encoding", "chunked"
|
263
|
+
builder.body_chunk "asd"
|
264
|
+
end
|
265
|
+
|
266
|
+
it "changes the state to :writing_body" do
|
267
|
+
builder.body_chunk "asd"
|
268
|
+
builder.state.should equal(:writing_body)
|
269
|
+
end
|
270
|
+
|
271
|
+
it "writes chunked body data" do
|
272
|
+
builder.body_chunk ""
|
273
|
+
builder.should_receive(:write).with "c\r\nasdfoobarbaz\r\n"
|
274
|
+
builder.body_chunk "asdfoobarbaz"
|
275
|
+
end
|
276
|
+
|
277
|
+
it "writes empty chunked data" do
|
278
|
+
builder.body_chunk ""
|
279
|
+
builder.should_receive(:write).with "0\r\n\r\n"
|
280
|
+
builder.body_chunk ""
|
281
|
+
end
|
282
|
+
|
283
|
+
it "writes plain body data" do
|
284
|
+
builder.header "Content-Length", "12"
|
285
|
+
builder.body_chunk ""
|
286
|
+
builder.should_receive(:write).with "asdfoobarbaz"
|
287
|
+
builder.body_chunk "asdfoobarbaz"
|
288
|
+
end
|
289
|
+
|
290
|
+
it "doesn't write empty plain data" do
|
291
|
+
builder.header "Content-Length", "123"
|
292
|
+
builder.body_chunk ""
|
293
|
+
builder.should_not_receive :write
|
294
|
+
builder.body_chunk ""
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe "#complete" do
|
299
|
+
before do
|
300
|
+
builder.send :initialize
|
301
|
+
builder.response_line 200
|
302
|
+
builder.stub :body_chunk
|
303
|
+
end
|
304
|
+
|
305
|
+
it "does nothing if state is :ready" do
|
306
|
+
builder.reset
|
307
|
+
builder.should_not_receive :write
|
308
|
+
builder.complete
|
309
|
+
end
|
310
|
+
|
311
|
+
it "sets Content-Length to 0 if no body has been sent and transfer is chunked" do
|
312
|
+
builder.should_receive(:header).with "Content-Length", "0"
|
313
|
+
builder.complete
|
314
|
+
end
|
315
|
+
|
316
|
+
it "writes an empty body chunk" do
|
317
|
+
builder.should_receive(:body_chunk).with ""
|
318
|
+
builder.complete
|
319
|
+
end
|
320
|
+
|
321
|
+
let(:hook) { stub "hook", :call => nil }
|
322
|
+
|
323
|
+
it "calls the on_complete hooks" do
|
324
|
+
builder.on_complete << hook
|
325
|
+
hook.should_receive :call
|
326
|
+
builder.complete
|
327
|
+
end
|
328
|
+
|
329
|
+
it "calls #reset" do
|
330
|
+
builder.should_receive :reset
|
331
|
+
builder.complete
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
describe "#write(data)" do
|
336
|
+
let(:hook) { stub "hook" }
|
337
|
+
let(:data) { stub "data" }
|
338
|
+
|
339
|
+
before { builder.send :initialize }
|
340
|
+
|
341
|
+
it "calls the on_write hooks" do
|
342
|
+
builder.on_write << hook
|
343
|
+
hook.should_receive(:call).with data
|
344
|
+
builder.write data
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "#error(message)" do
|
349
|
+
let(:hook1) { stub "hook#1" }
|
350
|
+
let(:hook2) { stub "hook#2" }
|
351
|
+
let(:message) { "error! error!" }
|
352
|
+
let(:exception) { stub "exception" }
|
353
|
+
|
354
|
+
before do
|
355
|
+
builder.send :initialize
|
356
|
+
builder.on_error << hook1 << hook2
|
357
|
+
end
|
358
|
+
|
359
|
+
it "calls the error hooks" do
|
360
|
+
Hatetepe::BuilderError.stub :new => exception
|
361
|
+
|
362
|
+
hook1.should_receive(:call).with exception
|
363
|
+
hook2.should_receive(:call).with exception
|
364
|
+
builder.error message
|
365
|
+
end
|
366
|
+
|
367
|
+
it "raises the exception if no hooks were added" do
|
368
|
+
builder.on_error.clear
|
369
|
+
proc { builder.error message }.should raise_error(Hatetepe::BuilderError, message)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
data/spec/unit/client_spec.rb
CHANGED
@@ -210,7 +210,7 @@ describe Hatetepe::Client do
|
|
210
210
|
it "feeds the builder" do
|
211
211
|
request.body.write "asdf"
|
212
212
|
|
213
|
-
builder.should_receive(:
|
213
|
+
builder.should_receive(:request_line).with request.verb, request.uri
|
214
214
|
builder.should_receive(:headers).with request.headers
|
215
215
|
builder.should_receive(:body).with request.body
|
216
216
|
builder.should_receive(:complete)
|
@@ -220,7 +220,7 @@ describe Hatetepe::Client do
|
|
220
220
|
|
221
221
|
it "wraps the builder feeding within a Fiber" do
|
222
222
|
outer, inner = Fiber.current, nil
|
223
|
-
builder.should_receive(:
|
223
|
+
builder.should_receive(:request_line) {
|
224
224
|
inner = Fiber.current
|
225
225
|
}
|
226
226
|
|
data/spec/unit/server_spec.rb
CHANGED
@@ -159,7 +159,8 @@ describe Hatetepe::Server do
|
|
159
159
|
server.requests.unshift previous
|
160
160
|
app.stub(:call) {|e| response }
|
161
161
|
request.stub :succeed
|
162
|
-
server.builder.stub :
|
162
|
+
server.builder.stub :response_line
|
163
|
+
server.builder.stub :headers
|
163
164
|
}
|
164
165
|
|
165
166
|
it "deletes itself from env[] to prevent multiple calls" do
|
@@ -178,10 +179,12 @@ describe Hatetepe::Server do
|
|
178
179
|
end
|
179
180
|
|
180
181
|
it "initiates the response" do
|
181
|
-
server.builder.should_receive(:
|
182
|
-
|
183
|
-
|
184
|
-
|
182
|
+
server.builder.should_receive(:response_line) {|code|
|
183
|
+
code.should equal(response[0])
|
184
|
+
}
|
185
|
+
server.builder.should_receive(:headers) {|headers|
|
186
|
+
headers["Key"].should equal(response[1]["Key"])
|
187
|
+
headers["Server"].should == "hatetepe/#{Hatetepe::VERSION}"
|
185
188
|
}
|
186
189
|
previous.succeed
|
187
190
|
server.process
|
@@ -191,7 +194,7 @@ describe Hatetepe::Server do
|
|
191
194
|
context "env[stream.send].call(chunk)" do
|
192
195
|
it "passes data to the builder" do
|
193
196
|
app.stub(:call) {|e|
|
194
|
-
e["stream.send"].should == server.builder.method(:
|
197
|
+
e["stream.send"].should == server.builder.method(:body_chunk)
|
195
198
|
[-1]
|
196
199
|
}
|
197
200
|
server.process
|
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.2.
|
4
|
+
version: 0.2.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-24 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: http_parser.rb
|
16
|
-
requirement: &
|
16
|
+
requirement: &77539070 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.5.3
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *77539070
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: eventmachine
|
27
|
-
requirement: &
|
27
|
+
requirement: &77524530 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *77524530
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: em-synchrony
|
38
|
-
requirement: &
|
38
|
+
requirement: &77524030 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '1.0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *77524030
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rack
|
49
|
-
requirement: &
|
49
|
+
requirement: &77523660 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *77523660
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: async-rack
|
60
|
-
requirement: &
|
60
|
+
requirement: &77523290 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *77523290
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: thor
|
71
|
-
requirement: &
|
71
|
+
requirement: &77522880 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *77522880
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rspec
|
82
|
-
requirement: &
|
82
|
+
requirement: &77521160 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *77521160
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: fakefs
|
93
|
-
requirement: &
|
93
|
+
requirement: &77520680 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *77520680
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: em-http-request
|
104
|
-
requirement: &
|
104
|
+
requirement: &77519340 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
version: '1.0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *77519340
|
113
113
|
description:
|
114
114
|
email:
|
115
115
|
- lars.gierth@gmail.com
|
@@ -148,6 +148,7 @@ files:
|
|
148
148
|
- spec/spec_helper.rb
|
149
149
|
- spec/unit/app_spec.rb
|
150
150
|
- spec/unit/body_spec.rb
|
151
|
+
- spec/unit/builder_spec.rb
|
151
152
|
- spec/unit/client_spec.rb
|
152
153
|
- spec/unit/events_spec.rb
|
153
154
|
- spec/unit/parser_spec.rb
|
@@ -178,3 +179,4 @@ signing_key:
|
|
178
179
|
specification_version: 3
|
179
180
|
summary: The HTTP toolkit
|
180
181
|
test_files: []
|
182
|
+
has_rdoc:
|