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.
-
#timeout ⇒ Integer
Timeout in milliseconds.
-
#username ⇒ String
HTTP username.
Attributes inherited from Message
Class Method Summary collapse
- .encode(string) ⇒ Object
- .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
-
#fingerprint? ⇒ Bool
‘true` if the Response should be fingerprinted for platforms, `false` otherwise.
-
#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.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/arachni/http/request.rb', line 123 def initialize( = {} ) [:method] ||= :get super( ) @train = false if @train.nil? @fingerprint = true if @fingerprint.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 |
#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
.encode(string) ⇒ Object
501 502 503 504 |
# File 'lib/arachni/http/request.rb', line 501 def encode( string ) @easy ||= Ethon::Easy.new( url: 'www.example.com' ) @easy.escape string end |
.from_rpc_data(data) ⇒ Request
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/arachni/http/request.rb', line 468 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.
491 492 493 494 495 496 497 498 499 |
# File 'lib/arachni/http/request.rb', line 491 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
429 430 431 |
# File 'lib/arachni/http/request.rb', line 429 def ==( other ) hash == other.hash end |
#asynchronous? ⇒ Boolean
Returns ‘true` if #mode is `:async`, `false` otherwise.
170 171 172 |
# File 'lib/arachni/http/request.rb', line 170 def asynchronous? mode == :async end |
#blocking? ⇒ Boolean
Returns ‘true` if #mode is `:sync`, `false` otherwise.
176 177 178 |
# File 'lib/arachni/http/request.rb', line 176 def blocking? mode == :sync end |
#body_parameters ⇒ Object
222 223 224 225 |
# File 'lib/arachni/http/request.rb', line 222 def body_parameters return {} if method != :post parameters.any? ? parameters : self.class.parse_body( body ) end |
#clear_callbacks ⇒ Object
Clears #on_complete callbacks.
256 257 258 |
# File 'lib/arachni/http/request.rb', line 256 def clear_callbacks @on_complete.clear end |
#effective_cookies ⇒ Object
211 212 213 214 215 216 |
# File 'lib/arachni/http/request.rb', line 211 def Cookie.from_string( url, headers['Cookie'] || '' ).inject({}) do |h, | h[.name] = .value h end.merge( ) end |
#effective_parameters ⇒ Object
218 219 220 |
# File 'lib/arachni/http/request.rb', line 218 def effective_parameters Utilities.uri_parse_query( url ).merge( parameters || {} ) end |
#fingerprint? ⇒ Bool
Returns ‘true` if the Arachni::HTTP::Response should be fingerprinted for platforms, `false` otherwise.
269 270 271 |
# File 'lib/arachni/http/request.rb', line 269 def fingerprint? @fingerprint end |
#follow_location? ⇒ Bool
Returns ‘true` if redirects should be followed, `false` otherwise.
262 263 264 |
# File 'lib/arachni/http/request.rb', line 262 def follow_location? !!@follow_location end |
#handle_response(response) ⇒ Object
307 308 309 310 311 |
# File 'lib/arachni/http/request.rb', line 307 def handle_response( response ) response.request = self @on_complete.each { |b| b.call response } response end |
#hash ⇒ Object
433 434 435 |
# File 'lib/arachni/http/request.rb', line 433 def hash to_h.hash end |
#high_priority? ⇒ Boolean
141 142 143 |
# File 'lib/arachni/http/request.rb', line 141 def high_priority? !!@high_priority end |
#inspect ⇒ Object
233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/arachni/http/request.rb', line 233 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
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
# File 'lib/arachni/http/request.rb', line 437 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
454 455 456 |
# File 'lib/arachni/http/request.rb', line 454 def marshal_load( h ) h.each { |k, v| instance_variable_set( "@#{k}", v ) } end |
#method(*args) ⇒ Symbol
Returns HTTP method.
182 183 184 185 |
# File 'lib/arachni/http/request.rb', line 182 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.
196 197 198 |
# File 'lib/arachni/http/request.rb', line 196 def method=( verb ) @method = verb.to_s.downcase.to_sym end |
#on_complete(&block) ⇒ Object
Can be invoked multiple times.
249 250 251 252 253 |
# File 'lib/arachni/http/request.rb', line 249 def on_complete( &block ) fail 'Block is missing.' if !block_given? @on_complete << block self end |
#prepare_headers ⇒ Object
507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
# File 'lib/arachni/http/request.rb', line 507 def prepare_headers 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 } headers['Cookie'] = . map { |k, v| "#{Cookie.encode( k )}=#{Cookie.encode( v )}" }. join( ';' ) headers.delete( 'Cookie' ) if headers['Cookie'].empty? headers end |
#run ⇒ Response
Will call #on_complete callbacks.
Performs the Arachni::HTTP::Request without going through Client.
303 304 305 |
# File 'lib/arachni/http/request.rb', line 303 def run client_run.tap { |r| r.request = self } end |
#to_h ⇒ Object
417 418 419 420 421 422 423 424 425 426 427 |
# File 'lib/arachni/http/request.rb', line 417 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.
460 461 462 |
# File 'lib/arachni/http/request.rb', line 460 def to_rpc_data marshal_dump end |
#to_s ⇒ String
Returns HTTP request string.
229 230 231 |
# File 'lib/arachni/http/request.rb', line 229 def to_s "#{headers_string}#{effective_body}" end |
#to_typhoeus ⇒ Typhoeus::Response
Returns ‘self` converted to a `Typhoeus::Request`.
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 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# File 'lib/arachni/http/request.rb', line 315 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, # If Content-Length is missing this option will have no effect, so # we'll also stream the body to make sure that we can at least abort # the reading of the response body if it exceeds this limit. 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 typhoeus_request = Typhoeus::Request.new( curl, ) if @on_complete.any? response_body_buffer = '' set_body_reader( typhoeus_request, response_body_buffer ) typhoeus_request.on_complete do |typhoeus_response| if typhoeus_request.[:maxfilesize] typhoeus_response.[:response_body] = response_body_buffer end fill_in_data_from_typhoeus_response typhoeus_response handle_response Response.from_typhoeus( typhoeus_response ) end end typhoeus_request end |
#train ⇒ Object
Flags that the response should be analyzed by the Trainer for new elements.
282 283 284 |
# File 'lib/arachni/http/request.rb', line 282 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.
276 277 278 |
# File 'lib/arachni/http/request.rb', line 276 def train? @train end |
#update_cookies ⇒ Object
Flags that the CookieJar should be updated with the Arachni::HTTP::Response cookies.
294 295 296 |
# File 'lib/arachni/http/request.rb', line 294 def @update_cookies = true end |
#update_cookies? ⇒ Bool
Returns ‘true` if the CookieJar should be updated with the Arachni::HTTP::Response cookies, `false` otherwise.
289 290 291 |
# File 'lib/arachni/http/request.rb', line 289 def @update_cookies end |