http2 0.0.28 → 0.0.33

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 +150 -28
  3. data/Rakefile +20 -31
  4. data/lib/http2.rb +105 -70
  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 +75 -42
  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 +73 -0
  25. data/spec/http2/url_builder_spec.rb +1 -1
  26. data/spec/http2_spec.rb +107 -89
  27. data/spec/spec_helper.rb +8 -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 +118 -36
  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 -77
  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 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a28eaa08bb929414333c763236db9b220a499eb8
4
- data.tar.gz: 8cb38c1995fc84a1562b3c8a117ed702fff75db1
2
+ SHA256:
3
+ metadata.gz: 856e9e6edf6d355dc73912489a6263a6a213abbaa1ec87f6fa4b5547f727f336
4
+ data.tar.gz: f4062dda7f2970331ab68a9e38095fe7bc729f61a27305e7eaea4ddb9a2d28fe
5
5
  SHA512:
6
- metadata.gz: 63c24b5f90f05a1e8f67a59cbe7765475bd087ae384b873c47ee90794f52e1ea5c88386769e30bdc51234fde4f32ae2454d16e990acf13fc97ba5e7a81e4bcce
7
- data.tar.gz: 0f42d6609f0520b481723dd5c0d648371cd8b2b0f050c6608f45e81b9a511c87d4a651942d168c21f92d30fbb08f826c40450666ec8da657ba5f27ef5b493242
6
+ metadata.gz: 8ca5c943ae78a977a5253487670755830ea8225b417f79238cbaff5cf6d4f3adabe1e572b6480325c19e6cb317f35e10d2ef491de79df9d15cc7f6f8014f2b13
7
+ data.tar.gz: aead6eadd6b8569bab500e3ebf64bea0188ebf06739c83ba78d1f1fcd70b3b3ac0a6ad2516610bdefd2751bc63acb53c352fbbc1e3e310931d41ab0b6bf72f18
data/README.md CHANGED
@@ -1,41 +1,143 @@
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
- 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}"
15
+ Http2.new(host: "www.google.dk") do |http|
16
+ # Do requests here.
36
17
  end
37
18
  ```
38
19
 
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
+ ```
101
+
102
+ ## Building URL's
103
+ ```ruby
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"
117
+ ```
118
+
119
+ ## Inspecting responses
120
+
121
+ ```ruby
122
+ resp = http.get("path/to/something")
123
+ resp.content_type #=> "text/html"
124
+ resp.content_length #=> 136
125
+ resp.header("content-length") #=> "136"
126
+ resp.headers #=> {"content-type" => ["text/html"], "content-length" => ["136"]}
127
+ resp.code #=> "200"
128
+ resp.charset #=> "utf-8"
129
+ resp.http_version #=> "1.1"
130
+ resp.body #=> "<html><body>..."
131
+ resp.requested_url #=> "http://example.com/maybe/redirected/path/to/something"
132
+ ```
133
+
134
+ ## Get parameters later.
135
+
136
+ ```ruby
137
+ http.host #=> example.com
138
+ http.port #=> 80
139
+ ```
140
+
39
141
 
40
142
  ## Reconnect
41
143
 
@@ -45,6 +147,27 @@ Handy when doing retries.
45
147
  http.reconnect
46
148
  ```
47
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
+
48
171
  ## Contributing to http2
49
172
 
50
173
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
@@ -59,4 +182,3 @@ http.reconnect
59
182
 
60
183
  Copyright (c) 2012 Kasper Johansen. See LICENSE.txt for
61
184
  further details.
62
-
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,9 +3,10 @@ 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
- # Http2.new(:host => "www.somedomain.com", :port => 80, :ssl => false, :debug => false) do |http|
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")
10
11
  # html = res.body
11
12
  # print html
@@ -15,52 +16,64 @@ 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
 
54
+ def host
55
+ @args.fetch(:host)
56
+ end
57
+
58
+ def port
59
+ @args.fetch(:port)
60
+ end
61
+
62
+ def ssl?
63
+ @args[:ssl] ? true : false
64
+ end
65
+
53
66
  def reconnect
54
67
  @connection.reconnect
55
68
  end
56
69
 
57
70
  def new_url
58
71
  builder = Http2::UrlBuilder.new
59
- builder.host = @args[:host]
60
- builder.port = @args[:port]
72
+ builder.host = host
73
+ builder.port = port
61
74
  builder.protocol = @args[:protocol]
62
75
 
63
- return builder
76
+ builder
64
77
  end
65
78
 
66
79
  # Closes current connection if any, changes the arguments on the object and reconnects keeping all cookies and other stuff intact.
@@ -70,7 +83,7 @@ class Http2
70
83
  @connection = ::Http2::Connection.new(self)
71
84
  end
72
85
 
73
- #Destroys the object unsetting all variables and closing all sockets.
86
+ # Destroys the object unsetting all variables and closing all sockets.
74
87
  #===Examples
75
88
  # http.destroy
76
89
  def destroy
@@ -86,26 +99,22 @@ class Http2
86
99
  @connection = nil
87
100
  end
88
101
 
89
- #Forces various stuff into arguments-hash like URL from original arguments and enables single-string-shortcuts and more.
102
+ # Forces various stuff into arguments-hash like URL from original arguments and enables single-string-shortcuts and more.
90
103
  def parse_args(*args)
91
104
  if args.length == 1 && args.first.is_a?(String)
92
- args = {:url => args.first}
93
- elsif args.length >= 2
94
- raise "Couldnt parse arguments."
95
- elsif args.is_a?(Array) && args.length == 1
105
+ args = {url: args.first}
106
+ elsif args.length == 1
96
107
  args = args.first
97
108
  else
98
- raise "Invalid arguments: '#{args.class.name}'."
109
+ raise "Invalid arguments: '#{args.class.name}'"
99
110
  end
100
111
 
101
- if args[:url].to_s.split("\n").length != 1
102
- raise "Invalid URL: '#{args[:url]}'."
103
- end
112
+ raise "Invalid URL: '#{args[:url]}'" if args[:url] != "" && args[:url].to_s.split("\n").length != 1
104
113
 
105
- return args
114
+ args
106
115
  end
107
116
 
108
- #Returns a result-object based on the arguments.
117
+ # Returns a result-object based on the arguments.
109
118
  #===Examples
110
119
  # res = http.get("somepage.html")
111
120
  # print res.body #=> <String>-object containing the HTML gotten.
@@ -116,13 +125,13 @@ class Http2
116
125
  # Proxies the request to another method but forces the method to be "DELETE".
117
126
  def delete(args)
118
127
  if args[:json]
119
- return post(args.merge(:method => :delete))
128
+ post(args.merge(method: :delete))
120
129
  else
121
- return get(args.merge(:method => :delete))
130
+ get(args.merge(method: :delete))
122
131
  end
123
132
  end
124
133
 
125
- #Returns the default headers for a request.
134
+ # Returns the default headers for a request.
126
135
  #===Examples
127
136
  # headers_hash = http.default_headers
128
137
  # print "#{headers_hash}"
@@ -131,97 +140,120 @@ class Http2
131
140
 
132
141
  headers = {
133
142
  "Connection" => "Keep-Alive",
134
- "User-Agent" => @uagent
143
+ "User-Agent" => @uagent,
144
+ "Host" => host_header
135
145
  }
136
146
 
137
- #Possible to give custom host-argument.
138
- host = args[:host] || @args[:host]
139
- port = args[:port] || @args[:port]
140
-
141
- headers["Host"] = host
142
- headers["Host"] << ":#{port}" if port && ![80, 443].include?(port.to_i) && !@args[:skip_port_in_host_header]
143
147
  headers["Accept-Encoding"] = "gzip" if @args[:encoding_gzip]
144
148
 
145
149
  if @args[:basic_auth]
146
150
  require "base64" unless ::Kernel.const_defined?(:Base64)
147
- headers["Authorization"] = "Basic #{Base64.encode64("#{@args[:basic_auth][:user]}:#{@args[:basic_auth][:passwd]}").strip}"
151
+ headers["Authorization"] = "Basic #{Base64.strict_encode64("#{@args[:basic_auth][:user]}:#{@args[:basic_auth][:passwd]}").strip}"
152
+ end
153
+
154
+ if @args[:proxy] && @args[:proxy][:user] && @args[:proxy][:passwd] && !@connection.proxy_connect?
155
+ require "base64" unless ::Kernel.const_defined?(:Base64)
156
+ puts "Http2: Adding proxy auth header to request" if @debug
157
+ headers["Proxy-Authorization"] = "Basic #{Base64.strict_encode64("#{@args[:proxy][:user]}:#{@args[:proxy][:passwd]}").strip}"
148
158
  end
149
159
 
150
160
  headers.merge!(@args[:extra_headers]) if @args[:extra_headers]
151
161
  headers.merge!(args[:headers]) if args[:headers]
152
- return headers
162
+
163
+ headers
153
164
  end
154
165
 
155
- #Posts to a certain page.
166
+ # Posts to a certain page.
156
167
  #===Examples
157
168
  # res = http.post("login.php", {"username" => "John Doe", "password" => 123)
158
169
  def post(args)
159
170
  ::Http2::PostRequest.new(self, args).execute
160
171
  end
161
172
 
162
- #Posts to a certain page using the multipart-method.
173
+ # Posts to a certain page using the multipart-method.
163
174
  #===Examples
164
175
  # res = http.post_multipart("upload.php", {"normal_value" => 123, "file" => Tempfile.new(?)})
165
176
  def post_multipart(*args)
166
177
  ::Http2::PostMultipartRequest.new(self, *args).execute
167
178
  end
168
179
 
169
- #Returns a header-string which normally would be used for a request in the given state.
170
- def header_str(headers_hash, args = {})
171
- headers_hash["Cookie"] = cookie_header_string
180
+ # Returns a header-string which normally would be used for a request in the given state.
181
+ def header_str(headers_hash)
182
+ headers_hash["Cookie"] = cookie_header_string unless cookie_header_string.empty?
172
183
 
173
184
  headers_str = ""
174
185
  headers_hash.each do |key, val|
175
186
  headers_str << "#{key}: #{val}#{@nl}"
176
187
  end
177
188
 
178
- return headers_str
189
+ headers_str
179
190
  end
180
191
 
181
192
  def cookie_header_string
182
193
  cstr = ""
183
194
 
184
195
  first = true
185
- @cookies.each do |cookie_name, cookie_data|
196
+ @cookies.each do |_cookie_name, cookie|
186
197
  cstr << "; " unless first
187
198
  first = false if first
199
+ ensure_single_lines([cookie.name, cookie.value])
200
+ cstr << "#{Http2::Utils.urlenc(cookie.name)}=#{Http2::Utils.urlenc(cookie.value)}"
201
+ end
188
202
 
189
- if cookie_data.is_a?(Hash)
190
- name = cookie_data["name"]
191
- value = cookie_data["value"]
192
- else
193
- name = cookie_name
194
- value = cookie_data
195
- end
203
+ cstr
204
+ end
196
205
 
197
- raise "Unexpected lines: #{value.lines.to_a.length}." if value.lines.to_a.length != 1
198
- cstr << "#{Http2::Utils.urlenc(name)}=#{Http2::Utils.urlenc(value)}"
199
- end
206
+ def cookie(name)
207
+ name = name.to_s
208
+ return @cookies.fetch(name) if @cookies.key?(name)
200
209
 
201
- return cstr
210
+ raise "No cookie by that name: '#{name}' in '#{@cookies.keys.join(", ")}'"
211
+ end
212
+
213
+ def ensure_single_lines(*strings)
214
+ strings.each do |string|
215
+ raise "More than one line: #{string}." unless string.to_s.lines.to_a.length == 1
216
+ end
202
217
  end
203
218
 
204
219
  def on_content_call(args, str)
205
220
  args[:on_content].call(str) if args.key?(:on_content)
206
221
  end
207
222
 
208
- #Reads the response after posting headers and data.
223
+ # Reads the response after posting headers and data.
209
224
  #===Examples
210
225
  # res = http.read_response
211
- def read_response(args = {})
212
- ::Http2::ResponseReader.new(http2: self, sock: @sock, args: args).response
226
+ def read_response(request, args = {})
227
+ ::Http2::ResponseReader.new(http2: self, sock: @sock, args: args, request: request).response
228
+ end
229
+
230
+ def to_s
231
+ "<Http2 host: #{host}:#{port}>"
232
+ end
233
+
234
+ def inspect
235
+ to_s
213
236
  end
214
237
 
215
238
  private
216
239
 
217
- #Registers the states from a result.
240
+ def host_header
241
+ # Possible to give custom host-argument.
242
+ host = args[:host] || self.host
243
+ port = args[:port] || self.port
244
+
245
+ host_header_string = host.dup # Copy host string to avoid changing the original string if port has been given!
246
+ host_header_string << ":#{port}" if port && ![80, 443].include?(port.to_i) && !@args[:skip_port_in_host_header]
247
+ host_header_string
248
+ end
249
+
250
+ # Registers the states from a result.
218
251
  def autostate_register(res)
219
252
  puts "Http2: Running autostate-register on result." if @debug
220
253
  @autostate_values.clear
221
254
 
222
255
  res.body.to_s.scan(/<input type="hidden" name="__(EVENTTARGET|EVENTARGUMENT|VIEWSTATE|LASTFOCUS)" id="(.*?)" value="(.*?)" \/>/) do |match|
223
256
  name = "__#{match[0]}"
224
- id = match[1]
225
257
  value = match[2]
226
258
 
227
259
  puts "Http2: Registered autostate-value with name '#{name}' and value '#{value}'." if @debug
@@ -231,21 +263,24 @@ private
231
263
  raise "No states could be found." if @autostate_values.empty?
232
264
  end
233
265
 
234
- #Sets the states on the given post-hash.
266
+ # Sets the states on the given post-hash.
235
267
  def autostate_set_on_post_hash(phash)
236
268
  phash.merge!(@autostate_values)
237
269
  end
238
270
 
239
271
  def parse_init_args(args)
240
- args = {:host => args} if args.is_a?(String)
272
+ args = {host: args} if args.is_a?(String)
241
273
  raise "Arguments wasnt a hash." unless args.is_a?(Hash)
242
274
 
243
- args.each do |key, val|
275
+ args.each_key do |key|
244
276
  raise "Invalid key: '#{key}'." unless VALID_ARGUMENTS_INITIALIZE.include?(key)
245
277
  end
246
278
 
279
+ args[:proxy][:connect] = true if args[:proxy] && !args[:proxy].key?(:connect) && args[:ssl]
280
+
247
281
  raise "No host was given." unless args[:host]
248
- return args
282
+
283
+ args
249
284
  end
250
285
 
251
286
  def set_default_values
@@ -253,7 +288,7 @@ private
253
288
  @autostate_values = {} if autostate
254
289
  @nl = @args[:nl] || "\r\n"
255
290
 
256
- if !@args[:port]
291
+ unless @args[:port]
257
292
  if @args[:ssl]
258
293
  @args[:port] = 443
259
294
  else
@@ -273,4 +308,4 @@ private
273
308
  @raise_errors = false
274
309
  end
275
310
  end
276
- end
311
+ end