http2 0.0.29 → 0.0.34
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![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
|
-
|
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
|
-
|
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
|