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.
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