1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
require "test_helper"
using Plum::BinaryString
class ClientTest < Minitest::Test
def test_request_sync
server_thread = start_tls_server
client = Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE)
res1 = client.put!("/", "aaa", headers: { "header" => "ccc" })
assert_equal("PUTcccaaa", res1.body)
client.close
ensure
server_thread.join if server_thread
end
def test_request_async
res2 = nil
client = nil
server_thread = start_tls_server
Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) { |c|
client = c
res1 = client.request({ ":path" => "/", ":method" => "GET", ":scheme" => "https", "header" => "ccc" }, nil) { |res1|
assert(res1.headers)
}
assert_nil(res1.headers)
res2 = client.get("/", headers: { "header" => "ccc" })
assert_nil(res2.headers)
}
assert(res2.headers)
assert_equal("GETccc", res2.body)
ensure
server_thread.join if server_thread
end
def test_verify
client = nil
server_thread = start_tls_server
assert_raises(OpenSSL::SSL::SSLError) {
client = Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_PEER)
}
ensure
server_thread.join if server_thread
end
def test_raise_error_sync
client = nil
server_thread = start_tls_server
Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) { |c|
client = c
assert_raises(LocalConnectionError) {
client.get!("/connection_error")
}
}
ensure
server_thread.join if server_thread
end
def test_raise_error_async_seq_resume
server_thread = start_tls_server
client = Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE)
res = client.get("/error_in_data")
assert_raises(LocalConnectionError) {
client.resume(res)
}
client.close
ensure
server_thread.join if server_thread
end
def test_raise_error_async_block
client = nil
server_thread = start_tls_server
assert_raises(LocalConnectionError) {
Client.start("127.0.0.1", LISTEN_PORT, https: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) { |c|
client = c
client.get("/connection_error") { |res| flunk "success??" }
} # resume
}
ensure
server_thread.join if server_thread
end
def test_session_socket_http2_https
sock = StringSocket.new
client = Client.start(sock, nil, scheme: "https")
assert(client.session.class == ClientSession)
end
def test_session_socket_http2_http
sock = StringSocket.new("HTTP/1.1 100\r\n\r\n")
client = Client.start(sock, nil, scheme: "http")
assert(client.session.class == UpgradeClientSession)
end
private
def start_tls_server(&block)
ctx = OpenSSL::SSL::SSLContext.new
ctx.alpn_select_cb = -> protocols { "h2" }
ctx.cert = TLS_CERT
ctx.key = TLS_KEY
tcp_server = TCPServer.new("127.0.0.1", LISTEN_PORT)
ssl_server = OpenSSL::SSL::SSLServer.new(tcp_server, ctx)
server_thread = Thread.new {
plum = nil
begin
Timeout.timeout(1) {
sock = ssl_server.accept
plum = ServerConnection.new(sock.method(:write))
plum.on(:stream) { |stream|
headers = data = nil
stream.on(:headers) { |h|
headers = h.to_h }
stream.on(:data) { |d|
data = d }
stream.on(:end_stream) {
case headers[":path"]
when "/connection_error"
plum.goaway(:protocol_error)
when "/error_in_data"
stream.send_headers({ ":status" => 200 }, end_stream: false)
stream.send_data("a", end_stream: false)
raise ExampleError, "example error"
else
stream.send_headers({ ":status" => 200 }, end_stream: false)
stream.send_data(headers.to_h[":method"] + headers.to_h["header"].to_s + data.to_s, end_stream: true)
end } }
yield plum if block_given?
begin
while !sock.closed? && !sock.eof?
plum << sock.readpartial(1024)
end
rescue Errno::ECONNABORTED
# Ignore, this happens only when running on mingw64(?)
end
}
rescue OpenSSL::SSL::SSLError
rescue Timeout::Error
flunk "server timeout"
rescue ExampleError => e
plum.goaway(:internal_error) if plum
ensure
tcp_server.close
end
}
end
end
|