http2 0.0.31 → 0.0.35
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 +15 -2
- data/Rakefile +18 -17
- data/lib/http2/base_request.rb +22 -0
- data/{include → lib/http2}/connection.rb +21 -10
- data/{include → lib/http2}/cookie.rb +4 -1
- 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 +13 -29
- data/{include → lib/http2}/response.rb +48 -35
- data/{include → lib/http2}/response_reader.rb +61 -41
- data/{include → lib/http2}/url_builder.rb +5 -5
- data/{include → lib/http2}/utils.rb +12 -10
- data/lib/http2.rb +43 -37
- data/spec/helpers.rb +4 -6
- data/spec/http2/cookies_spec.rb +6 -6
- 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 +80 -4
- data/spec/http2/url_builder_spec.rb +1 -1
- data/spec/http2_spec.rb +81 -66
- data/spec/spec_helper.rb +7 -9
- data/spec/spec_root/redirect_test.rhtml +1 -1
- data/spec/spec_root/unauthorized.rhtml +3 -0
- data/spec/spec_root/unsupported_media_type.rhtml +3 -0
- metadata +82 -42
- data/include/errors.rb +0 -11
- data/include/get_request.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ff94aecdfbfa493bb62b38edeef5a2bf49f9b5fb16ce5f023e6928ed77cb21c7
|
4
|
+
data.tar.gz: d8858f9e7daf39ed428311db9af0d561c971780d249cf0d0932a36962c921884
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04205c61f20290a3dec42a1c7a78b380ac749e0245ea53ba13f1a65cc983140e486a73fd26bf1e8a6ad808cde9a97d98ab9ba982f984726386d0b6db201da8d3
|
7
|
+
data.tar.gz: 413150d064f99e448cfcb0cca6380a6677b8e525ffcbbdaebfd957b5b7a6c263aeb105562ffcb6e8584603fd097a7fcfbda13327a662d7ba9927ad2e0d077afa
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
[](https://app.shippable.com/projects/540e7b9b3479c5ea8f9ec21d/builds/latest)
|
2
1
|
[](https://codeclimate.com/github/kaspernj/http2)
|
3
|
-
[](https://www.peakflow.io/en/projects/http2/build-groups)
|
4
4
|
|
5
5
|
# http2
|
6
6
|
|
@@ -36,6 +36,11 @@ You can also use SSL:
|
|
36
36
|
Http2.new(host: "myhost.com", ssl: true, ssl_skip_verify: true)
|
37
37
|
```
|
38
38
|
|
39
|
+
You can make it follow redirects like this:
|
40
|
+
```ruby
|
41
|
+
Http2.new(host: "myhost.com", follow_redirects: true)
|
42
|
+
```
|
43
|
+
|
39
44
|
## Get requests
|
40
45
|
```ruby
|
41
46
|
res = http.get("path/to/something")
|
@@ -155,6 +160,14 @@ http = Http2.new(
|
|
155
160
|
)
|
156
161
|
```
|
157
162
|
|
163
|
+
## Inspect the headers that were sent
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
response = http.get("some_page")
|
167
|
+
request = response.request
|
168
|
+
request.headers_string #=> "GET /some_page\n..."
|
169
|
+
```
|
170
|
+
|
158
171
|
## Contributing to http2
|
159
172
|
|
160
173
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
data/Rakefile
CHANGED
@@ -1,37 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
5
3
|
begin
|
6
4
|
Bundler.setup(:default, :development)
|
7
5
|
rescue Bundler::BundlerError => e
|
8
|
-
|
9
|
-
|
6
|
+
warn e.message
|
7
|
+
warn "Run `bundle install` to install missing gems"
|
10
8
|
exit e.status_code
|
11
9
|
end
|
12
|
-
require
|
10
|
+
require "rake"
|
13
11
|
|
14
|
-
require
|
15
|
-
require
|
12
|
+
require "rspec/core"
|
13
|
+
require "rspec/core/rake_task"
|
16
14
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
17
|
-
spec.pattern = FileList[
|
15
|
+
spec.pattern = FileList["spec/**/*_spec.rb"]
|
18
16
|
end
|
19
17
|
|
20
18
|
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
21
|
-
spec.pattern =
|
19
|
+
spec.pattern = "spec/**/*_spec.rb"
|
22
20
|
spec.rcov = true
|
23
21
|
end
|
24
22
|
|
25
|
-
task :
|
23
|
+
task default: :spec
|
26
24
|
|
27
|
-
require
|
25
|
+
require "rdoc/task"
|
28
26
|
Rake::RDocTask.new do |rdoc|
|
29
|
-
version = File.exist?(
|
27
|
+
version = File.exist?("VERSION") ? File.read("VERSION") : ""
|
30
28
|
|
31
|
-
rdoc.rdoc_dir =
|
29
|
+
rdoc.rdoc_dir = "rdoc"
|
32
30
|
rdoc.title = "http2 #{version}"
|
33
|
-
rdoc.rdoc_files.include(
|
34
|
-
rdoc.rdoc_files.include(
|
31
|
+
rdoc.rdoc_files.include("README*")
|
32
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
35
33
|
end
|
36
34
|
|
37
35
|
Bundler::GemHelper.install_tasks
|
36
|
+
|
37
|
+
require "best_practice_project"
|
38
|
+
BestPracticeProject.load_tasks
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Http2::BaseRequest
|
2
|
+
attr_reader :http2, :args, :debug
|
3
|
+
|
4
|
+
VALID_ARGUMENTS_POST = [:post, :url, :default_headers, :headers, :json, :method, :cookies, :on_content, :content_type].freeze
|
5
|
+
|
6
|
+
def initialize(http2, args)
|
7
|
+
@http2 = http2
|
8
|
+
@args = http2.parse_args(args)
|
9
|
+
@debug = http2.debug
|
10
|
+
@nl = http2.nl
|
11
|
+
|
12
|
+
@args.each_key do |key|
|
13
|
+
raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_POST.include?(key)
|
14
|
+
end
|
15
|
+
|
16
|
+
@conn = @http2.connection
|
17
|
+
end
|
18
|
+
|
19
|
+
def path
|
20
|
+
@args.fetch(:url)
|
21
|
+
end
|
22
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
class Http2::Connection
|
2
2
|
def initialize(http2)
|
3
|
-
@http2
|
3
|
+
@http2 = http2
|
4
|
+
@debug = http2.debug
|
5
|
+
@args = http2.args
|
6
|
+
@nl = http2.nl
|
4
7
|
reconnect
|
5
8
|
end
|
6
9
|
|
@@ -23,10 +26,6 @@ class Http2::Connection
|
|
23
26
|
@sock.read(length)
|
24
27
|
end
|
25
28
|
|
26
|
-
def close
|
27
|
-
@sock.close
|
28
|
-
end
|
29
|
-
|
30
29
|
def closed?
|
31
30
|
@sock.closed?
|
32
31
|
end
|
@@ -34,6 +33,7 @@ class Http2::Connection
|
|
34
33
|
def sock_write(str)
|
35
34
|
str = str.to_s
|
36
35
|
return if str.empty?
|
36
|
+
|
37
37
|
count = @sock.write(str)
|
38
38
|
raise "Couldnt write to socket: '#{count}', '#{str}'." if count <= 0
|
39
39
|
end
|
@@ -46,10 +46,13 @@ class Http2::Connection
|
|
46
46
|
def write(str)
|
47
47
|
reconnect unless socket_working?
|
48
48
|
|
49
|
+
puts "Http2: Writing: #{str}" if @debug
|
50
|
+
|
49
51
|
begin
|
50
52
|
raise Errno::EPIPE, "The socket is closed." if !@sock || @sock.closed?
|
53
|
+
|
51
54
|
sock_write(str)
|
52
|
-
rescue Errno::EPIPE #this can also be thrown by puts.
|
55
|
+
rescue Errno::EPIPE # this can also be thrown by puts.
|
53
56
|
reconnect
|
54
57
|
sock_write(str)
|
55
58
|
end
|
@@ -61,7 +64,7 @@ class Http2::Connection
|
|
61
64
|
def reconnect
|
62
65
|
puts "Http2: Reconnect." if @debug
|
63
66
|
|
64
|
-
#Open connection.
|
67
|
+
# Open connection.
|
65
68
|
if @args[:proxy]
|
66
69
|
if @args[:proxy][:connect]
|
67
70
|
connect_proxy_connect
|
@@ -84,7 +87,7 @@ class Http2::Connection
|
|
84
87
|
#===Examples
|
85
88
|
# puts "Socket is working." if http.socket_working?
|
86
89
|
def socket_working?
|
87
|
-
return false if !@sock
|
90
|
+
return false if !@sock || @sock.closed?
|
88
91
|
|
89
92
|
if @keepalive_timeout && @request_last
|
90
93
|
between = Time.now.to_i - @request_last.to_i
|
@@ -94,7 +97,7 @@ class Http2::Connection
|
|
94
97
|
end
|
95
98
|
end
|
96
99
|
|
97
|
-
|
100
|
+
true
|
98
101
|
end
|
99
102
|
|
100
103
|
# Closes the current connection if any.
|
@@ -130,6 +133,7 @@ class Http2::Connection
|
|
130
133
|
|
131
134
|
res = @sock_plain.gets.to_s
|
132
135
|
raise "Couldn't connect through proxy: #{res}" unless res.match(/^http\/1\.(0|1)\s+200/i)
|
136
|
+
|
133
137
|
@sock_plain.gets
|
134
138
|
|
135
139
|
@proxy_connect = true
|
@@ -149,8 +153,15 @@ class Http2::Connection
|
|
149
153
|
require "openssl" unless ::Kernel.const_defined?(:OpenSSL)
|
150
154
|
|
151
155
|
ssl_context = OpenSSL::SSL::SSLContext.new
|
152
|
-
|
156
|
+
|
157
|
+
if @args[:ssl_skip_verify]
|
158
|
+
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
159
|
+
else
|
160
|
+
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
161
|
+
end
|
162
|
+
|
153
163
|
@sock_ssl = OpenSSL::SSL::SSLSocket.new(@sock_plain, ssl_context)
|
164
|
+
@sock_ssl.hostname = @http2.host
|
154
165
|
@sock_ssl.sync_close = true
|
155
166
|
@sock_ssl.connect
|
156
167
|
|
@@ -2,7 +2,10 @@ class Http2::Cookie
|
|
2
2
|
attr_reader :name, :value, :path, :expires_raw
|
3
3
|
|
4
4
|
def initialize(args)
|
5
|
-
@name
|
5
|
+
@name = args[:name]
|
6
|
+
@value = args[:value]
|
7
|
+
@path = args[:path]
|
8
|
+
@expires_raw = args[:expires]
|
6
9
|
end
|
7
10
|
|
8
11
|
def inspect
|
data/lib/http2/errors.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# This class holds various classes for error-handeling.
|
2
|
+
class Http2::Errors
|
3
|
+
class BaseError < RuntimeError
|
4
|
+
attr_accessor :response
|
5
|
+
end
|
6
|
+
|
7
|
+
class Noaccess < BaseError; end
|
8
|
+
|
9
|
+
class Internalserver < BaseError; end
|
10
|
+
|
11
|
+
class Notfound < BaseError; end
|
12
|
+
|
13
|
+
class Badrequest < BaseError; end
|
14
|
+
|
15
|
+
class Unauthorized < BaseError; end
|
16
|
+
|
17
|
+
class UnsupportedMediaType < BaseError; end
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Http2::GetRequest < Http2::BaseRequest
|
2
|
+
def execute
|
3
|
+
@http2.mutex.synchronize do
|
4
|
+
@http2.connection.write(headers_string)
|
5
|
+
|
6
|
+
puts "Http2: Reading response." if @debug
|
7
|
+
resp = @http2.read_response(self, @args)
|
8
|
+
|
9
|
+
puts "Http2: Done with get request." if @debug
|
10
|
+
return resp
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def headers_string
|
15
|
+
unless @header_str
|
16
|
+
@header_str = "#{method} /#{@args[:url]} HTTP/1.1#{@nl}"
|
17
|
+
@header_str << @http2.header_str(@http2.default_headers(@args))
|
18
|
+
@header_str << @nl
|
19
|
+
end
|
20
|
+
|
21
|
+
@header_str
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def method
|
27
|
+
if @args[:method]
|
28
|
+
@args[:method].to_s.upcase
|
29
|
+
else
|
30
|
+
"GET"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
class Http2::PostDataGenerator
|
2
2
|
def initialize(pdata, args = {})
|
3
|
-
@pdata
|
3
|
+
@pdata = pdata
|
4
|
+
@args = args
|
4
5
|
end
|
5
6
|
|
6
7
|
def generate
|
@@ -14,7 +15,7 @@ class Http2::PostDataGenerator
|
|
14
15
|
return @pdata.to_s
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
+
praw
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
@@ -22,7 +23,7 @@ private
|
|
22
23
|
def generate_for_hash(hash)
|
23
24
|
praw = ""
|
24
25
|
|
25
|
-
|
26
|
+
hash.each do |key, val|
|
26
27
|
praw << "&" if praw != ""
|
27
28
|
key = "#{@args[:orig_key]}[#{key}]" if @args[:orig_key]
|
28
29
|
praw << generate_key_value(key, val)
|
@@ -35,7 +36,7 @@ private
|
|
35
36
|
praw = ""
|
36
37
|
|
37
38
|
count = 0
|
38
|
-
|
39
|
+
array.each do |val|
|
39
40
|
praw << "&" if praw != ""
|
40
41
|
|
41
42
|
if @args[:orig_key]
|
@@ -53,10 +54,10 @@ private
|
|
53
54
|
|
54
55
|
def generate_key_value(key, value)
|
55
56
|
if value.is_a?(Hash) || value.is_a?(Array)
|
56
|
-
|
57
|
+
::Http2::PostDataGenerator.new(value, orig_key: key).generate
|
57
58
|
else
|
58
59
|
data = ::Http2::PostDataGenerator.new(value).generate
|
59
|
-
|
60
|
+
"#{Http2::Utils.urlenc(key)}=#{Http2::Utils.urlenc(data)}"
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
@@ -1,42 +1,44 @@
|
|
1
1
|
require "tempfile"
|
2
2
|
|
3
|
-
class Http2::PostMultipartRequest
|
3
|
+
class Http2::PostMultipartRequest < Http2::BaseRequest
|
4
|
+
attr_reader :headers_string
|
5
|
+
|
4
6
|
def initialize(http2, *args)
|
5
|
-
|
7
|
+
super
|
8
|
+
|
6
9
|
@phash = @args[:post].clone
|
7
10
|
@http2.autostate_set_on_post_hash(phash) if @http2.autostate
|
8
11
|
@boundary = rand(36**50).to_s(36)
|
9
|
-
@conn = @http2.connection
|
10
12
|
end
|
11
13
|
|
12
14
|
def execute
|
13
|
-
generate_raw(@phash) do |
|
14
|
-
puts "Http2: Header string: #{header_string}" if @debug
|
15
|
-
|
15
|
+
generate_raw(@phash) do |_helper, praw|
|
16
16
|
@http2.mutex.synchronize do
|
17
|
-
@conn.write(
|
17
|
+
@conn.write(header_string_with_raw_post(praw))
|
18
18
|
|
19
19
|
praw.rewind
|
20
20
|
praw.each_line do |data|
|
21
21
|
@conn.sock_write(data)
|
22
22
|
end
|
23
23
|
|
24
|
-
return @http2.read_response(@args)
|
24
|
+
return @http2.read_response(self, @args)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
31
|
+
def header_string_with_raw_post(praw)
|
32
|
+
@headers_string = "POST /#{@args[:url]} HTTP/1.1#{@nl}"
|
33
|
+
|
34
|
+
headers = @http2.default_headers(@args).merge(
|
34
35
|
"Content-Type" => "multipart/form-data; boundary=#{@boundary}",
|
35
36
|
"Content-Length" => praw.size
|
36
|
-
)
|
37
|
-
header_str << @nl
|
37
|
+
)
|
38
38
|
|
39
|
-
|
39
|
+
@headers_string << @http2.header_str(headers)
|
40
|
+
@headers_string << @nl
|
41
|
+
@headers_string
|
40
42
|
end
|
41
43
|
|
42
44
|
def generate_raw(phash)
|
@@ -54,13 +56,11 @@ private
|
|
54
56
|
|
55
57
|
def read_file(path, praw)
|
56
58
|
File.open(path, "r") do |fp|
|
57
|
-
|
58
|
-
|
59
|
-
praw << data
|
60
|
-
end
|
61
|
-
rescue EOFError
|
62
|
-
# Happens when done.
|
59
|
+
while (data = fp.sysread(4096))
|
60
|
+
praw << data
|
63
61
|
end
|
62
|
+
rescue EOFError
|
63
|
+
# Happens when done.
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -1,13 +1,13 @@
|
|
1
|
-
class Http2::PostRequest
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
class Http2::PostRequest < Http2::BaseRequest
|
2
|
+
def headers_string
|
3
|
+
unless @headers_string
|
4
|
+
@headers_string = "#{method} /#{@args[:url]} HTTP/1.1#{@nl}"
|
5
|
+
@headers_string << @http2.header_str(headers)
|
6
|
+
@headers_string << @nl
|
7
|
+
@headers_string << @data
|
7
8
|
end
|
8
9
|
|
9
|
-
@
|
10
|
-
@conn = @http2.connection
|
10
|
+
@headers_string
|
11
11
|
end
|
12
12
|
|
13
13
|
def execute
|
@@ -15,10 +15,9 @@ class Http2::PostRequest
|
|
15
15
|
|
16
16
|
@http2.mutex.synchronize do
|
17
17
|
puts "Http2: Doing post." if @debug
|
18
|
-
puts "Http2: Header str: #{header_string}" if @debug
|
19
18
|
|
20
|
-
@conn.write(
|
21
|
-
return @http2.read_response(@args)
|
19
|
+
@conn.write(headers_string)
|
20
|
+
return @http2.read_response(self, @args)
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
@@ -36,7 +35,7 @@ private
|
|
36
35
|
if @args[:content_type]
|
37
36
|
@args[:content_type]
|
38
37
|
elsif @args[:json]
|
39
|
-
|
38
|
+
"application/json"
|
40
39
|
else
|
41
40
|
"application/x-www-form-urlencoded"
|
42
41
|
end
|
@@ -61,22 +60,7 @@ private
|
|
61
60
|
"Content-Type" => content_type
|
62
61
|
}
|
63
62
|
headers_hash.merge! @http2.default_headers(@args)
|
64
|
-
|
65
|
-
|
66
|
-
if @args[:json]
|
67
|
-
headers_hash["Accept"] = "application/json"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
return headers_hash
|
72
|
-
end
|
73
|
-
|
74
|
-
def header_string
|
75
|
-
header_str = "#{method} /#{@args[:url]} HTTP/1.1#{@nl}"
|
76
|
-
header_str << @http2.header_str(headers, @args)
|
77
|
-
header_str << @nl
|
78
|
-
header_str << @data
|
79
|
-
|
80
|
-
header_str
|
63
|
+
headers_hash["Accept"] = "application/json" if @args[:json] && !headers_hash["Accept"]
|
64
|
+
headers_hash
|
81
65
|
end
|
82
66
|
end
|
@@ -1,45 +1,42 @@
|
|
1
|
-
#This object will be returned as the response for each request.
|
1
|
+
# This object will be returned as the response for each request.
|
2
2
|
class Http2::Response
|
3
|
-
#All the data the response contains. Headers, body, cookies, requested URL and more.
|
4
|
-
attr_reader :
|
5
|
-
attr_accessor :body, :charset, :code, :
|
6
|
-
|
7
|
-
#This method should not be called manually.
|
8
|
-
def initialize(args = {})
|
9
|
-
@args = args
|
10
|
-
@args[:headers] = {} unless @args.key?(:headers)
|
11
|
-
@body = args[:body] || ""
|
12
|
-
@debug = @args[:debug]
|
13
|
-
end
|
3
|
+
# All the data the response contains. Headers, body, cookies, requested URL and more.
|
4
|
+
attr_reader :headers, :request, :request_args, :requested_url
|
5
|
+
attr_accessor :body, :charset, :code, :http_version
|
6
|
+
attr_writer :content_type
|
14
7
|
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
# This method should not be called manually.
|
9
|
+
def initialize(body: "", debug: false, headers: {}, request:)
|
10
|
+
@body = body
|
11
|
+
@debug = debug
|
12
|
+
@headers = headers
|
13
|
+
@request = request
|
14
|
+
@requested_url = request.path
|
20
15
|
end
|
21
16
|
|
22
|
-
#Returns a certain header by name or false if not found.
|
17
|
+
# Returns a certain header by name or false if not found.
|
23
18
|
#===Examples
|
24
19
|
# val = res.header("content-type")
|
25
20
|
def header(key)
|
26
|
-
return false
|
27
|
-
|
21
|
+
return false unless headers.key?(key)
|
22
|
+
|
23
|
+
headers.fetch(key).first.to_s
|
28
24
|
end
|
29
25
|
|
30
|
-
#Returns true if a header of the given string exists.
|
26
|
+
# Returns true if a header of the given string exists.
|
31
27
|
#===Examples
|
32
28
|
# print "No content-type was given." if !http.header?("content-type")
|
33
29
|
def header?(key)
|
34
|
-
return true if
|
35
|
-
|
30
|
+
return true if headers.key?(key) && !headers[key].first.to_s.empty?
|
31
|
+
|
32
|
+
false
|
36
33
|
end
|
37
34
|
|
38
35
|
def content_length
|
39
36
|
if header?("content-length")
|
40
37
|
header("content-length").to_i
|
41
38
|
elsif @body
|
42
|
-
|
39
|
+
@body.bytesize
|
43
40
|
else
|
44
41
|
raise "Couldn't calculate content-length."
|
45
42
|
end
|
@@ -47,20 +44,12 @@ class Http2::Response
|
|
47
44
|
|
48
45
|
def content_type
|
49
46
|
if header?("content-type")
|
50
|
-
|
47
|
+
header("content-type")
|
51
48
|
else
|
52
49
|
raise "No content-type was given."
|
53
50
|
end
|
54
51
|
end
|
55
52
|
|
56
|
-
#Returns the requested URL as a string.
|
57
|
-
#===Examples
|
58
|
-
# res.requested_url #=> "?show=status&action=getstatus"
|
59
|
-
def requested_url
|
60
|
-
raise "URL could not be detected." unless @args[:request_args][:url]
|
61
|
-
return @args[:request_args][:url]
|
62
|
-
end
|
63
|
-
|
64
53
|
# Checks the data that has been sat on the object and raises various exceptions, if it does not validate somehow.
|
65
54
|
def validate!
|
66
55
|
puts "Http2: Validating response length." if @debug
|
@@ -69,18 +58,42 @@ class Http2::Response
|
|
69
58
|
|
70
59
|
# Returns true if the result is JSON.
|
71
60
|
def json?
|
72
|
-
content_type
|
61
|
+
content_type&.start_with?("application/json")
|
73
62
|
end
|
74
63
|
|
75
64
|
def json
|
76
65
|
@json ||= JSON.parse(body)
|
77
66
|
end
|
78
67
|
|
68
|
+
def host
|
69
|
+
@request.http2.host
|
70
|
+
end
|
71
|
+
|
72
|
+
def port
|
73
|
+
@request.http2.port
|
74
|
+
end
|
75
|
+
|
76
|
+
def ssl?
|
77
|
+
@request.http2.ssl?
|
78
|
+
end
|
79
|
+
|
80
|
+
def path
|
81
|
+
@request.path
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_s
|
85
|
+
"#<Http::Response host=\"#{host}\" port=#{port} ssl=#{ssl?} path=\"#{path}\">"
|
86
|
+
end
|
87
|
+
|
88
|
+
def inspect
|
89
|
+
to_s
|
90
|
+
end
|
91
|
+
|
79
92
|
private
|
80
93
|
|
81
94
|
# Checks that the length of the body is the same as the given content-length if given.
|
82
95
|
def validate_body_versus_content_length!
|
83
|
-
unless
|
96
|
+
unless header?("content-length")
|
84
97
|
puts "Http2: No content length given - skipping length validation." if @debug
|
85
98
|
return nil
|
86
99
|
end
|