Class: Http2

Inherits:
Object
  • Object
show all
Defined in:
lib/http2.rb

Overview

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.

Examples

Http2.new(host: “www.somedomain.com”, port: 80, ssl: false, debug: false) do |http|

res = http.get("index.rhtml?show=some_page")
html = res.body
print html

res = res.post("index.rhtml?choice=login", {"username" => "John Doe", "password" => 123})
print res.body
print "#{res.headers}"

end

Defined Under Namespace

Classes: BaseRequest, Connection, Cookie, Errors, GetRequest, PostDataGenerator, PostMultipartRequest, PostRequest, Response, ResponseReader, UrlBuilder, Utils

Constant Summary collapse

VALID_ARGUMENTS_INITIALIZE =
[
  :host, :port, :skip_port_in_host_header, :ssl, :ssl_skip_verify, :nl, :user_agent, :raise_errors,
  :follow_redirects, :debug, :encoding_gzip, :autostate, :basic_auth, :extra_headers, :proxy
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Http2

Returns a new instance of Http2.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/http2.rb', line 38

def initialize(args = {})
  @args = parse_init_args(args)
  set_default_values
  @cookies = {}
  @mutex = Monitor.new
  @connection = ::Http2::Connection.new(self)

  if block_given?
    begin
      yield(self)
    ensure
      destroy
    end
  end
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



31
32
33
# File 'lib/http2.rb', line 31

def args
  @args
end

#autostateObject (readonly)

Returns the value of attribute autostate.



31
32
33
# File 'lib/http2.rb', line 31

def autostate
  @autostate
end

#connectionObject (readonly)

Returns the value of attribute connection.



31
32
33
# File 'lib/http2.rb', line 31

def connection
  @connection
end

#cookiesObject (readonly)

Returns the value of attribute cookies.



31
32
33
# File 'lib/http2.rb', line 31

def cookies
  @cookies
end

#debugObject (readonly)

Returns the value of attribute debug.



31
32
33
# File 'lib/http2.rb', line 31

def debug
  @debug
end

#keepalive_maxObject

Returns the value of attribute keepalive_max.



32
33
34
# File 'lib/http2.rb', line 32

def keepalive_max
  @keepalive_max
end

#keepalive_timeoutObject

Returns the value of attribute keepalive_timeout.



32
33
34
# File 'lib/http2.rb', line 32

def keepalive_timeout
  @keepalive_timeout
end

#mutexObject (readonly)

Returns the value of attribute mutex.



31
32
33
# File 'lib/http2.rb', line 31

def mutex
  @mutex
end

#nlObject (readonly)

Returns the value of attribute nl.



31
32
33
# File 'lib/http2.rb', line 31

def nl
  @nl
end

#raise_errorsObject (readonly)

Returns the value of attribute raise_errors.



31
32
33
# File 'lib/http2.rb', line 31

def raise_errors
  @raise_errors
end

#respObject (readonly)

Returns the value of attribute resp.



31
32
33
# File 'lib/http2.rb', line 31

def resp
  @resp
end

Class Method Details

.const_missing(name) ⇒ Object

Autoloader for subclasses.



20
21
22
23
24
25
26
27
28
29
# File 'lib/http2.rb', line 20

def self.const_missing(name)
  file_path = "#{File.dirname(__FILE__)}/http2/#{::StringCases.camel_to_snake(name)}.rb"

  if File.exist?(file_path)
    require file_path
    return Http2.const_get(name) if Http2.const_defined?(name)
  end

  super
end

Instance Method Details

#change(args) ⇒ Object

Closes current connection if any, changes the arguments on the object and reconnects keeping all cookies and other stuff intact.



80
81
82
83
84
# File 'lib/http2.rb', line 80

def change(args)
  @args.merge!(args)
  @connection.destroy
  @connection = ::Http2::Connection.new(self)
end


205
206
207
208
209
210
# File 'lib/http2.rb', line 205

def cookie(name)
  name = name.to_s
  return @cookies.fetch(name) if @cookies.key?(name)

  raise "No cookie by that name: '#{name}' in '#{@cookies.keys.join(", ")}'"
end


191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/http2.rb', line 191

def cookie_header_string
  cstr = ""

  first = true
  @cookies.each do |_cookie_name, cookie|
    cstr << "; " unless first
    first = false if first
    ensure_single_lines([cookie.name, cookie.value])
    cstr << "#{Http2::Utils.urlenc(cookie.name)}=#{Http2::Utils.urlenc(cookie.value)}"
  end

  cstr
end

#default_headers(args = {}) ⇒ Object

Returns the default headers for a request.

Examples

headers_hash = http.default_headers print “#headers_hash”



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/http2.rb', line 137

def default_headers(args = {})
  return args[:default_headers] if args[:default_headers]

  headers = {
    "Connection" => "Keep-Alive",
    "User-Agent" => @uagent,
    "Host" => host_header
  }

  headers["Accept-Encoding"] = "gzip" if @args[:encoding_gzip]

  if @args[:basic_auth]
    require "base64" unless ::Kernel.const_defined?(:Base64)
    headers["Authorization"] = "Basic #{Base64.strict_encode64("#{@args[:basic_auth][:user]}:#{@args[:basic_auth][:passwd]}").strip}"
  end

  if @args[:proxy] && @args[:proxy][:user] && @args[:proxy][:passwd] && !@connection.proxy_connect?
    require "base64" unless ::Kernel.const_defined?(:Base64)
    puts "Http2: Adding proxy auth header to request" if @debug
    headers["Proxy-Authorization"] = "Basic #{Base64.strict_encode64("#{@args[:proxy][:user]}:#{@args[:proxy][:passwd]}").strip}"
  end

  headers.merge!(@args[:extra_headers]) if @args[:extra_headers]
  headers.merge!(args[:headers]) if args[:headers]

  headers
end

#delete(args) ⇒ Object

Proxies the request to another method but forces the method to be “DELETE”.



125
126
127
128
129
130
131
# File 'lib/http2.rb', line 125

def delete(args)
  if args[:json]
    post(args.merge(method: :delete))
  else
    get(args.merge(method: :delete))
  end
end

#destroyObject

Destroys the object unsetting all variables and closing all sockets.

Examples

http.destroy



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/http2.rb', line 89

def destroy
  @cookies = nil
  @debug = nil
  @mutex = nil
  @uagent = nil
  @keepalive_timeout = nil
  @request_last = nil

  @connection.destroy
  @connection = nil
end

#ensure_single_lines(*strings) ⇒ Object



212
213
214
215
216
# File 'lib/http2.rb', line 212

def ensure_single_lines(*strings)
  strings.each do |string|
    raise "More than one line: #{string}." unless string.to_s.lines.to_a.length == 1
  end
end

#get(args) ⇒ Object

Returns a result-object based on the arguments.

Examples

res = http.get(“somepage.html”) print res.body #=> <String>-object containing the HTML gotten.



120
121
122
# File 'lib/http2.rb', line 120

def get(args)
  ::Http2::GetRequest.new(self, args).execute
end

#header_str(headers_hash) ⇒ Object

Returns a header-string which normally would be used for a request in the given state.



180
181
182
183
184
185
186
187
188
189
# File 'lib/http2.rb', line 180

def header_str(headers_hash)
  headers_hash["Cookie"] = cookie_header_string unless cookie_header_string.empty?

  headers_str = ""
  headers_hash.each do |key, val|
    headers_str << "#{key}: #{val}#{@nl}"
  end

  headers_str
end

#hostObject



54
55
56
# File 'lib/http2.rb', line 54

def host
  @args.fetch(:host)
end

#inspectObject



233
234
235
# File 'lib/http2.rb', line 233

def inspect
  to_s
end

#new_urlObject



70
71
72
73
74
75
76
77
# File 'lib/http2.rb', line 70

def new_url
  builder = Http2::UrlBuilder.new
  builder.host = host
  builder.port = port
  builder.protocol = @args[:protocol]

  builder
end

#on_content_call(args, str) ⇒ Object



218
219
220
# File 'lib/http2.rb', line 218

def on_content_call(args, str)
  args[:on_content].call(str) if args.key?(:on_content)
end

#parse_args(*args) ⇒ Object

Forces various stuff into arguments-hash like URL from original arguments and enables single-string-shortcuts and more.



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/http2.rb', line 102

def parse_args(*args)
  if args.length == 1 && args.first.is_a?(String)
    args = {url: args.first}
  elsif args.length == 1
    args = args.first
  else
    raise "Invalid arguments: '#{args.class.name}'"
  end

  raise "Invalid URL: '#{args[:url]}'" if args[:url] != "" && args[:url].to_s.split("\n").length != 1

  args
end

#portObject



58
59
60
# File 'lib/http2.rb', line 58

def port
  @args.fetch(:port)
end

#post(args) ⇒ Object

Posts to a certain page.

Examples

res = http.post(“login.php”, {“username” => “John Doe”, “password” => 123)



168
169
170
# File 'lib/http2.rb', line 168

def post(args)
  ::Http2::PostRequest.new(self, args).execute
end

#post_multipart(*args) ⇒ Object

Posts to a certain page using the multipart-method.

Examples

res = http.post_multipart(“upload.php”, => 123, “file” => Tempfile.new(?))



175
176
177
# File 'lib/http2.rb', line 175

def post_multipart(*args)
  ::Http2::PostMultipartRequest.new(self, *args).execute
end

#read_response(request, args = {}) ⇒ Object

Reads the response after posting headers and data.

Examples

res = http.read_response



225
226
227
# File 'lib/http2.rb', line 225

def read_response(request, args = {})
  ::Http2::ResponseReader.new(http2: self, sock: @sock, args: args, request: request).response
end

#reconnectObject



66
67
68
# File 'lib/http2.rb', line 66

def reconnect
  @connection.reconnect
end

#ssl?Boolean

Returns:

  • (Boolean)


62
63
64
# File 'lib/http2.rb', line 62

def ssl?
  @args[:ssl] ? true : false
end

#to_sObject



229
230
231
# File 'lib/http2.rb', line 229

def to_s
  "<Http2 host: #{host}:#{port}>"
end