http2 0.0.28 → 0.0.33

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