http2 0.0.31 → 0.0.35
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://api.shippable.com/projects/540e7b9b3479c5ea8f9ec21d/badge?branchName=master)](https://app.shippable.com/projects/540e7b9b3479c5ea8f9ec21d/builds/latest)
|
2
1
|
[![Code Climate](https://codeclimate.com/github/kaspernj/http2.png)](https://codeclimate.com/github/kaspernj/http2)
|
3
|
-
[![
|
2
|
+
[![Build Status](https://www.peakflow.io/en/projects/http2/branch-statuses/master.svg
|
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
|