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.
- checksums.yaml +5 -5
- data/README.md +131 -30
- data/Rakefile +20 -31
- data/lib/http2.rb +85 -67
- data/lib/http2/base_request.rb +22 -0
- data/{include → lib/http2}/connection.rb +56 -28
- data/lib/http2/cookie.rb +22 -0
- data/lib/http2/errors.rb +18 -0
- data/lib/http2/get_request.rb +33 -0
- data/{include → lib/http2}/post_data_generator.rb +7 -6
- data/{include → lib/http2}/post_multipart_request.rb +20 -20
- data/{include → lib/http2}/post_request.rb +17 -22
- data/lib/http2/response.rb +109 -0
- data/{include → lib/http2}/response_reader.rb +74 -41
- data/{include → lib/http2}/url_builder.rb +6 -6
- data/lib/http2/utils.rb +52 -0
- data/spec/helpers.rb +27 -0
- data/spec/http2/cookies_spec.rb +18 -0
- data/spec/http2/get_request_spec.rb +11 -0
- data/spec/http2/post_data_generator_spec.rb +2 -1
- data/spec/http2/post_multipart_request_spec.rb +11 -0
- data/spec/http2/post_request_spec.rb +11 -0
- data/spec/http2/response_reader_spec.rb +12 -0
- data/spec/http2/response_spec.rb +84 -8
- data/spec/http2/url_builder_spec.rb +1 -1
- data/spec/http2_spec.rb +104 -85
- data/spec/spec_helper.rb +9 -8
- data/spec/spec_root/content_type_test.rhtml +4 -0
- data/spec/spec_root/cookie_test.rhtml +8 -0
- data/spec/spec_root/json_test.rhtml +9 -0
- data/spec/spec_root/multipart_test.rhtml +28 -0
- data/spec/spec_root/redirect_test.rhtml +3 -0
- data/spec/spec_root/unauthorized.rhtml +3 -0
- data/spec/spec_root/unsupported_media_type.rhtml +3 -0
- metadata +131 -35
- data/.document +0 -5
- data/.rspec +0 -1
- data/Gemfile +0 -14
- data/Gemfile.lock +0 -77
- data/VERSION +0 -1
- data/http2.gemspec +0 -78
- data/include/errors.rb +0 -11
- data/include/get_request.rb +0 -34
- data/include/response.rb +0 -73
- data/include/utils.rb +0 -40
- data/shippable.yml +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 86c71528bc092c75bb6c6ec82ec5dc2dd8ca73bc7836ca235a8f66f7a8be26bd
|
4
|
+
data.tar.gz: 8eb7666d2020f5a38ae91c45d38f11cf772f136cb8a30c17c104d96743a6d967
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9411f817d1409689d895e01a6bb8cc22fe07f04c4e1b3ce03649ef23680da7dbc52fe3427c13171106453f3b08dc3e9f84cab938c1154bca0611e720d41e7c6e
|
7
|
+
data.tar.gz: b1214c3a8936c7fb605b731ed0b638a4aad0185890c3b58f4d083ac8ec950d3fe565e0bc863a29b3888d4e7762ed2b2e14237e5d2a51f2ba424fa50faa2cecdb
|
data/README.md
CHANGED
@@ -1,49 +1,122 @@
|
|
1
|
+
[](https://codeclimate.com/github/kaspernj/http2)
|
2
|
+
[](https://www.peakflow.io/en/projects/http2/build-groups)
|
4
|
+
|
1
5
|
# http2
|
2
6
|
|
3
|
-
|
4
|
-
[](https://codeclimate.com/github/kaspernj/http2)
|
5
|
-
[](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
|
-
|
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
|
-
#
|
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
|
-
|
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
|
-
|
43
|
-
|
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
|
-
##
|
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
|
-
|
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
|
-
|
9
|
-
|
6
|
+
warn e.message
|
7
|
+
warn "Run `bundle install` to install missing gems"
|
10
8
|
exit e.status_code
|
11
9
|
end
|
12
|
-
require
|
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
|
29
|
-
require
|
12
|
+
require "rspec/core"
|
13
|
+
require "rspec/core/rake_task"
|
30
14
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
-
spec.pattern = FileList[
|
15
|
+
spec.pattern = FileList["spec/**/*_spec.rb"]
|
32
16
|
end
|
33
17
|
|
34
18
|
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
-
spec.pattern =
|
19
|
+
spec.pattern = "spec/**/*_spec.rb"
|
36
20
|
spec.rcov = true
|
37
21
|
end
|
38
22
|
|
39
|
-
task :
|
23
|
+
task default: :spec
|
40
24
|
|
41
|
-
require
|
25
|
+
require "rdoc/task"
|
42
26
|
Rake::RDocTask.new do |rdoc|
|
43
|
-
version = File.exist?(
|
27
|
+
version = File.exist?("VERSION") ? File.read("VERSION") : ""
|
44
28
|
|
45
|
-
rdoc.rdoc_dir =
|
29
|
+
rdoc.rdoc_dir = "rdoc"
|
46
30
|
rdoc.title = "http2 #{version}"
|
47
|
-
rdoc.rdoc_files.include(
|
48
|
-
rdoc.rdoc_files.include(
|
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
|
data/lib/http2.rb
CHANGED
@@ -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.
|
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
|
-
|
21
|
-
return Http2.const_get(name)
|
22
|
-
end
|
21
|
+
file_path = "#{File.dirname(__FILE__)}/http2/#{::StringCases.camel_to_snake(name)}.rb"
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
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 = [
|
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
|
-
|
49
|
+
destroy
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
54
|
def host
|
54
|
-
@args
|
55
|
+
@args.fetch(:host)
|
55
56
|
end
|
56
57
|
|
57
58
|
def port
|
58
|
-
@args
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
127
|
+
post(args.merge(method: :delete))
|
128
128
|
else
|
129
|
-
|
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.
|
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
|
-
|
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
|
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
|
-
|
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 |
|
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
|
-
|
198
|
-
|
199
|
-
value = cookie_data["value"]
|
200
|
-
else
|
201
|
-
name = cookie_name
|
202
|
-
value = cookie_data
|
203
|
-
end
|
202
|
+
cstr
|
203
|
+
end
|
204
204
|
|
205
|
-
|
206
|
-
|
207
|
-
|
205
|
+
def cookie(name)
|
206
|
+
name = name.to_s
|
207
|
+
return @cookies.fetch(name) if @cookies.key?(name)
|
208
208
|
|
209
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
|
-
|
290
|
+
unless @args[:port]
|
273
291
|
if @args[:ssl]
|
274
292
|
@args[:port] = 443
|
275
293
|
else
|