http2 0.0.31 → 0.0.32

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.
@@ -1,13 +1,13 @@
1
- class Http2::PostRequest
2
- VALID_ARGUMENTS_POST = [:post, :url, :default_headers, :headers, :json, :method, :cookies, :on_content, :content_type]
3
-
4
- def initialize(http2, args)
5
- args.each do |key, val|
6
- raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_POST.include?(key)
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
- @http2, @args, @debug, @nl = http2, http2.parse_args(args), http2.debug, http2.nl
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(header_string)
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
- content_type = "application/json"
38
+ "application/json"
40
39
  else
41
40
  "application/x-www-form-urlencoded"
42
41
  end
@@ -63,20 +62,9 @@ private
63
62
  headers_hash.merge! @http2.default_headers(@args)
64
63
 
65
64
  unless headers_hash["Accept"]
66
- if @args[:json]
67
- headers_hash["Accept"] = "application/json"
68
- end
65
+ headers_hash["Accept"] = "application/json" if @args[:json]
69
66
  end
70
67
 
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
68
+ headers_hash
81
69
  end
82
70
  end
@@ -1,38 +1,39 @@
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 :args
3
+ # All the data the response contains. Headers, body, cookies, requested URL and more.
4
+ attr_reader :args, :request
5
5
  attr_accessor :body, :charset, :code, :content_type, :http_version
6
6
 
7
- #This method should not be called manually.
7
+ # This method should not be called manually.
8
8
  def initialize(args = {})
9
9
  @args = args
10
- @args[:headers] = {} unless @args.key?(:headers)
10
+ @args[:headers] ||= {}
11
11
  @body = args[:body] || ""
12
- @debug = @args[:debug]
12
+ @debug = args[:debug]
13
+ @request = args.fetch(:request)
13
14
  end
14
15
 
15
- #Returns headers given from the host for the result.
16
+ # Returns headers given from the host for the result.
16
17
  #===Examples
17
18
  # headers_hash = res.headers
18
19
  def headers
19
- return @args[:headers]
20
+ @args.fetch(:headers)
20
21
  end
21
22
 
22
- #Returns a certain header by name or false if not found.
23
+ # Returns a certain header by name or false if not found.
23
24
  #===Examples
24
25
  # val = res.header("content-type")
25
26
  def header(key)
26
- return false if !@args[:headers].key?(key)
27
- return @args[:headers][key].first.to_s
27
+ return false unless @args.fetch(:headers).key?(key)
28
+ @args.fetch(:headers).fetch(key).first.to_s
28
29
  end
29
30
 
30
- #Returns true if a header of the given string exists.
31
+ # Returns true if a header of the given string exists.
31
32
  #===Examples
32
33
  # print "No content-type was given." if !http.header?("content-type")
33
34
  def header?(key)
34
35
  return true if @args[:headers].key?(key) && @args[:headers][key].first.to_s.length > 0
35
- return false
36
+ false
36
37
  end
37
38
 
38
39
  def content_length
@@ -53,12 +54,12 @@ class Http2::Response
53
54
  end
54
55
  end
55
56
 
56
- #Returns the requested URL as a string.
57
+ # Returns the requested URL as a string.
57
58
  #===Examples
58
59
  # res.requested_url #=> "?show=status&action=getstatus"
59
60
  def requested_url
60
61
  raise "URL could not be detected." unless @args[:request_args][:url]
61
- return @args[:request_args][:url]
62
+ @args[:request_args][:url]
62
63
  end
63
64
 
64
65
  # Checks the data that has been sat on the object and raises various exceptions, if it does not validate somehow.
@@ -76,6 +77,30 @@ class Http2::Response
76
77
  @json ||= JSON.parse(body)
77
78
  end
78
79
 
80
+ def host
81
+ @request.http2.host
82
+ end
83
+
84
+ def port
85
+ @request.http2.port
86
+ end
87
+
88
+ def ssl?
89
+ @request.http2.ssl?
90
+ end
91
+
92
+ def path
93
+ @request.path
94
+ end
95
+
96
+ def to_s
97
+ "#<Http::Response host=\"#{host}\" port=#{port} ssl=#{ssl?} path=\"#{path}\">"
98
+ end
99
+
100
+ def inspect
101
+ to_s
102
+ end
103
+
79
104
  private
80
105
 
81
106
  # Checks that the length of the body is the same as the given content-length if given.
@@ -4,9 +4,12 @@ class Http2::ResponseReader
4
4
  def initialize(args)
5
5
  @mode = "headers"
6
6
  @transfer_encoding = nil
7
- @response = Http2::Response.new(request_args: args, debug: @debug)
7
+ @response = Http2::Response.new(request: args.fetch(:request), request_args: args, debug: @debug)
8
8
  @rec_count = 0
9
- @args, @debug, @http2, @sock = args[:args], args[:http2].debug, args[:http2], args[:sock]
9
+ @args = args[:args]
10
+ @debug = args[:http2].debug
11
+ @http2 = args[:http2]
12
+ @sock = args[:sock]
10
13
  @nl = @http2.nl
11
14
  @conn = @http2.connection
12
15
 
@@ -49,7 +52,7 @@ class Http2::ResponseReader
49
52
  end
50
53
 
51
54
  def finish
52
- #Check if we should reconnect based on keep-alive-max.
55
+ # Check if we should reconnect based on keep-alive-max.
53
56
  if @keepalive_max == 1 || @connection == "close"
54
57
  @conn.close unless @conn.closed?
55
58
  end
@@ -66,7 +69,7 @@ class Http2::ResponseReader
66
69
  @http2.autostate_register(@response) if @http2.args[:autostate]
67
70
  handle_errors
68
71
 
69
- if response = check_and_follow_redirect
72
+ if (response = check_and_follow_redirect)
70
73
  @response = response
71
74
  end
72
75
  end
@@ -100,14 +103,19 @@ private
100
103
 
101
104
  def url_and_args_from_location
102
105
  uri = URI.parse(@response.header("location"))
106
+
103
107
  url = uri.path
104
108
  url << "?#{uri.query}" if uri.query.to_s.length > 0
109
+ url = url.gsub(/\A\//, "")
110
+
111
+ args = @http2.args
112
+ .reject { |k, _v| [:ssl, :port].include? k }
113
+ .merge(host: uri.host)
105
114
 
106
- args = {host: uri.host}
107
115
  args[:ssl] = true if uri.scheme == "https"
108
116
  args[:port] = uri.port if uri.port
109
117
 
110
- return [url, args]
118
+ [url, args]
111
119
  end
112
120
 
113
121
  def check_and_decode
@@ -123,7 +131,7 @@ private
123
131
  begin
124
132
  valid_string = ic.encode("UTF-8")
125
133
  rescue
126
- valid_string = untrusted_str.force_encoding("UTF-8").encode("UTF-8", :invalid => :replace, :replace => "").encode("UTF-8")
134
+ valid_string = untrusted_str.force_encoding("UTF-8").encode("UTF-8", invalid: :replace, replace: "").encode("UTF-8")
127
135
  end
128
136
 
129
137
  @response.body = valid_string
@@ -131,7 +139,7 @@ private
131
139
  end
132
140
 
133
141
  def handle_errors
134
- return unless @http2.raise_errors
142
+ return unless @http2.raise_errors
135
143
 
136
144
  if @response.code == "500"
137
145
  err = Http2::Errors::Internalserver.new("A internal server error occurred")
@@ -176,7 +184,7 @@ private
176
184
  end
177
185
 
178
186
  def parse_content_type(content_type_line)
179
- if match_charset = content_type_line.match(/\s*;\s*charset=(.+)/i)
187
+ if (match_charset = content_type_line.match(/\s*;\s*charset=(.+)/i))
180
188
  @charset = match_charset[1].downcase
181
189
  @response.charset = @charset
182
190
  content_type_line.gsub!(match_charset[0], "")
@@ -185,15 +193,15 @@ private
185
193
  @response.content_type = content_type_line
186
194
  end
187
195
 
188
- #Parse a header-line and saves it on the object.
196
+ # Parse a header-line and saves it on the object.
189
197
  #===Examples
190
198
  # http.parse_header("Content-Type: text/html\r\n")
191
199
  def parse_header(line)
192
- if match = line.match(/^(.+?):\s*(.+)#{@nl}$/)
200
+ if (match = line.match(/^(.+?):\s*(.+)#{@nl}$/))
193
201
  key = match[1].downcase
194
202
  set_header_special_values(key, match[2])
195
203
  parse_normal_header(line, key, match[1], match[2])
196
- elsif match = line.match(/^HTTP\/([\d\.]+)\s+(\d+)\s+(.+)$/)
204
+ elsif (match = line.match(/^HTTP\/([\d\.]+)\s+(\d+)\s+(.+)$/))
197
205
  @response.code = match[2]
198
206
  @response.http_version = match[1]
199
207
  @http2.on_content_call(@args, line)
@@ -229,7 +237,7 @@ private
229
237
  end
230
238
  end
231
239
 
232
- #Parses the body based on given headers and saves it to the result-object.
240
+ # Parses the body based on given headers and saves it to the result-object.
233
241
  # http.parse_body(str)
234
242
  def parse_body(line)
235
243
  return :break if @length == 0
@@ -1,7 +1,7 @@
1
1
  class Http2::UrlBuilder
2
2
  attr_accessor :host, :port, :protocol, :path, :params
3
3
 
4
- def initialize args = {}
4
+ def initialize
5
5
  @params = {}
6
6
  end
7
7
 
@@ -24,7 +24,7 @@ class Http2::UrlBuilder
24
24
  end
25
25
  end
26
26
 
27
- return url_params
27
+ url_params
28
28
  end
29
29
 
30
30
  def build_path_and_params
@@ -35,7 +35,7 @@ class Http2::UrlBuilder
35
35
  url << build_params
36
36
  end
37
37
 
38
- return url
38
+ url
39
39
  end
40
40
 
41
41
  def build
@@ -49,7 +49,7 @@ class Http2::UrlBuilder
49
49
 
50
50
  url << build_path_and_params
51
51
 
52
- return url
52
+ url
53
53
  end
54
54
 
55
55
  def params?
@@ -2,17 +2,17 @@
2
2
  class Http2::Utils
3
3
  # URL-encodes a string.
4
4
  def self.urlenc(string)
5
- #Thanks to CGI framework
5
+ # Thanks to CGI framework
6
6
  string.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/) do
7
- '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
8
- end.tr(' ', '+')
7
+ "%" + $1.unpack("H2" * $1.bytesize).join("%").upcase
8
+ end.tr(" ", "+")
9
9
  end
10
10
 
11
11
  # URL-decodes a string.
12
12
  def self.urldec(string)
13
- #Thanks to CGI framework
14
- str = string.to_s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
15
- [$1.delete('%')].pack('H*')
13
+ # Thanks to CGI framework
14
+ string.to_s.tr("+", " ").gsub(/((?:%[0-9a-fA-F]{2})+)/) do
15
+ [$1.delete("%")].pack("H*")
16
16
  end
17
17
  end
18
18
 
@@ -28,10 +28,10 @@ class Http2::Utils
28
28
 
29
29
  cookie_data = {
30
30
  name: urldec(match[1].to_s),
31
- value: self.urldec(match[2].to_s)
31
+ value: urldec(match[2].to_s)
32
32
  }
33
33
 
34
- while match = str.match(/(.+?)=(.*?)(;\s*|$)/)
34
+ while (match = str.match(/(.+?)=(.*?)(;\s*|$)/))
35
35
  str = str.gsub(match[0], "")
36
36
  key = match[1].to_s.downcase
37
37
  value = match[2].to_s
@@ -45,6 +45,6 @@ class Http2::Utils
45
45
 
46
46
  cookie = Http2::Cookie.new(cookie_data)
47
47
 
48
- return [cookie]
48
+ [cookie]
49
49
  end
50
50
  end
@@ -5,14 +5,14 @@ describe Http2 do
5
5
 
6
6
  it "should parse cookies and let them be read" do
7
7
  with_http do |http|
8
- res = http.get("cookie_test.rhtml")
9
- http.cookies.length.should eq 2
8
+ http.get("cookie_test.rhtml")
9
+ expect(http.cookies.length).to eq 2
10
10
 
11
11
  cookie = http.cookie("TestCookie")
12
- cookie.name.should eq "TestCookie"
13
- cookie.value.should eq "TestValue"
14
- cookie.path.should eq "/"
15
- cookie.expires.should > Time.now
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
16
  end
17
17
  end
18
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
@@ -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
@@ -1,17 +1,73 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Http2::Response do
4
- it "should register content type" do
4
+ it "#content_type" do
5
5
  with_http do |http|
6
6
  res = http.get("content_type_test.rhtml")
7
- res.content_type.should eq "text/html"
7
+ expect(res.content_type).to eq "text/html"
8
8
  end
9
9
  end
10
10
 
11
- it "should register content length" do
11
+ it "#content_length" do
12
12
  with_http do |http|
13
13
  res = http.get("content_type_test.rhtml")
14
- res.content_length.should > 50
14
+ expect(res.content_length).to be > 50
15
+ end
16
+ end
17
+
18
+ it "#json?" do
19
+ with_http do |http|
20
+ res = http.get("json_test.rhtml")
21
+ expect(res.json?).to eq true
22
+ end
23
+ end
24
+
25
+ it "#host" do
26
+ with_http do |http|
27
+ res = http.get("json_test.rhtml")
28
+ expect(res.host).to eq "localhost"
29
+ end
30
+ end
31
+
32
+ it "#port" do
33
+ with_http do |http|
34
+ res = http.get("json_test.rhtml")
35
+ expect(res.port).to eq http.port
36
+ end
37
+ end
38
+
39
+ it "#ssl?" do
40
+ with_http do |http|
41
+ res = http.get("json_test.rhtml")
42
+ expect(res.ssl?).to eq false
43
+ end
44
+ end
45
+
46
+ it "#path" do
47
+ with_http do |http|
48
+ res = http.get("json_test.rhtml")
49
+ expect(res.path).to eq "json_test.rhtml"
50
+ end
51
+ end
52
+
53
+ it "#header" do
54
+ with_http do |http|
55
+ res = http.get("json_test.rhtml")
56
+ expect(res.header("connection")).to eq "Keep-Alive"
57
+ end
58
+ end
59
+
60
+ it "#header?" do
61
+ with_http do |http|
62
+ res = http.get("json_test.rhtml")
63
+ expect(res.header?("connection")).to eq true
64
+ end
65
+ end
66
+
67
+ it "#json" do
68
+ with_http do |http|
69
+ res = http.post(url: "json_test.rhtml", post: {test: "test2"})
70
+ expect(res.json["_POST"]).to eq("test" => "test2")
15
71
  end
16
72
  end
17
73
  end