hatetepe 0.4.1 → 0.5.0.pre
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/examples/parallel_requests.rb +32 -0
- data/hatetepe.gemspec +3 -4
- data/lib/hatetepe/builder.rb +1 -0
- data/lib/hatetepe/cli.rb +11 -20
- data/lib/hatetepe/client.rb +210 -181
- data/lib/hatetepe/connection.rb +31 -12
- data/lib/hatetepe/server/keep_alive.rb +15 -53
- data/lib/hatetepe/server/pipeline.rb +14 -18
- data/lib/hatetepe/server/rack_app.rb +39 -0
- data/lib/hatetepe/server.rb +60 -108
- data/lib/hatetepe/version.rb +1 -1
- data/lib/rack/handler/hatetepe.rb +2 -0
- data/spec/integration/cli/start_spec.rb +84 -92
- data/spec/integration/client/keep_alive_spec.rb +5 -56
- data/spec/integration/client/timeout_spec.rb +93 -0
- data/spec/integration/server/keep_alive_spec.rb +8 -80
- data/spec/integration/server/timeout_spec.rb +45 -0
- data/spec/spec_helper.rb +7 -59
- data/spec/unit/client_spec.rb +68 -363
- data/spec/unit/connection_spec.rb +5 -7
- data/spec/unit/server_spec.rb +108 -338
- metadata +58 -43
- data/lib/hatetepe/client/keep_alive.rb +0 -32
- data/lib/hatetepe/client/pipeline.rb +0 -19
- data/lib/hatetepe/server/app.rb +0 -85
- data/lib/hatetepe/server/proxy.rb +0 -48
- data/spec/unit/app_spec.rb +0 -125
- data/spec/unit/client/pipeline_spec.rb +0 -40
- data/spec/unit/proxy_spec.rb +0 -145
@@ -1,61 +1,23 @@
|
|
1
|
-
|
1
|
+
module Hatetepe::Server
|
2
2
|
class KeepAlive
|
3
|
-
|
4
|
-
|
5
|
-
def initialize(app)
|
6
|
-
@app = app
|
3
|
+
def initialize(app, connection)
|
4
|
+
@app, @connection = app, connection
|
7
5
|
end
|
8
|
-
|
9
|
-
def call(
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
else env["HTTP_VERSION"] =~ /^HTTP\/(0\.9|1\.0)$/ ? :close : :keep_alive
|
6
|
+
|
7
|
+
def call(request, &respond)
|
8
|
+
@app.call(request) do |response|
|
9
|
+
respond.call(response)
|
10
|
+
maybe_close(request, response)
|
14
11
|
end
|
15
|
-
|
16
|
-
send :"call_and_#{m}", env
|
17
12
|
end
|
18
|
-
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
if response
|
27
|
-
response[1]["Connection"] = "close"
|
28
|
-
else
|
29
|
-
stream_start = env["stream.start"]
|
30
|
-
env["stream.start"] = proc do |res|
|
31
|
-
res[1]["Connection"] = "close"
|
32
|
-
stream_start.call res
|
33
|
-
end
|
13
|
+
|
14
|
+
def maybe_close(request, response)
|
15
|
+
version = request.http_version.to_f
|
16
|
+
header = request.headers["Connection"] || response.headers["Connection"]
|
17
|
+
|
18
|
+
if (version < 1.1 && header != "keep-alive") || header == "close"
|
19
|
+
@connection.stop!
|
34
20
|
end
|
35
|
-
|
36
|
-
response || app.call(env)
|
37
|
-
end
|
38
|
-
|
39
|
-
def call_and_keep_alive(env)
|
40
|
-
stream_start = env["stream.start"]
|
41
|
-
env["stream.start"] = proc do |res|
|
42
|
-
if res[1]["Connection"] == "close"
|
43
|
-
call_and_close env, res
|
44
|
-
else
|
45
|
-
res[1]["Connection"] = "keep-alive"
|
46
|
-
end
|
47
|
-
stream_start.call res
|
48
|
-
end
|
49
|
-
|
50
|
-
app.call env
|
51
|
-
end
|
52
|
-
|
53
|
-
def extract_request(env)
|
54
|
-
env["hatetepe.request"] || raise("env[hatetepe.request] not set")
|
55
|
-
end
|
56
|
-
|
57
|
-
def extract_connection(env)
|
58
|
-
env["hatetepe.connection"] || raise("env[hatetepe.connection] not set")
|
59
21
|
end
|
60
22
|
end
|
61
23
|
end
|
@@ -1,24 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Hatetepe::Server
|
4
|
-
# TODO move specs from server_spec.rb to server/pipeline_spec.rb
|
1
|
+
module Hatetepe::Server
|
5
2
|
class Pipeline
|
6
|
-
|
7
|
-
|
8
|
-
def initialize(app)
|
9
|
-
@app = app
|
3
|
+
def initialize(app, connection)
|
4
|
+
@requests, @app = [], app
|
10
5
|
end
|
11
|
-
|
12
|
-
def call(
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
6
|
+
|
7
|
+
def call(request, &respond)
|
8
|
+
begin
|
9
|
+
previous = @requests.last
|
10
|
+
@requests << request
|
11
|
+
@app.call(request) do |response|
|
12
|
+
EM::Synchrony.sync(previous) if previous
|
13
|
+
respond.call(response)
|
14
|
+
end
|
15
|
+
ensure
|
16
|
+
@requests.delete(request)
|
19
17
|
end
|
20
|
-
|
21
|
-
app.call env
|
22
18
|
end
|
23
19
|
end
|
24
20
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Hatetepe::Server
|
2
|
+
class RackApp
|
3
|
+
def initialize(app, connection)
|
4
|
+
@app, @connection = app, connection
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(request, &respond)
|
8
|
+
env = env_for(request)
|
9
|
+
env["async.callback"] = proc do |response|
|
10
|
+
async_callback(response, &respond)
|
11
|
+
end
|
12
|
+
|
13
|
+
response = [ -1 ]
|
14
|
+
catch :async do
|
15
|
+
response = @app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
async_callback(response, &respond)
|
19
|
+
end
|
20
|
+
|
21
|
+
def async_callback(response, &respond)
|
22
|
+
if response[0] >= 0
|
23
|
+
respond.call(Hatetepe::Response.new(*response))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def env_for(request)
|
28
|
+
request.to_h.merge({
|
29
|
+
"SERVER_NAME" => @connection.config[:host],
|
30
|
+
"SERVER_PORT" => @connection.config[:port].to_s,
|
31
|
+
"rack.errors" => $stderr,
|
32
|
+
"rack.multithread" => false,
|
33
|
+
"rack.multiprocess" => false,
|
34
|
+
"rack.run_once" => false,
|
35
|
+
"rack.url_scheme" => "http"
|
36
|
+
})
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/hatetepe/server.rb
CHANGED
@@ -1,137 +1,89 @@
|
|
1
1
|
require "eventmachine"
|
2
2
|
require "em-synchrony"
|
3
|
-
require "rack"
|
4
3
|
|
5
4
|
require "hatetepe/builder"
|
6
5
|
require "hatetepe/connection"
|
7
6
|
require "hatetepe/parser"
|
7
|
+
require "hatetepe/server/keep_alive"
|
8
|
+
require "hatetepe/server/pipeline"
|
9
|
+
require "hatetepe/server/rack_app"
|
8
10
|
require "hatetepe/version"
|
9
11
|
|
10
|
-
module Hatetepe
|
11
|
-
|
12
|
-
end
|
12
|
+
module Hatetepe::Server
|
13
|
+
include Hatetepe::Connection
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
require "hatetepe/server/proxy"
|
15
|
+
attr_reader :config, :requests
|
16
|
+
|
17
|
+
CONFIG_DEFAULTS = { :timeout => 5.0 }
|
18
18
|
|
19
|
-
|
19
|
+
# @api public
|
20
20
|
def self.start(config)
|
21
|
-
EM.start_server
|
21
|
+
EM.start_server(config[:host], config[:port], self, config)
|
22
22
|
end
|
23
|
-
|
24
|
-
attr_reader :app, :config, :errors
|
25
|
-
attr_reader :requests, :parser, :builder
|
26
|
-
|
27
|
-
def initialize(config)
|
28
|
-
@config = {:timeout => 1}.merge(config)
|
29
|
-
@errors = @config.delete(:errors) || $stderr
|
30
23
|
|
31
|
-
|
24
|
+
# @api semipublic
|
25
|
+
def initialize(config)
|
26
|
+
@config = CONFIG_DEFAULTS.merge(config)
|
32
27
|
end
|
33
|
-
|
28
|
+
|
29
|
+
# @api semipublic
|
34
30
|
def post_init
|
35
|
-
@requests = []
|
36
31
|
@parser, @builder = Hatetepe::Parser.new, Hatetepe::Builder.new
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
b.use Pipeline
|
48
|
-
b.use App
|
49
|
-
b.use KeepAlive
|
50
|
-
b.use Proxy
|
51
|
-
b.run config[:app]
|
52
|
-
end.to_app
|
53
|
-
|
54
|
-
self.processing_enabled = true
|
32
|
+
@parser.on_request &method(:process_request)
|
33
|
+
@builder.on_write &method(:send_data)
|
34
|
+
# @builder.on_write {|data| p "<--| #{data}" }
|
35
|
+
|
36
|
+
@app = [
|
37
|
+
Pipeline,
|
38
|
+
KeepAlive,
|
39
|
+
RackApp
|
40
|
+
].reverse.inject(config[:app]) {|inner, outer| outer.new(inner, self) }
|
41
|
+
|
55
42
|
self.comm_inactivity_timeout = config[:timeout]
|
56
43
|
end
|
57
|
-
|
44
|
+
|
45
|
+
# @api semipubic
|
58
46
|
def receive_data(data)
|
59
|
-
#p "
|
60
|
-
parser << data
|
61
|
-
rescue
|
47
|
+
# p "-->| #{data}"
|
48
|
+
@parser << data
|
49
|
+
rescue Object => ex
|
50
|
+
p ex
|
62
51
|
close_connection
|
63
|
-
raise ex if ENV["RACK_ENV"] == "testing"
|
64
|
-
rescue Exception => ex
|
65
|
-
close_connection_after_writing
|
66
|
-
backtrace = ex.backtrace.map {|line| "\t#{line}" }.join("\n")
|
67
|
-
errors << "#{ex.class}: #{ex.message}\n#{backtrace}\n"
|
68
|
-
errors.flush
|
69
|
-
raise ex if ENV["RACK_ENV"] == "testing"
|
70
52
|
end
|
71
|
-
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
53
|
+
|
54
|
+
# @api private
|
55
|
+
def process_request(request)
|
56
|
+
Fiber.new do
|
57
|
+
@app.call(request) do |response|
|
58
|
+
send_response(request, response)
|
59
|
+
end
|
60
|
+
end.resume
|
77
61
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
request = requests.last
|
82
|
-
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
def send_response(request, response)
|
83
65
|
self.comm_inactivity_timeout = 0
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
inject_environment e
|
92
|
-
e["stream.start"] = proc do |response|
|
93
|
-
e.delete "stream.start"
|
94
|
-
start_response response
|
95
|
-
end
|
96
|
-
e["stream.send"] = builder.method(:body_chunk)
|
97
|
-
e["stream.close"] = proc do
|
98
|
-
e.delete "stream.send"
|
99
|
-
e.delete "stream.close"
|
100
|
-
close_response request
|
101
|
-
end
|
66
|
+
@builder.response(response.to_a)
|
67
|
+
self.comm_inactivity_timeout = config[:timeout]
|
68
|
+
|
69
|
+
if response.failure?
|
70
|
+
request.fail(response)
|
71
|
+
else
|
72
|
+
request.succeed(response)
|
102
73
|
end
|
103
|
-
|
104
|
-
Fiber.new { app.call env }.resume
|
105
74
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
builder.headers response[1]
|
75
|
+
|
76
|
+
# @api semipublic
|
77
|
+
def unbind(reason)
|
78
|
+
super
|
111
79
|
end
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
requests.delete(request).succeed
|
80
|
+
|
81
|
+
# @api public
|
82
|
+
def stop
|
116
83
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
env["rack.input"].source = self
|
122
|
-
env["rack.errors"] = errors
|
123
|
-
|
124
|
-
env["rack.multithread"] = false
|
125
|
-
env["rack.multiprocess"] = false
|
126
|
-
env["rack.run_once"] = false
|
127
|
-
|
128
|
-
env["SERVER_NAME"] = config[:host].dup
|
129
|
-
env["SERVER_PORT"] = String(config[:port])
|
130
|
-
env["REMOTE_ADDR"] = remote_address.dup
|
131
|
-
env["REMOTE_PORT"] = String(remote_port)
|
132
|
-
|
133
|
-
host = env["HTTP_HOST"] || config[:host].dup
|
134
|
-
host += ":#{config[:port]}" unless host.include? ":"
|
135
|
-
env["HTTP_HOST"] = host
|
84
|
+
|
85
|
+
# @api public
|
86
|
+
def stop!
|
87
|
+
close_connection_after_writing
|
136
88
|
end
|
137
89
|
end
|
data/lib/hatetepe/version.rb
CHANGED
@@ -1,120 +1,112 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
require "hatetepe/cli"
|
3
|
+
require "hatetepe/server"
|
4
|
+
require "hatetepe/version"
|
5
|
+
require "rack/builder"
|
6
|
+
|
7
|
+
describe Hatetepe::CLI do
|
8
|
+
let :rackup do
|
9
|
+
[ proc {|*| }, {} ]
|
10
|
+
end
|
3
11
|
|
4
|
-
describe "The `hatetepe start' command" do
|
5
12
|
before do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
File.open "config.ru", "w" do |f|
|
12
|
-
f.write 'run proc {|env| [200, {}, ["Hello world!"]] }'
|
13
|
-
end
|
14
|
-
File.open "config2.ru", "w" do |f|
|
15
|
-
f.write 'run proc {|env| [501, {}, ["Herp derp"]] }'
|
16
|
-
end
|
13
|
+
file = File.expand_path("config.ru")
|
14
|
+
Rack::Builder.stub(:parse_file).with(file) { rackup }
|
15
|
+
|
16
|
+
$stdout, $stderr = StringIO.new, StringIO.new
|
17
|
+
@old_env = ENV.delete("RACK_ENV")
|
17
18
|
end
|
18
19
|
|
19
20
|
after do
|
20
|
-
$stderr = STDERR
|
21
|
-
|
22
|
-
FakeFS.deactivate!
|
23
|
-
FakeFS::FileSystem.clear
|
21
|
+
$stdout, $stderr = STDOUT, STDERR
|
22
|
+
ENV["RACK_ENV"] = @old_env
|
24
23
|
end
|
25
|
-
|
26
|
-
describe "
|
27
|
-
it "
|
28
|
-
|
29
|
-
|
24
|
+
|
25
|
+
describe "#version" do
|
26
|
+
it "prints Hatetepe's version" do
|
27
|
+
Hatetepe::CLI.start([ "version" ])
|
28
|
+
$stdout.rewind
|
29
|
+
$stdout.read.should include(Hatetepe::VERSION)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#start" do
|
34
|
+
it "starts a server running the default configuration" do
|
35
|
+
Hatetepe::Server.should_receive(:start) do |config|
|
36
|
+
config[:host].should == "127.0.0.1"
|
37
|
+
config[:port].should equal(3000)
|
38
|
+
config[:timeout].should == 5
|
39
|
+
|
40
|
+
config[:app].should equal(rackup[0])
|
30
41
|
ENV["RACK_ENV"].should == "development"
|
31
|
-
$stderr.string.should include("config.ru", "127.0.0.1:3000", "development")
|
32
42
|
end
|
43
|
+
Hatetepe::CLI.start([])
|
33
44
|
end
|
34
|
-
|
35
|
-
it "
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
response.body.read.should == "Hello world!"
|
40
|
-
end
|
41
|
-
end
|
45
|
+
|
46
|
+
it "writes stuff to stderr" do
|
47
|
+
Hatetepe::CLI.start([])
|
48
|
+
$stderr.rewind
|
49
|
+
$stderr.read.should include("config.ru", "127.0.0.1:3000", "development")
|
42
50
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
it "binds the Hatetepe::Server to the specified TCP port" do
|
48
|
-
command "#{opt} 3002" do
|
49
|
-
Socket.tcp("127.0.0.1", 3002) {|*| }
|
50
|
-
end
|
51
|
-
end
|
51
|
+
|
52
|
+
it "starts an EventMachine reactor" do
|
53
|
+
EM.should_receive(:synchrony)
|
54
|
+
Hatetepe::CLI.start([])
|
52
55
|
end
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
it "binds the Hatetepe::Server to the specified TCP interface" do
|
58
|
-
command "#{opt} 127.0.0.2" do
|
59
|
-
Socket.tcp("127.0.0.2", 3000) {|*| }
|
60
|
-
end
|
61
|
-
end
|
56
|
+
|
57
|
+
it "enables epoll" do
|
58
|
+
EM.should_receive(:epoll)
|
59
|
+
Hatetepe::CLI.start([])
|
62
60
|
end
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
61
|
+
|
62
|
+
it "doesn't overwrite RACK_ENV" do
|
63
|
+
ENV["RACK_ENV"] = "foobar"
|
64
|
+
Hatetepe::CLI.start([])
|
65
|
+
ENV["RACK_ENV"].should == "foobar"
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "with --bind option" do
|
69
|
+
it "passes the :host option to Server.start" do
|
70
|
+
Hatetepe::Server.should_receive(:start) do |config|
|
71
|
+
config[:host].should == "127.0.5.1"
|
73
72
|
end
|
73
|
+
Hatetepe::CLI.start([ "--bind", "127.0.5.1" ])
|
74
74
|
end
|
75
75
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
command "#{opt} herpderp" do
|
82
|
-
ENV["RACK_ENV"].should == "herpderp"
|
76
|
+
|
77
|
+
describe "with --port option" do
|
78
|
+
it "passes the :port option to Server.start" do
|
79
|
+
Hatetepe::Server.should_receive(:start) do |config|
|
80
|
+
config[:port].should == 5234
|
83
81
|
end
|
82
|
+
Hatetepe::CLI.start([ "--port", "5234" ])
|
84
83
|
end
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "with --timeout option" do
|
87
|
+
it "passes the :timeout option to Server.start" do
|
88
|
+
Hatetepe::Server.should_receive(:start) do |config|
|
89
|
+
config[:timeout].should == 123.4
|
91
90
|
end
|
91
|
+
Hatetepe::CLI.start([ "--timeout", "123.4" ])
|
92
92
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "with --rackup option" do
|
96
|
+
it "boots from the specified RackUp file" do
|
97
|
+
file = File.expand_path("./other_config.ru")
|
98
|
+
Rack::Builder.should_receive(:parse_file).with(file) { rackup }
|
99
|
+
Hatetepe::Server.should_receive(:start) do |config|
|
100
|
+
config[:app].should equal(rackup[0])
|
97
101
|
end
|
102
|
+
Hatetepe::CLI.start([ "--rackup", "other_config.ru" ])
|
98
103
|
end
|
99
104
|
end
|
100
|
-
end
|
101
|
-
|
102
|
-
["--timeout", "-t"].each do |opt|
|
103
|
-
describe "with #{opt} option" do
|
104
|
-
let :client do
|
105
|
-
Hatetepe::Client.start :host => "127.0.0.1", :port => 3000
|
106
|
-
end
|
107
|
-
|
108
|
-
it "times out a connection after the specified amount of seconds" do
|
109
|
-
command "#{opt} 0.5", 1 do
|
110
|
-
client.should_not be_closed
|
111
105
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
client.should be_closed_by_remote
|
117
|
-
end
|
106
|
+
describe "with --env option" do
|
107
|
+
it "sets RACK_ENV to the specified value" do
|
108
|
+
Hatetepe::CLI.start([ "--env", "production" ])
|
109
|
+
ENV["RACK_ENV"].should == "production"
|
118
110
|
end
|
119
111
|
end
|
120
112
|
end
|
@@ -5,70 +5,19 @@ require "stringio"
|
|
5
5
|
require "yaml"
|
6
6
|
|
7
7
|
describe Hatetepe::Client, "with Keep-Alive" do
|
8
|
-
before do
|
9
|
-
$stderr = StringIO.new
|
10
|
-
|
11
|
-
FakeFS.activate!
|
12
|
-
File.open "config.ru", "w" do |f|
|
13
|
-
f.write 'run proc {|env| [200,
|
14
|
-
{"Content_Type" => "text/plain"},
|
15
|
-
[env["HTTP_CONNECTION"]]] }'
|
16
|
-
end
|
17
|
-
File.open "config_close.ru", "w" do |f|
|
18
|
-
f.write 'run proc {|env| [200,
|
19
|
-
{"Content-Type" => "text/plain",
|
20
|
-
"Connection" => "close"},
|
21
|
-
[env["HTTP_CONNECTION"]]] }'
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
after do
|
26
|
-
$stderr = STDERR
|
27
|
-
|
28
|
-
FakeFS.deactivate!
|
29
|
-
FakeFS::FileSystem.clear
|
30
|
-
end
|
31
|
-
|
32
8
|
let :client do
|
33
9
|
Hatetepe::Client.start :host => "127.0.0.1", :port => 30001
|
34
10
|
end
|
35
11
|
|
36
|
-
it "keeps the connection open"
|
37
|
-
command "-p 30001", 2 do
|
38
|
-
client
|
39
|
-
EM::Synchrony.sleep 1.95
|
40
|
-
client.should_not be_closed_by_self
|
41
|
-
end
|
42
|
-
end
|
12
|
+
it "keeps the connection open"
|
43
13
|
|
44
|
-
it "sends Connection: keep-alive"
|
45
|
-
command "-p 30001" do
|
46
|
-
client.get("/").body.read.should == "keep-alive"
|
47
|
-
end
|
48
|
-
end
|
14
|
+
it "sends Connection: keep-alive"
|
49
15
|
|
50
16
|
describe "and an obviously single request" do
|
51
|
-
it "sends Connection: close"
|
52
|
-
command "-p 30001" do
|
53
|
-
Hatetepe::Client.get "http://127.0.0.1:30001/" do |response|
|
54
|
-
YAML.load(response.body.read).should == "close"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
17
|
+
it "sends Connection: close"
|
58
18
|
|
59
|
-
it "closes the connection immediately after the response"
|
60
|
-
command "-p 30001" do
|
61
|
-
#Hatetepe::Client.any_instance.should_receive :stop
|
62
|
-
Hatetepe::Client.get "http://127.0.0.1:30001/"
|
63
|
-
end
|
64
|
-
end
|
19
|
+
it "closes the connection immediately after the response"
|
65
20
|
end
|
66
21
|
|
67
|
-
it "closes the connection if the server tells it to"
|
68
|
-
#pending "Server can't send Conn: close as its Keep-Alive middleware overwrites it"
|
69
|
-
command "-p 30001 -r config_close.ru" do
|
70
|
-
client.get "/"
|
71
|
-
client.should be_closed
|
72
|
-
end
|
73
|
-
end
|
22
|
+
it "closes the connection if the server tells it to"
|
74
23
|
end
|