http2 0.0.29 → 0.0.34
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.
- checksums.yaml +5 -5
- data/README.md +131 -30
- data/Rakefile +20 -31
- data/lib/http2.rb +85 -67
- data/lib/http2/base_request.rb +22 -0
- data/{include → lib/http2}/connection.rb +56 -28
- data/lib/http2/cookie.rb +22 -0
- data/lib/http2/errors.rb +18 -0
- data/lib/http2/get_request.rb +33 -0
- data/{include → lib/http2}/post_data_generator.rb +7 -6
- data/{include → lib/http2}/post_multipart_request.rb +20 -20
- data/{include → lib/http2}/post_request.rb +17 -22
- data/lib/http2/response.rb +109 -0
- data/{include → lib/http2}/response_reader.rb +74 -41
- data/{include → lib/http2}/url_builder.rb +6 -6
- data/lib/http2/utils.rb +52 -0
- data/spec/helpers.rb +27 -0
- data/spec/http2/cookies_spec.rb +18 -0
- data/spec/http2/get_request_spec.rb +11 -0
- data/spec/http2/post_data_generator_spec.rb +2 -1
- data/spec/http2/post_multipart_request_spec.rb +11 -0
- data/spec/http2/post_request_spec.rb +11 -0
- data/spec/http2/response_reader_spec.rb +12 -0
- data/spec/http2/response_spec.rb +84 -8
- data/spec/http2/url_builder_spec.rb +1 -1
- data/spec/http2_spec.rb +104 -85
- data/spec/spec_helper.rb +9 -8
- data/spec/spec_root/content_type_test.rhtml +4 -0
- data/spec/spec_root/cookie_test.rhtml +8 -0
- data/spec/spec_root/json_test.rhtml +9 -0
- data/spec/spec_root/multipart_test.rhtml +28 -0
- data/spec/spec_root/redirect_test.rhtml +3 -0
- data/spec/spec_root/unauthorized.rhtml +3 -0
- data/spec/spec_root/unsupported_media_type.rhtml +3 -0
- metadata +131 -35
- data/.document +0 -5
- data/.rspec +0 -1
- data/Gemfile +0 -14
- data/Gemfile.lock +0 -77
- data/VERSION +0 -1
- data/http2.gemspec +0 -78
- data/include/errors.rb +0 -11
- data/include/get_request.rb +0 -34
- data/include/response.rb +0 -73
- data/include/utils.rb +0 -40
- data/shippable.yml +0 -9
data/spec/helpers.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Helpers
|
2
|
+
def with_webserver
|
3
|
+
require "hayabusa"
|
4
|
+
hayabusa = Hayabusa.new(
|
5
|
+
doc_root: "#{File.dirname(__FILE__)}/spec_root",
|
6
|
+
port: 3005
|
7
|
+
)
|
8
|
+
hayabusa.start
|
9
|
+
|
10
|
+
begin
|
11
|
+
yield(hayabusa)
|
12
|
+
ensure
|
13
|
+
hayabusa.stop
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_http(args = {})
|
18
|
+
with_webserver do |hayabusa|
|
19
|
+
Http2.new({host: "localhost", port: hayabusa.port, encoding_gzip: false}.merge(args)) do |http|
|
20
|
+
yield http
|
21
|
+
end
|
22
|
+
rescue Http2::Errors::Internalserver => e
|
23
|
+
puts "Body of error-response: #{e.response.body}"
|
24
|
+
raise e
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Http2 do
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
it "should parse cookies and let them be read" do
|
7
|
+
with_http do |http|
|
8
|
+
http.get("cookie_test.rhtml")
|
9
|
+
expect(http.cookies.length).to eq 2
|
10
|
+
|
11
|
+
cookie = http.cookie("TestCookie")
|
12
|
+
expect(cookie.name).to eq "TestCookie"
|
13
|
+
expect(cookie.value).to eq "TestValue"
|
14
|
+
expect(cookie.path).to eq "/"
|
15
|
+
expect(cookie.expires).to be > Time.now
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Http2::GetRequest do
|
4
|
+
it "reads the headers from the request" do
|
5
|
+
with_http do |http|
|
6
|
+
res = http.get("content_type_test.rhtml")
|
7
|
+
headers = res.request.headers_string
|
8
|
+
expect(headers).to include "GET /content_type_test.rhtml"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -19,6 +19,7 @@ describe Http2::PostDataGenerator do
|
|
19
19
|
}
|
20
20
|
}
|
21
21
|
).generate
|
22
|
-
|
22
|
+
|
23
|
+
expect(res).to eq "test1%5Border%5D%5B%5B%3ABnet_profile%2C+%22profile_id%22%5D%5D=5"
|
23
24
|
end
|
24
25
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Http2::PostMultipartRequest do
|
4
|
+
it "reads the headers from the request" do
|
5
|
+
with_http do |http|
|
6
|
+
res = http.post_multipart(url: "json_test.rhtml", post: {"test1" => "test2"})
|
7
|
+
headers = res.request.headers_string
|
8
|
+
expect(headers).to include "POST /json_test.rhtml"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Http2::PostRequest do
|
4
|
+
it "reads the headers from the request" do
|
5
|
+
with_http do |http|
|
6
|
+
res = http.post(url: "json_test.rhtml", json: {testkey: "testvalue"})
|
7
|
+
headers = res.request.headers_string
|
8
|
+
expect(headers).to include "POST /json_test.rhtml"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Http2::ResponseReader do
|
4
|
+
it "#url_and_args_from_location" do
|
5
|
+
with_http(ssl_skip_verify: true, follow_redirects: true) do |http|
|
6
|
+
response = http.get("redirect_test.rhtml?redirect_to=https://www.google.dk")
|
7
|
+
expect(response.host).to eq "www.google.dk"
|
8
|
+
expect(response.ssl?).to eq true
|
9
|
+
expect(response.port).to eq 443
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/spec/http2/response_spec.rb
CHANGED
@@ -1,17 +1,93 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Http2::Response do
|
4
|
-
it "
|
5
|
-
|
6
|
-
res = http.get("content_type_test.
|
7
|
-
res.content_type.
|
4
|
+
it "#content_type" do
|
5
|
+
with_http do |http|
|
6
|
+
res = http.get("content_type_test.rhtml")
|
7
|
+
expect(res.content_type).to eq "text/html"
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
it "
|
12
|
-
|
13
|
-
res = http.get("content_type_test.
|
14
|
-
res.content_length.
|
11
|
+
it "#content_length" do
|
12
|
+
with_http do |http|
|
13
|
+
res = http.get("content_type_test.rhtml")
|
14
|
+
expect(res.content_length).to be > 50
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#json?" do
|
19
|
+
it "returns true for 'application/json'" do
|
20
|
+
with_http do |http|
|
21
|
+
res = http.get("json_test.rhtml")
|
22
|
+
|
23
|
+
expect(res).to receive(:content_type).and_return("application/json")
|
24
|
+
expect(res.json?).to eq true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns true for 'application/json'" do
|
29
|
+
with_http do |http|
|
30
|
+
res = http.get("json_test.rhtml")
|
31
|
+
expect(res.json?).to eq true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns true for 'application/json'" do
|
36
|
+
with_http do |http|
|
37
|
+
res = http.post(url: "json_test.rhtml", post: {test: "test2"})
|
38
|
+
|
39
|
+
expect(res).to receive(:content_type).and_return("application/json; charset=utf-8")
|
40
|
+
expect(res.json?).to eq true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "#host" do
|
46
|
+
with_http do |http|
|
47
|
+
res = http.get("json_test.rhtml")
|
48
|
+
expect(res.host).to eq "localhost"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "#port" do
|
53
|
+
with_http do |http|
|
54
|
+
res = http.get("json_test.rhtml")
|
55
|
+
expect(res.port).to eq http.port
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "#ssl?" do
|
60
|
+
with_http do |http|
|
61
|
+
res = http.get("json_test.rhtml")
|
62
|
+
expect(res.ssl?).to eq false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "#path" do
|
67
|
+
with_http do |http|
|
68
|
+
res = http.get("json_test.rhtml")
|
69
|
+
expect(res.path).to eq "json_test.rhtml"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "#header" do
|
74
|
+
with_http do |http|
|
75
|
+
res = http.get("json_test.rhtml")
|
76
|
+
expect(res.header("connection")).to eq "Keep-Alive"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it "#header?" do
|
81
|
+
with_http do |http|
|
82
|
+
res = http.get("json_test.rhtml")
|
83
|
+
expect(res.header?("connection")).to eq true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "#json" do
|
88
|
+
with_http do |http|
|
89
|
+
res = http.post(url: "json_test.rhtml", post: {test: "test2"})
|
90
|
+
expect(res.json["_POST"]).to eq("test" => "test2")
|
15
91
|
end
|
16
92
|
end
|
17
93
|
end
|
@@ -11,7 +11,7 @@ describe Http2::UrlBuilder do
|
|
11
11
|
ub.params["test"] = "true"
|
12
12
|
ub.params["test2"] = "false"
|
13
13
|
|
14
|
-
ub.build.
|
14
|
+
expect(ub.build).to eq "https://www.github.com:443/index.php?test=true&test2=false"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/spec/http2_spec.rb
CHANGED
@@ -3,154 +3,173 @@ require "json"
|
|
3
3
|
|
4
4
|
describe "Http2" do
|
5
5
|
it "should be able to do normal post-requests." do
|
6
|
-
#Test posting keep-alive and advanced post-data.
|
7
|
-
|
6
|
+
# Test posting keep-alive and advanced post-data.
|
7
|
+
with_http do |http|
|
8
8
|
0.upto(5) do
|
9
|
-
|
10
|
-
|
11
|
-
resp = http.post(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
9
|
+
http.get("multipart_test.rhtml")
|
10
|
+
|
11
|
+
resp = http.post(
|
12
|
+
url: "multipart_test.rhtml?choice=post-test",
|
13
|
+
post: {
|
14
|
+
"val1" => "test1",
|
15
|
+
"val2" => "test2",
|
16
|
+
"val3" => [
|
17
|
+
"test3"
|
18
|
+
],
|
19
|
+
"val4" => {
|
20
|
+
"val5" => "test5"
|
21
|
+
},
|
22
|
+
"val6" => {
|
23
|
+
"val7" => [
|
24
|
+
{
|
25
|
+
"val8" => "test8"
|
26
|
+
}
|
27
|
+
]
|
28
|
+
},
|
29
|
+
"val9" => %w[a b d]
|
30
|
+
}
|
31
|
+
)
|
29
32
|
res = JSON.parse(resp.body)
|
30
33
|
|
31
|
-
res.is_a?(Hash).
|
32
|
-
res["val1"].
|
33
|
-
res["val2"].
|
34
|
-
res["val3"][0].
|
35
|
-
res["val4"]["val5"].
|
36
|
-
res["val6"]["val7"][0]["val8"].
|
37
|
-
res["val9"][0].
|
38
|
-
res["val9"][1].
|
39
|
-
res["val9"][2].
|
34
|
+
expect(res.is_a?(Hash)).to eq true
|
35
|
+
expect(res["val1"]).to eq "test1"
|
36
|
+
expect(res["val2"]).to eq "test2"
|
37
|
+
expect(res["val3"]["0"]).to eq "test3"
|
38
|
+
expect(res["val4"]["val5"]).to eq "test5"
|
39
|
+
expect(res["val6"]["val7"]["0"]["val8"]).to eq "test8"
|
40
|
+
expect(res["val9"]["0"]).to eq "a"
|
41
|
+
expect(res["val9"]["1"]).to eq "b"
|
42
|
+
expect(res["val9"]["2"]).to eq "d"
|
40
43
|
end
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
44
47
|
it "#reconnect" do
|
45
|
-
|
46
|
-
resp1 = http.get("multipart_test.
|
48
|
+
with_http(follow_redirects: false, encoding_gzip: false) do |http|
|
49
|
+
resp1 = http.get("multipart_test.rhtml")
|
47
50
|
http.reconnect
|
48
|
-
resp2 = http.get("multipart_test.
|
51
|
+
resp2 = http.get("multipart_test.rhtml")
|
49
52
|
|
50
|
-
resp1.body.
|
53
|
+
expect(resp1.body).to eq resp2.body
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
54
57
|
it "should be able to do multipart-requests and keep-alive when using multipart." do
|
55
|
-
|
58
|
+
with_http(follow_redirects: false) do |http|
|
56
59
|
0.upto(5) do
|
57
60
|
fpath = File.realpath(__FILE__)
|
58
61
|
fpath2 = "#{File.realpath(File.dirname(__FILE__))}/../lib/http2.rb"
|
59
62
|
|
60
|
-
resp = http.post_multipart(
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
resp = http.post_multipart(
|
64
|
+
url: "multipart_test.rhtml",
|
65
|
+
post: {
|
66
|
+
"test_var" => "true",
|
67
|
+
"test_file1" => {
|
68
|
+
fpath: fpath,
|
69
|
+
filename: "specfile"
|
70
|
+
},
|
71
|
+
"test_file2" => {
|
72
|
+
fpath: fpath2,
|
73
|
+
filename: "http2.rb"
|
74
|
+
}
|
69
75
|
}
|
70
|
-
|
76
|
+
)
|
71
77
|
|
72
78
|
data = JSON.parse(resp.body)
|
73
79
|
|
74
|
-
data["post"]["test_var"].
|
75
|
-
data["files_data"]["test_file1"].
|
76
|
-
data["files_data"]["test_file2"].
|
80
|
+
expect(data["post"]["test_var"]).to eq "true"
|
81
|
+
expect(data["files_data"]["test_file1"]).to eq File.read(fpath)
|
82
|
+
expect(data["files_data"]["test_file2"]).to eq File.read(fpath2)
|
77
83
|
end
|
78
84
|
end
|
79
85
|
end
|
80
86
|
|
81
87
|
it "it should be able to handle keep-alive correctly" do
|
82
88
|
urls = [
|
83
|
-
"
|
84
|
-
"
|
85
|
-
"?show=drinksdb",
|
86
|
-
"?show=forum&fid=9&tid=1917&page=0"
|
89
|
+
"content_type_test.rhtml",
|
90
|
+
"json_test.rhtml"
|
87
91
|
]
|
88
|
-
urls = ["robots.txt"]
|
89
92
|
|
90
|
-
|
91
|
-
0.upto(105) do |
|
93
|
+
with_http do |http|
|
94
|
+
0.upto(105) do |_count|
|
92
95
|
url = urls[rand(urls.size)]
|
93
|
-
#
|
96
|
+
# puts "Doing request #{count} of 200 (#{url})."
|
94
97
|
res = http.get(url)
|
95
|
-
res.body.to_s.length.
|
98
|
+
expect(res.body.to_s.length).to be > 0
|
96
99
|
end
|
97
100
|
end
|
98
101
|
end
|
99
102
|
|
100
|
-
it "should be able to convert URL's to 'is.gd'-short-urls" do
|
101
|
-
isgd = Http2.isgdlink("https://github.com/kaspernj/http2")
|
102
|
-
raise "Expected isgd-var to be valid but it wasnt: '#{isgd}'." if !isgd.match(/^http:\/\/is\.gd\/([A-z\d]+)$/)
|
103
|
-
end
|
104
|
-
|
105
103
|
it "should raise exception when something is not found" do
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
110
|
-
}.to raise_error(::Http2::Errors::Notfound)
|
104
|
+
with_http do |http|
|
105
|
+
expect { http.get("something_that_does_not_exist.rhtml") }.to raise_error(::Http2::Errors::Notfound)
|
106
|
+
end
|
111
107
|
end
|
112
108
|
|
113
109
|
it "should be able to post json" do
|
114
|
-
|
110
|
+
with_http do |http|
|
115
111
|
res = http.post(
|
116
|
-
url: "
|
112
|
+
url: "json_test.rhtml",
|
117
113
|
json: {testkey: "testvalue"}
|
118
114
|
)
|
119
115
|
|
120
116
|
data = JSON.parse(res.body)
|
121
|
-
data["_SERVER"]["
|
122
|
-
|
117
|
+
expect(data["_SERVER"]["HTTP_CONTENT_TYPE"]).to eq "application/json"
|
118
|
+
|
119
|
+
# Hack JSON data from Hayabusa.
|
120
|
+
json_data = JSON.parse(data["_POST"].keys.first)
|
121
|
+
expect(json_data["testkey"]).to eq "testvalue"
|
122
|
+
|
123
|
+
expect(res.content_type).to eq "application/json"
|
124
|
+
expect(res.json?).to eq true
|
125
|
+
expect(res.json["_SERVER"]["REQUEST_METHOD"]).to eq "POST"
|
123
126
|
end
|
124
127
|
end
|
125
128
|
|
126
129
|
it "should be able to post custom content types" do
|
127
|
-
|
128
|
-
|
129
|
-
Http2.new(host: "http2test.kaspernj.org") do |http|
|
130
|
+
with_http do |http|
|
130
131
|
res = http.post(
|
131
|
-
url: "content_type_test.
|
132
|
+
url: "content_type_test.rhtml",
|
132
133
|
content_type: "plain/text",
|
133
134
|
post: "test1_test2_test3"
|
134
135
|
)
|
135
136
|
|
136
137
|
data = JSON.parse(res.body)
|
137
|
-
data["_SERVER"]["
|
138
|
-
|
138
|
+
expect(data["_SERVER"]["HTTP_CONTENT_TYPE"]).to eq "plain/text"
|
139
|
+
|
140
|
+
raw_data = data["_POST"].keys.first
|
141
|
+
expect(raw_data).to eq "test1_test2_test3"
|
139
142
|
end
|
140
143
|
end
|
141
144
|
|
142
145
|
it "should set various timeouts" do
|
143
|
-
|
144
|
-
|
145
|
-
http.keepalive_timeout.
|
146
|
-
http.keepalive_max.
|
146
|
+
with_http do |http|
|
147
|
+
http.get("content_type_test.rhtml")
|
148
|
+
expect(http.keepalive_timeout).to eq 15
|
149
|
+
expect(http.keepalive_max).to eq 30
|
147
150
|
end
|
148
151
|
end
|
149
152
|
|
150
153
|
it "should follow redirects" do
|
151
|
-
|
152
|
-
resp = http.get("redirect_test.
|
153
|
-
resp.code.
|
154
|
+
with_http(follow_redirects: true) do |http|
|
155
|
+
resp = http.get("redirect_test.rhtml")
|
156
|
+
expect(resp.code).to eq "200"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
it "throws errors on unauhtorized" do
|
161
|
+
with_http do |http|
|
162
|
+
expect do
|
163
|
+
http.get("unauthorized.rhtml")
|
164
|
+
end.to raise_error(Http2::Errors::Unauthorized)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
it "throws errors on unsupported media type" do
|
169
|
+
with_http do |http|
|
170
|
+
expect do
|
171
|
+
http.get("unsupported_media_type.rhtml")
|
172
|
+
end.to raise_error(Http2::Errors::UnsupportedMediaType)
|
154
173
|
end
|
155
174
|
end
|
156
175
|
end
|