http2 0.0.29 → 0.0.34

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +131 -30
  3. data/Rakefile +20 -31
  4. data/lib/http2.rb +85 -67
  5. data/lib/http2/base_request.rb +22 -0
  6. data/{include → lib/http2}/connection.rb +56 -28
  7. data/lib/http2/cookie.rb +22 -0
  8. data/lib/http2/errors.rb +18 -0
  9. data/lib/http2/get_request.rb +33 -0
  10. data/{include → lib/http2}/post_data_generator.rb +7 -6
  11. data/{include → lib/http2}/post_multipart_request.rb +20 -20
  12. data/{include → lib/http2}/post_request.rb +17 -22
  13. data/lib/http2/response.rb +109 -0
  14. data/{include → lib/http2}/response_reader.rb +74 -41
  15. data/{include → lib/http2}/url_builder.rb +6 -6
  16. data/lib/http2/utils.rb +52 -0
  17. data/spec/helpers.rb +27 -0
  18. data/spec/http2/cookies_spec.rb +18 -0
  19. data/spec/http2/get_request_spec.rb +11 -0
  20. data/spec/http2/post_data_generator_spec.rb +2 -1
  21. data/spec/http2/post_multipart_request_spec.rb +11 -0
  22. data/spec/http2/post_request_spec.rb +11 -0
  23. data/spec/http2/response_reader_spec.rb +12 -0
  24. data/spec/http2/response_spec.rb +84 -8
  25. data/spec/http2/url_builder_spec.rb +1 -1
  26. data/spec/http2_spec.rb +104 -85
  27. data/spec/spec_helper.rb +9 -8
  28. data/spec/spec_root/content_type_test.rhtml +4 -0
  29. data/spec/spec_root/cookie_test.rhtml +8 -0
  30. data/spec/spec_root/json_test.rhtml +9 -0
  31. data/spec/spec_root/multipart_test.rhtml +28 -0
  32. data/spec/spec_root/redirect_test.rhtml +3 -0
  33. data/spec/spec_root/unauthorized.rhtml +3 -0
  34. data/spec/spec_root/unsupported_media_type.rhtml +3 -0
  35. metadata +131 -35
  36. data/.document +0 -5
  37. data/.rspec +0 -1
  38. data/Gemfile +0 -14
  39. data/Gemfile.lock +0 -77
  40. data/VERSION +0 -1
  41. data/http2.gemspec +0 -78
  42. data/include/errors.rb +0 -11
  43. data/include/get_request.rb +0 -34
  44. data/include/response.rb +0 -73
  45. data/include/utils.rb +0 -40
  46. data/shippable.yml +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 73d24887d39ea86831b94629d6dc98eed99333eb
4
- data.tar.gz: 364f8d08601a1279bfdf2a214d02d545473a806a
2
+ SHA256:
3
+ metadata.gz: 86c71528bc092c75bb6c6ec82ec5dc2dd8ca73bc7836ca235a8f66f7a8be26bd
4
+ data.tar.gz: 8eb7666d2020f5a38ae91c45d38f11cf772f136cb8a30c17c104d96743a6d967
5
5
  SHA512:
6
- metadata.gz: a856ec3dd70d2db8640a53b109592acfd17af7ff66a3130a2200f4cf5b38317dc9e51cf2996a871a5d959f957de78361f63b069d88dc84d69fb19e8deeba9771
7
- data.tar.gz: fd6d03348ab61b6b5b18cca4c0f27369d23bdf756d9f8fc9d5ee40a92e16fd90b054265f171b5ff8599f2141656873980011dfb0273096dc3cc0b690ed042d46
6
+ metadata.gz: 9411f817d1409689d895e01a6bb8cc22fe07f04c4e1b3ce03649ef23680da7dbc52fe3427c13171106453f3b08dc3e9f84cab938c1154bca0611e720d41e7c6e
7
+ data.tar.gz: b1214c3a8936c7fb605b731ed0b638a4aad0185890c3b58f4d083ac8ec950d3fe565e0bc863a29b3888d4e7762ed2b2e14237e5d2a51f2ba424fa50faa2cecdb
data/README.md CHANGED
@@ -1,49 +1,122 @@
1
+ [![Code Climate](https://codeclimate.com/github/kaspernj/http2.png)](https://codeclimate.com/github/kaspernj/http2)
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
+
1
5
  # http2
2
6
 
3
- [![Build Status](https://api.shippable.com/projects/53bd3eef2e23bdcb03c0df9e/badge/master)](https://www.shippable.com/projects/53bd3eef2e23bdcb03c0df9e)
4
- [![Code Climate](https://codeclimate.com/github/kaspernj/http2.png)](https://codeclimate.com/github/kaspernj/http2)
5
- [![Code Climate](https://codeclimate.com/github/kaspernj/http2/coverage.png)](https://codeclimate.com/github/kaspernj/http2)
7
+ A HTTP-framework for Ruby supporting keep-alive, compression, JSON-posting, detailed inspection of responses and much more.
6
8
 
7
- Example of usage:
9
+ # Usage
8
10
 
9
11
  ```ruby
10
12
  require "rubygems"
11
13
  require "http2"
12
14
 
13
15
  Http2.new(host: "www.google.dk") do |http|
14
- #Get-request.
15
- res = http.get("path/to/something")
16
- puts res.body
17
- puts "All response-headers: #{res.headers}"
18
- puts "Specific header: #{res.header("HeaderName")}"
19
-
20
- #Post-request.
21
- res = http.post(url: "path/to/something", post: {
22
- "some_post_val" => "some_value"
23
- })
24
-
25
- res.content_type #=> "text/html"
26
-
27
- #Post-multipart (upload).
28
- res = http.post_multipart(url: "path/to/something", post: {
29
- "test_file1" => {
30
- fpath: fpath,
31
- filename: "specfile"
32
- }
33
- })
34
-
35
- puts "Cookies until now: #{http.cookies}"
16
+ # Do requests here.
36
17
  end
37
18
  ```
38
19
 
39
- ## Get parameters.
20
+ Or without using a block for ensuring closing of connection:
21
+ ```ruby
22
+ http = Http2.new(...)
23
+
24
+ # Do requests here.
25
+
26
+ http.destroy # Closes the connection and frees up any variables used
27
+ ```
28
+
29
+ Or through a proxy:
30
+ ```ruby
31
+ Http2.new(host: "www.google.com", proxy: {host: "myproxy.com", port: 80, user: "myname", passwd: "mypassword"})
32
+ ```
33
+
34
+ You can also use SSL:
35
+ ```ruby
36
+ Http2.new(host: "myhost.com", ssl: true, ssl_skip_verify: true)
37
+ ```
38
+
39
+ You can make it follow redirects like this:
40
+ ```ruby
41
+ Http2.new(host: "myhost.com", follow_redirects: true)
42
+ ```
43
+
44
+ ## Get requests
45
+ ```ruby
46
+ res = http.get("path/to/something")
47
+ ```
48
+
49
+ Or as a hash:
50
+ ```ruby
51
+ res = http.get(url: "path/to/something")
52
+ ```
53
+
54
+ ## Post requests
55
+ ```ruby
56
+ res = http.post(url: "path/to/something", post: {
57
+ "some_post_val" => "some_value"
58
+ })
59
+ ```
60
+
61
+ ### Extra headers
62
+ ```ruby
63
+ res = http.post(
64
+ url: "path",
65
+ headers: {"Auth": "123"},
66
+ post: {data: "test"}
67
+ )
68
+ ```
69
+
70
+ ### Post JSON as content
71
+ ```ruby
72
+ res = http.post(url: "path/to/something", json: {some_argument: true})
73
+ ```
74
+
75
+ ### Reading JSON from request
76
+ ```ruby
77
+ res = http.post(url: "something", json: {some_argument: true})
78
+ res.json? #=> true (if content-type is application/json)
79
+ res.json #=> {"value" => "something"}
80
+ ```
81
+
82
+ ## Delete requests
83
+ ```ruby
84
+ res = http.delete(url: "path/to/something")
85
+ ```
86
+
87
+ ## File upload
88
+ ```ruby
89
+ res = http.post_multipart(url: "path/to/something", post: {
90
+ "test_file1" => {
91
+ fpath: fpath,
92
+ filename: "specfile"
93
+ }
94
+ })
95
+ ```
96
+
97
+ ## Reading cookies
98
+ ```ruby
99
+ puts "Cookies until now: #{http.cookies}"
100
+ ```
40
101
 
102
+ ## Building URL's
41
103
  ```ruby
42
- http.host => example.com
43
- http.port => 80
104
+ ub = ::Http2::UrlBuilder.new
105
+ ub.host = "www.google.com"
106
+ ub.port = 80
107
+ ub.path = "script.php"
108
+ ub.params["some_param"] = 2
109
+
110
+ ub.build #=> "http://www.google.com/..."
111
+ ub.build_params #=> "some_param=2&some_other_param=..."
112
+ ub.build_path_and_params #=> "script.php?some_param=2"
113
+ ub.params? #=> true
114
+ ub.host #=> "www.google.com"
115
+ ub.port #=> 80
116
+ ub.path #=> "script.php"
44
117
  ```
45
118
 
46
- ## Response details.
119
+ ## Inspecting responses
47
120
 
48
121
  ```ruby
49
122
  resp = http.get("path/to/something")
@@ -58,6 +131,13 @@ resp.body #=> "<html><body>..."
58
131
  resp.requested_url #=> "http://example.com/maybe/redirected/path/to/something"
59
132
  ```
60
133
 
134
+ ## Get parameters later.
135
+
136
+ ```ruby
137
+ http.host #=> example.com
138
+ http.port #=> 80
139
+ ```
140
+
61
141
 
62
142
  ## Reconnect
63
143
 
@@ -67,6 +147,27 @@ Handy when doing retries.
67
147
  http.reconnect
68
148
  ```
69
149
 
150
+
151
+ ## Basic HTTP authentication for all requests
152
+
153
+ ```ruby
154
+ http = Http2.new(
155
+ host: "www.somehost.com",
156
+ basic_auth: {
157
+ user: "username",
158
+ passwd: "password"
159
+ }
160
+ )
161
+ ```
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
+
70
171
  ## Contributing to http2
71
172
 
72
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,49 +1,38 @@
1
- # encoding: utf-8
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
- $stderr.puts e.message
9
- $stderr.puts "Run `bundle install` to install missing gems"
6
+ warn e.message
7
+ warn "Run `bundle install` to install missing gems"
10
8
  exit e.status_code
11
9
  end
12
- require 'rake'
13
-
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |gem|
16
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
- gem.name = "http2"
18
- gem.homepage = "http://github.com/kaspernj/http2"
19
- gem.license = "MIT"
20
- gem.summary = %Q{A lightweight framework for doing http-connections in Ruby. Supports cookies, keep-alive, compressing and much more.}
21
- gem.description = %Q{A lightweight framework for doing http-connections in Ruby. Supports cookies, keep-alive, compressing and much more.}
22
- gem.email = "k@spernj.org"
23
- gem.authors = ["Kasper Johansen"]
24
- # dependencies defined in Gemfile
25
- end
26
- Jeweler::RubygemsDotOrgTasks.new
10
+ require "rake"
27
11
 
28
- require 'rspec/core'
29
- require 'rspec/core/rake_task'
12
+ require "rspec/core"
13
+ require "rspec/core/rake_task"
30
14
  RSpec::Core::RakeTask.new(:spec) do |spec|
31
- spec.pattern = FileList['spec/**/*_spec.rb']
15
+ spec.pattern = FileList["spec/**/*_spec.rb"]
32
16
  end
33
17
 
34
18
  RSpec::Core::RakeTask.new(:rcov) do |spec|
35
- spec.pattern = 'spec/**/*_spec.rb'
19
+ spec.pattern = "spec/**/*_spec.rb"
36
20
  spec.rcov = true
37
21
  end
38
22
 
39
- task :default => :spec
23
+ task default: :spec
40
24
 
41
- require 'rdoc/task'
25
+ require "rdoc/task"
42
26
  Rake::RDocTask.new do |rdoc|
43
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
27
+ version = File.exist?("VERSION") ? File.read("VERSION") : ""
44
28
 
45
- rdoc.rdoc_dir = 'rdoc'
29
+ rdoc.rdoc_dir = "rdoc"
46
30
  rdoc.title = "http2 #{version}"
47
- rdoc.rdoc_files.include('README*')
48
- rdoc.rdoc_files.include('lib/**/*.rb')
31
+ rdoc.rdoc_files.include("README*")
32
+ rdoc.rdoc_files.include("lib/**/*.rb")
49
33
  end
34
+
35
+ Bundler::GemHelper.install_tasks
36
+
37
+ require "best_practice_project"
38
+ BestPracticeProject.load_tasks
@@ -3,7 +3,8 @@ require "uri"
3
3
  require "monitor" unless ::Kernel.const_defined?(:Monitor)
4
4
  require "string-cases"
5
5
 
6
- #This class tries to emulate a browser in Ruby without any visual stuff. Remember cookies, keep sessions alive, reset connections according to keep-alive rules and more.
6
+ # This class tries to emulate a browser in Ruby without any visual stuff.
7
+ # Remember cookies, keep sessions alive, reset connections according to keep-alive rules and more.
7
8
  #===Examples
8
9
  # Http2.new(host: "www.somedomain.com", port: 80, ssl: false, debug: false) do |http|
9
10
  # res = http.get("index.rhtml?show=some_page")
@@ -15,47 +16,51 @@ require "string-cases"
15
16
  # print "#{res.headers}"
16
17
  # end
17
18
  class Http2
18
- #Autoloader for subclasses.
19
+ # Autoloader for subclasses.
19
20
  def self.const_missing(name)
20
- require "#{File.dirname(__FILE__)}/../include/#{::StringCases.camel_to_snake(name)}.rb"
21
- return Http2.const_get(name)
22
- end
21
+ file_path = "#{File.dirname(__FILE__)}/http2/#{::StringCases.camel_to_snake(name)}.rb"
23
22
 
24
- #Converts a URL to "is.gd"-short-URL.
25
- def self.isgdlink(url)
26
- Http2.new(host: "is.gd") do |http|
27
- resp = http.get("/api.php?longurl=#{url}")
28
- return resp.body
23
+ if File.exist?(file_path)
24
+ require file_path
25
+ return Http2.const_get(name) if Http2.const_defined?(name)
29
26
  end
27
+
28
+ super
30
29
  end
31
30
 
32
31
  attr_reader :autostate, :connection, :cookies, :args, :debug, :mutex, :resp, :raise_errors, :nl
33
32
  attr_accessor :keepalive_max, :keepalive_timeout
34
33
 
35
- VALID_ARGUMENTS_INITIALIZE = [:host, :port, :skip_port_in_host_header, :ssl, :nl, :user_agent, :raise_errors, :follow_redirects, :debug, :encoding_gzip, :autostate, :basic_auth, :extra_headers, :proxy]
34
+ VALID_ARGUMENTS_INITIALIZE = [
35
+ :host, :port, :skip_port_in_host_header, :ssl, :ssl_skip_verify, :nl, :user_agent, :raise_errors,
36
+ :follow_redirects, :debug, :encoding_gzip, :autostate, :basic_auth, :extra_headers, :proxy
37
+ ].freeze
36
38
  def initialize(args = {})
37
39
  @args = parse_init_args(args)
38
40
  set_default_values
39
41
  @cookies = {}
40
42
  @mutex = Monitor.new
41
-
42
43
  @connection = ::Http2::Connection.new(self)
43
44
 
44
45
  if block_given?
45
46
  begin
46
47
  yield(self)
47
48
  ensure
48
- self.destroy
49
+ destroy
49
50
  end
50
51
  end
51
52
  end
52
53
 
53
54
  def host
54
- @args[:host]
55
+ @args.fetch(:host)
55
56
  end
56
57
 
57
58
  def port
58
- @args[:port]
59
+ @args.fetch(:port)
60
+ end
61
+
62
+ def ssl?
63
+ @args[:ssl] ? true : false
59
64
  end
60
65
 
61
66
  def reconnect
@@ -68,7 +73,7 @@ class Http2
68
73
  builder.port = port
69
74
  builder.protocol = @args[:protocol]
70
75
 
71
- return builder
76
+ builder
72
77
  end
73
78
 
74
79
  # Closes current connection if any, changes the arguments on the object and reconnects keeping all cookies and other stuff intact.
@@ -78,11 +83,10 @@ class Http2
78
83
  @connection = ::Http2::Connection.new(self)
79
84
  end
80
85
 
81
- #Destroys the object unsetting all variables and closing all sockets.
86
+ # Destroys the object unsetting all variables and closing all sockets.
82
87
  #===Examples
83
88
  # http.destroy
84
89
  def destroy
85
- @args = nil
86
90
  @cookies = nil
87
91
  @debug = nil
88
92
  @mutex = nil
@@ -94,26 +98,22 @@ class Http2
94
98
  @connection = nil
95
99
  end
96
100
 
97
- #Forces various stuff into arguments-hash like URL from original arguments and enables single-string-shortcuts and more.
101
+ # Forces various stuff into arguments-hash like URL from original arguments and enables single-string-shortcuts and more.
98
102
  def parse_args(*args)
99
103
  if args.length == 1 && args.first.is_a?(String)
100
104
  args = {url: args.first}
101
- elsif args.length >= 2
102
- raise "Couldnt parse arguments."
103
- elsif args.is_a?(Array) && args.length == 1
105
+ elsif args.length == 1
104
106
  args = args.first
105
107
  else
106
- raise "Invalid arguments: '#{args.class.name}'."
108
+ raise "Invalid arguments: '#{args.class.name}'"
107
109
  end
108
110
 
109
- if args[:url].to_s.split("\n").length != 1
110
- raise "Invalid URL: '#{args[:url]}'."
111
- end
111
+ raise "Invalid URL: '#{args[:url]}'" if args[:url] != "" && args[:url].to_s.split("\n").length != 1
112
112
 
113
- return args
113
+ args
114
114
  end
115
115
 
116
- #Returns a result-object based on the arguments.
116
+ # Returns a result-object based on the arguments.
117
117
  #===Examples
118
118
  # res = http.get("somepage.html")
119
119
  # print res.body #=> <String>-object containing the HTML gotten.
@@ -124,13 +124,13 @@ class Http2
124
124
  # Proxies the request to another method but forces the method to be "DELETE".
125
125
  def delete(args)
126
126
  if args[:json]
127
- return post(args.merge(method: :delete))
127
+ post(args.merge(method: :delete))
128
128
  else
129
- return get(args.merge(method: :delete))
129
+ get(args.merge(method: :delete))
130
130
  end
131
131
  end
132
132
 
133
- #Returns the default headers for a request.
133
+ # Returns the default headers for a request.
134
134
  #===Examples
135
135
  # headers_hash = http.default_headers
136
136
  # print "#{headers_hash}"
@@ -139,85 +139,91 @@ class Http2
139
139
 
140
140
  headers = {
141
141
  "Connection" => "Keep-Alive",
142
- "User-Agent" => @uagent
142
+ "User-Agent" => @uagent,
143
+ "Host" => host_header
143
144
  }
144
145
 
145
- #Possible to give custom host-argument.
146
- host = args[:host] || self.host
147
- port = args[:port] || self.port
148
-
149
- headers["Host"] = host
150
- headers["Host"] << ":#{port}" if port && ![80, 443].include?(port.to_i) && !@args[:skip_port_in_host_header]
151
146
  headers["Accept-Encoding"] = "gzip" if @args[:encoding_gzip]
152
147
 
153
148
  if @args[:basic_auth]
154
149
  require "base64" unless ::Kernel.const_defined?(:Base64)
155
- headers["Authorization"] = "Basic #{Base64.encode64("#{@args[:basic_auth][:user]}:#{@args[:basic_auth][:passwd]}").strip}"
150
+ headers["Authorization"] = "Basic #{Base64.strict_encode64("#{@args[:basic_auth][:user]}:#{@args[:basic_auth][:passwd]}").strip}"
151
+ end
152
+
153
+ if @args[:proxy] && @args[:proxy][:user] && @args[:proxy][:passwd] && !@connection.proxy_connect?
154
+ require "base64" unless ::Kernel.const_defined?(:Base64)
155
+ puts "Http2: Adding proxy auth header to request" if @debug
156
+ headers["Proxy-Authorization"] = "Basic #{Base64.strict_encode64("#{@args[:proxy][:user]}:#{@args[:proxy][:passwd]}").strip}"
156
157
  end
157
158
 
158
159
  headers.merge!(@args[:extra_headers]) if @args[:extra_headers]
159
160
  headers.merge!(args[:headers]) if args[:headers]
160
- return headers
161
+
162
+ headers
161
163
  end
162
164
 
163
- #Posts to a certain page.
165
+ # Posts to a certain page.
164
166
  #===Examples
165
167
  # res = http.post("login.php", {"username" => "John Doe", "password" => 123)
166
168
  def post(args)
167
169
  ::Http2::PostRequest.new(self, args).execute
168
170
  end
169
171
 
170
- #Posts to a certain page using the multipart-method.
172
+ # Posts to a certain page using the multipart-method.
171
173
  #===Examples
172
174
  # res = http.post_multipart("upload.php", {"normal_value" => 123, "file" => Tempfile.new(?)})
173
175
  def post_multipart(*args)
174
176
  ::Http2::PostMultipartRequest.new(self, *args).execute
175
177
  end
176
178
 
177
- #Returns a header-string which normally would be used for a request in the given state.
178
- def header_str(headers_hash, args = {})
179
- headers_hash["Cookie"] = cookie_header_string
179
+ # Returns a header-string which normally would be used for a request in the given state.
180
+ def header_str(headers_hash)
181
+ headers_hash["Cookie"] = cookie_header_string unless cookie_header_string.empty?
180
182
 
181
183
  headers_str = ""
182
184
  headers_hash.each do |key, val|
183
185
  headers_str << "#{key}: #{val}#{@nl}"
184
186
  end
185
187
 
186
- return headers_str
188
+ headers_str
187
189
  end
188
190
 
189
191
  def cookie_header_string
190
192
  cstr = ""
191
193
 
192
194
  first = true
193
- @cookies.each do |cookie_name, cookie_data|
195
+ @cookies.each do |_cookie_name, cookie|
194
196
  cstr << "; " unless first
195
197
  first = false if first
198
+ ensure_single_lines([cookie.name, cookie.value])
199
+ cstr << "#{Http2::Utils.urlenc(cookie.name)}=#{Http2::Utils.urlenc(cookie.value)}"
200
+ end
196
201
 
197
- if cookie_data.is_a?(Hash)
198
- name = cookie_data["name"]
199
- value = cookie_data["value"]
200
- else
201
- name = cookie_name
202
- value = cookie_data
203
- end
202
+ cstr
203
+ end
204
204
 
205
- raise "Unexpected lines: #{value.lines.to_a.length}." if value.lines.to_a.length != 1
206
- cstr << "#{Http2::Utils.urlenc(name)}=#{Http2::Utils.urlenc(value)}"
207
- end
205
+ def cookie(name)
206
+ name = name.to_s
207
+ return @cookies.fetch(name) if @cookies.key?(name)
208
208
 
209
- return cstr
209
+ raise "No cookie by that name: '#{name}' in '#{@cookies.keys.join(", ")}'"
210
+ end
211
+
212
+ def ensure_single_lines(*strings)
213
+ strings.each do |string|
214
+ raise "More than one line: #{string}." unless string.to_s.lines.to_a.length == 1
215
+ end
210
216
  end
211
217
 
212
218
  def on_content_call(args, str)
213
219
  args[:on_content].call(str) if args.key?(:on_content)
214
220
  end
215
221
 
216
- #Reads the response after posting headers and data.
222
+ # Reads the response after posting headers and data.
217
223
  #===Examples
218
224
  # res = http.read_response
219
- def read_response(args = {})
220
- ::Http2::ResponseReader.new(http2: self, sock: @sock, args: args).response
225
+ def read_response(request, args = {})
226
+ ::Http2::ResponseReader.new(http2: self, sock: @sock, args: args, request: request).response
221
227
  end
222
228
 
223
229
  def to_s
@@ -230,14 +236,23 @@ class Http2
230
236
 
231
237
  private
232
238
 
233
- #Registers the states from a result.
239
+ def host_header
240
+ # Possible to give custom host-argument.
241
+ host = args[:host] || self.host
242
+ port = args[:port] || self.port
243
+
244
+ host_header_string = host.dup # Copy host string to avoid changing the original string if port has been given!
245
+ host_header_string << ":#{port}" if port && ![80, 443].include?(port.to_i) && !@args[:skip_port_in_host_header]
246
+ host_header_string
247
+ end
248
+
249
+ # Registers the states from a result.
234
250
  def autostate_register(res)
235
251
  puts "Http2: Running autostate-register on result." if @debug
236
252
  @autostate_values.clear
237
253
 
238
254
  res.body.to_s.scan(/<input type="hidden" name="__(EVENTTARGET|EVENTARGUMENT|VIEWSTATE|LASTFOCUS)" id="(.*?)" value="(.*?)" \/>/) do |match|
239
255
  name = "__#{match[0]}"
240
- id = match[1]
241
256
  value = match[2]
242
257
 
243
258
  puts "Http2: Registered autostate-value with name '#{name}' and value '#{value}'." if @debug
@@ -247,7 +262,7 @@ private
247
262
  raise "No states could be found." if @autostate_values.empty?
248
263
  end
249
264
 
250
- #Sets the states on the given post-hash.
265
+ # Sets the states on the given post-hash.
251
266
  def autostate_set_on_post_hash(phash)
252
267
  phash.merge!(@autostate_values)
253
268
  end
@@ -256,12 +271,15 @@ private
256
271
  args = {host: args} if args.is_a?(String)
257
272
  raise "Arguments wasnt a hash." unless args.is_a?(Hash)
258
273
 
259
- args.each do |key, val|
274
+ args.each_key do |key|
260
275
  raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_INITIALIZE.include?(key)
261
276
  end
262
277
 
278
+ args[:proxy][:connect] = true if args[:proxy] && !args[:proxy].key?(:connect) && args[:ssl]
279
+
263
280
  raise "No host was given." unless args[:host]
264
- return args
281
+
282
+ args
265
283
  end
266
284
 
267
285
  def set_default_values
@@ -269,7 +287,7 @@ private
269
287
  @autostate_values = {} if autostate
270
288
  @nl = @args[:nl] || "\r\n"
271
289
 
272
- if !@args[:port]
290
+ unless @args[:port]
273
291
  if @args[:ssl]
274
292
  @args[:port] = 443
275
293
  else