Class: Arachni::HTTP::Request
- Defined in:
- lib/arachni/http/request.rb,
lib/arachni/http/request/scope.rb
Overview
HTTP Request representation.
Defined Under Namespace
Classes: Scope
Constant Summary collapse
- REDIRECT_LIMIT =
Default redirect limit, RFC says 5 max.
5
- MODES =
Supported modes of operation.
[ # Asynchronous (non-blocking) (Default) :async, # Synchronous (blocking) :sync ]
Instance Attribute Summary collapse
-
#cookies ⇒ Hash
Cookies set for this request.
-
#effective_body ⇒ String
Transmitted HTTP request body.
-
#follow_location ⇒ Bool
Follow ‘Location` headers.
-
#headers_string ⇒ String
Transmitted HTTP request headers.
- #high_priority ⇒ Bool
-
#id ⇒ Integer
Auto-incremented ID for this request (set by Client#request).
-
#max_redirects ⇒ Integer
Maximum number of redirects to follow.
-
#mode ⇒ Symbol
Mode of operation for the request.
-
#parameters ⇒ Hash
Request parameters.
-
#password ⇒ String
HTTP password.
-
#performer ⇒ Object
Entity which performed the request – mostly used to track which response was a result of which submitted element.
-
#proxy ⇒ String
‘host:port`.
- #proxy_type ⇒ String
-
#proxy_user_password ⇒ String
‘user:password`.
-
#response_max_size ⇒ Integer
Maximum HTTP response size to accept, in bytes.
- #root_redirect_id ⇒ Object
-
#timeout ⇒ Integer
Timeout in milliseconds.
-
#username ⇒ String
HTTP username.
Attributes inherited from Message
Class Method Summary collapse
- .from_rpc_data(data) ⇒ Request
-
.parse_body(body) ⇒ Hash
Parses an HTTP request body generated by submitting a form.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#asynchronous? ⇒ Boolean
‘true` if #mode is `:async`, `false` otherwise.
-
#blocking? ⇒ Boolean
‘true` if #mode is `:sync`, `false` otherwise.
- #body_parameters ⇒ Object
-
#clear_callbacks ⇒ Object
Clears #on_complete callbacks.
- #effective_cookies ⇒ Object
- #effective_parameters ⇒ Object
-
#follow_location? ⇒ Bool
‘true` if redirects should be followed, `false` otherwise.
- #handle_response(response) ⇒ Object
- #hash ⇒ Object
- #high_priority? ⇒ Boolean
-
#initialize(options = {}) ⇒ Request
constructor
A new instance of Request.
- #inspect ⇒ Object
- #marshal_dump ⇒ Object
- #marshal_load(h) ⇒ Object
-
#method(*args) ⇒ Symbol
HTTP method.
-
#method=(verb) ⇒ Symbol
Sets the request HTTP method.
- #on_complete(&block) ⇒ Object
- #prepare_headers ⇒ Object
- #run ⇒ Response
- #to_h ⇒ Object
-
#to_rpc_data ⇒ Hash
Data representing this instance that are suitable the RPC transmission.
-
#to_s ⇒ String
HTTP request string.
-
#to_typhoeus ⇒ Typhoeus::Response
‘self` converted to a `Typhoeus::Request`.
-
#train ⇒ Object
Flags that the response should be analyzed by the Trainer for new elements.
- #train? ⇒ Bool
- #update_cookies ⇒ Object
- #update_cookies? ⇒ Bool
Methods inherited from Message
Constructor Details
#initialize(options = {}) ⇒ Request
Returns a new instance of Request.
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/arachni/http/request.rb', line 126 def initialize( = {} ) [:method] ||= :get super( ) @train = false if @train.nil? @update_cookies = false if @update_cookies.nil? @follow_location = false if @follow_location.nil? @max_redirects = (Options.http.request_redirect_limit || REDIRECT_LIMIT) @on_complete = [] @timeout ||= Options.http.request_timeout @mode ||= :async @parameters ||= {} @cookies ||= {} end |
Instance Attribute Details
#cookies ⇒ Hash
Returns Cookies set for this request.
62 63 64 |
# File 'lib/arachni/http/request.rb', line 62 def @cookies end |
#effective_body ⇒ String
Available only via completed Arachni::HTTP::Response#request.
Returns Transmitted HTTP request body.
80 81 82 |
# File 'lib/arachni/http/request.rb', line 80 def effective_body @effective_body end |
#follow_location ⇒ Bool
Returns Follow ‘Location` headers.
44 45 46 |
# File 'lib/arachni/http/request.rb', line 44 def follow_location @follow_location end |
#headers_string ⇒ String
Available only via completed Arachni::HTTP::Response#request.
Returns Transmitted HTTP request headers.
74 75 76 |
# File 'lib/arachni/http/request.rb', line 74 def headers_string @headers_string end |
#high_priority ⇒ Bool
98 99 100 |
# File 'lib/arachni/http/request.rb', line 98 def high_priority @high_priority end |
#id ⇒ Integer
Returns Auto-incremented ID for this request (set by Client#request).
32 33 34 |
# File 'lib/arachni/http/request.rb', line 32 def id @id end |
#max_redirects ⇒ Integer
Returns Maximum number of redirects to follow.
50 51 52 |
# File 'lib/arachni/http/request.rb', line 50 def max_redirects @max_redirects end |
#mode ⇒ Symbol
Returns Mode of operation for the request.
68 69 70 |
# File 'lib/arachni/http/request.rb', line 68 def mode @mode end |
#parameters ⇒ Hash
Returns Request parameters.
36 37 38 |
# File 'lib/arachni/http/request.rb', line 36 def parameters @parameters end |
#password ⇒ String
Returns HTTP password.
58 59 60 |
# File 'lib/arachni/http/request.rb', line 58 def password @password end |
#performer ⇒ Object
Entity which performed the request – mostly used to track which response was a result of which submitted element.
84 85 86 |
# File 'lib/arachni/http/request.rb', line 84 def performer @performer end |
#proxy ⇒ String
Returns ‘host:port`.
88 89 90 |
# File 'lib/arachni/http/request.rb', line 88 def proxy @proxy end |
#proxy_type ⇒ String
95 96 97 |
# File 'lib/arachni/http/request.rb', line 95 def proxy_type @proxy_type end |
#proxy_user_password ⇒ String
Returns ‘user:password`.
92 93 94 |
# File 'lib/arachni/http/request.rb', line 92 def proxy_user_password @proxy_user_password end |
#response_max_size ⇒ Integer
Returns Maximum HTTP response size to accept, in bytes.
102 103 104 |
# File 'lib/arachni/http/request.rb', line 102 def response_max_size @response_max_size end |
#root_redirect_id ⇒ Object
105 106 107 |
# File 'lib/arachni/http/request.rb', line 105 def root_redirect_id @root_redirect_id end |
#timeout ⇒ Integer
Returns Timeout in milliseconds.
40 41 42 |
# File 'lib/arachni/http/request.rb', line 40 def timeout @timeout end |
#username ⇒ String
Returns HTTP username.
54 55 56 |
# File 'lib/arachni/http/request.rb', line 54 def username @username end |
Class Method Details
.from_rpc_data(data) ⇒ Request
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/arachni/http/request.rb', line 451 def from_rpc_data( data ) instance = allocate data.each do |name, value| value = case name when 'method', 'mode' value.to_sym else value end instance.instance_variable_set( "@#{name}", value ) end instance end |
.parse_body(body) ⇒ Hash
Parses an HTTP request body generated by submitting a form.
474 475 476 477 478 479 480 481 482 |
# File 'lib/arachni/http/request.rb', line 474 def parse_body( body ) return {} if !body body.to_s.split( '&' ).inject( {} ) do |h, pair| name, value = pair.split( '=', 2 ) h[Form.decode( name.to_s )] = Form.decode( value ) h end end |
Instance Method Details
#==(other) ⇒ Object
412 413 414 |
# File 'lib/arachni/http/request.rb', line 412 def ==( other ) hash == other.hash end |
#asynchronous? ⇒ Boolean
Returns ‘true` if #mode is `:async`, `false` otherwise.
172 173 174 |
# File 'lib/arachni/http/request.rb', line 172 def asynchronous? mode == :async end |
#blocking? ⇒ Boolean
Returns ‘true` if #mode is `:sync`, `false` otherwise.
178 179 180 |
# File 'lib/arachni/http/request.rb', line 178 def blocking? mode == :sync end |
#body_parameters ⇒ Object
224 225 226 227 |
# File 'lib/arachni/http/request.rb', line 224 def body_parameters return {} if method != :post parameters.any? ? parameters : self.class.parse_body( body ) end |
#clear_callbacks ⇒ Object
Clears #on_complete callbacks.
258 259 260 |
# File 'lib/arachni/http/request.rb', line 258 def clear_callbacks @on_complete.clear end |
#effective_cookies ⇒ Object
213 214 215 216 217 218 |
# File 'lib/arachni/http/request.rb', line 213 def Cookie.from_string( url, headers['Cookie'] || '' ).inject({}) do |h, | h[.name] = .value h end.merge( ) end |
#effective_parameters ⇒ Object
220 221 222 |
# File 'lib/arachni/http/request.rb', line 220 def effective_parameters Utilities.uri_parse_query( url ).merge( parameters || {} ) end |
#follow_location? ⇒ Bool
Returns ‘true` if redirects should be followed, `false` otherwise.
264 265 266 |
# File 'lib/arachni/http/request.rb', line 264 def follow_location? !!@follow_location end |
#handle_response(response) ⇒ Object
302 303 304 305 306 |
# File 'lib/arachni/http/request.rb', line 302 def handle_response( response ) response.request = self @on_complete.each { |b| b.call response } response end |
#hash ⇒ Object
416 417 418 |
# File 'lib/arachni/http/request.rb', line 416 def hash to_h.hash end |
#high_priority? ⇒ Boolean
143 144 145 |
# File 'lib/arachni/http/request.rb', line 143 def high_priority? !!@high_priority end |
#inspect ⇒ Object
235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/arachni/http/request.rb', line 235 def inspect s = "#<#{self.class} " s << "@id=#{id} " s << "@mode=#{mode} " s << "@method=#{method} " s << "@url=#{url.inspect} " s << "@parameters=#{parameters.inspect} " s << "@high_priority=#{high_priority} " s << "@performer=#{performer.inspect}" s << '>' end |
#marshal_dump ⇒ Object
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
# File 'lib/arachni/http/request.rb', line 420 def marshal_dump callbacks = @on_complete.dup performer = @performer @performer = nil @on_complete = [] instance_variables.inject( {} ) do |h, iv| next h if iv == :@scope h[iv.to_s.gsub('@','')] = instance_variable_get( iv ) h end ensure @on_complete = callbacks @performer = performer end |
#marshal_load(h) ⇒ Object
437 438 439 |
# File 'lib/arachni/http/request.rb', line 437 def marshal_load( h ) h.each { |k, v| instance_variable_set( "@#{k}", v ) } end |
#method(*args) ⇒ Symbol
Returns HTTP method.
184 185 186 187 |
# File 'lib/arachni/http/request.rb', line 184 def method( *args ) return super( *args ) if args.any? # Preserve Object#method. @method end |
#method=(verb) ⇒ Symbol
Method will be normalized to a lower-case symbol.
Sets the request HTTP method.
198 199 200 |
# File 'lib/arachni/http/request.rb', line 198 def method=( verb ) @method = verb.to_s.downcase.to_sym end |
#on_complete(&block) ⇒ Object
Can be invoked multiple times.
251 252 253 254 255 |
# File 'lib/arachni/http/request.rb', line 251 def on_complete( &block ) fail 'Block is missing.' if !block_given? @on_complete << block self end |
#prepare_headers ⇒ Object
485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'lib/arachni/http/request.rb', line 485 def prepare_headers headers['Cookie'] = . map { |k, v| "#{Cookie.encode( k )}=#{Cookie.encode( v )}" }. join( ';' ) headers.delete( 'Cookie' ) if headers['Cookie'].empty? headers['User-Agent'] ||= Options.http.user_agent headers['Accept'] ||= 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' headers['From'] ||= Options. if Options. headers.each { |k, v| headers[k] = Header.encode( v ) if v } end |
#run ⇒ Response
Will call #on_complete callbacks.
Performs the Arachni::HTTP::Request without going through Client.
298 299 300 |
# File 'lib/arachni/http/request.rb', line 298 def run client_run.tap { |r| r.request = self } end |
#to_h ⇒ Object
400 401 402 403 404 405 406 407 408 409 410 |
# File 'lib/arachni/http/request.rb', line 400 def to_h { url: url, parameters: parameters, headers: headers, headers_string: headers_string, effective_body: effective_body, body: body, method: method } end |
#to_rpc_data ⇒ Hash
Returns Data representing this instance that are suitable the RPC transmission.
443 444 445 |
# File 'lib/arachni/http/request.rb', line 443 def to_rpc_data marshal_dump end |
#to_s ⇒ String
Returns HTTP request string.
231 232 233 |
# File 'lib/arachni/http/request.rb', line 231 def to_s "#{headers_string}#{effective_body}" end |
#to_typhoeus ⇒ Typhoeus::Response
Returns ‘self` converted to a `Typhoeus::Request`.
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/arachni/http/request.rb', line 310 def to_typhoeus prepare_headers if (userpwd = (@username || Options.http.authentication_username)) if (passwd = (@password || Options.http.authentication_password)) userpwd += ":#{passwd}" end end max_size = @response_max_size || Options.http.response_max_size # Weird I know, for some reason 0 gets ignored. max_size = 1 if max_size == 0 max_size = nil if max_size < 0 = { method: method, headers: headers, body: body, params: effective_parameters, userpwd: userpwd, followlocation: follow_location?, maxredirs: @max_redirects, ssl_verifypeer: !!Options.http.ssl_verify_peer, ssl_verifyhost: Options.http.ssl_verify_host ? 2 : 0, sslcert: Options.http.ssl_certificate_filepath, sslcerttype: Options.http.ssl_certificate_type, sslkey: Options.http.ssl_key_filepath, sslkeytype: Options.http.ssl_key_type, sslkeypasswd: Options.http.ssl_key_password, cainfo: Options.http.ssl_ca_filepath, capath: Options.http.ssl_ca_directory, sslversion: Options.http.ssl_version, accept_encoding: 'gzip, deflate', nosignal: true, maxfilesize: max_size, # Don't keep the socket alive if this is a blocking request because # it's going to be performed by an one-off Hydra. forbid_reuse: blocking?, verbose: true } [:timeout_ms] = timeout if timeout # This will allow GSS-Negotiate to work out of the box but shouldn't # have any adverse effects. if ![:userpwd] && !parsed_url.user [:userpwd] = ':' [:httpauth] = :gssnegotiate else [:httpauth] = :auto end if proxy .merge!( proxy: proxy, proxytype: (proxy_type || :http).to_sym ) if proxy_user_password [:proxyuserpwd] = proxy_user_password end elsif Options.http.proxy_host && Options.http.proxy_port .merge!( proxy: "#{Options.http.proxy_host}:#{Options.http.proxy_port}", proxytype: (Options.http.proxy_type || :http).to_sym ) if Options.http.proxy_username && Options.http.proxy_password [:proxyuserpwd] = "#{Options.http.proxy_username}:#{Options.http.proxy_password}" end end curl = parsed_url.query ? url.gsub( "?#{parsed_url.query}", '' ) : url r = Typhoeus::Request.new( curl, ) if @on_complete.any? r.on_complete do |typhoeus_response| fill_in_data_from_typhoeus_response typhoeus_response handle_response Response.from_typhoeus( typhoeus_response ) end end r end |
#train ⇒ Object
Flags that the response should be analyzed by the Trainer for new elements.
277 278 279 |
# File 'lib/arachni/http/request.rb', line 277 def train @train = true end |
#train? ⇒ Bool
Returns ‘true` if the Arachni::HTTP::Response should be analyzed by the Trainer for new elements, `false` otherwise.
271 272 273 |
# File 'lib/arachni/http/request.rb', line 271 def train? @train end |
#update_cookies ⇒ Object
Flags that the CookieJar should be updated with the Arachni::HTTP::Response cookies.
289 290 291 |
# File 'lib/arachni/http/request.rb', line 289 def @update_cookies = true end |
#update_cookies? ⇒ Bool
Returns ‘true` if the CookieJar should be updated with the Arachni::HTTP::Response cookies, `false` otherwise.
284 285 286 |
# File 'lib/arachni/http/request.rb', line 284 def @update_cookies end |