Class: Arachni::HTTP::Response
- Defined in:
- lib/arachni/http/response.rb,
lib/arachni/http/response/scope.rb
Overview
HTTP Response representation.
Defined Under Namespace
Classes: Scope
Constant Summary collapse
- HTML_CONTENT_TYPES =
Set.new(%w(text/html application/xhtml+xml))
- HTML_IDENTIFIERS =
[ '<!doctype html', '<html', '<head', '<body', '<title', '<script' ]
- HTML_IDENTIFIER_REGEXPS =
HTML_IDENTIFIERS.map { |s| Regexp.new s, Regexp::IGNORECASE }
Instance Attribute Summary collapse
-
#app_time ⇒ Float
Approximate time the web application took to process the #request.
-
#code ⇒ Integer
HTTP response status code.
-
#headers_string ⇒ String
Raw headers.
-
#ip_address ⇒ String
IP address of the server.
-
#message ⇒ String
HTTP response status message.
-
#redirections ⇒ Array<Response>
Automatically followed redirections that eventually led to this response.
- #request ⇒ Request
-
#return_code ⇒ Symbol
`libcurl` return code.
-
#return_message ⇒ String
`libcurl` return code.
-
#time ⇒ Float
Time, in seconds, it took from the start until the full response was received.
-
#total_time ⇒ Float
Total time in seconds for the transfer, including name resolving, TCP connect etc.
Attributes inherited from Message
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object
- #body=(body) ⇒ Object
- #hash ⇒ Object
- #html? ⇒ Boolean
-
#initialize(options = {}) ⇒ Response
constructor
A new instance of Response.
-
#modified? ⇒ Boolean
`true` if the remote resource has been modified since the date given in the `If-Modified-Since` request header field, `false` otherwise.
-
#ok? ⇒ Boolean
`true` if the request was performed successfully and the response was received in full, `false` otherwise.
- #parse ⇒ Object
-
#partial? ⇒ Boolean
`true` if the client could not read the entire response, `false` otherwise.
-
#platforms ⇒ Platform
Applicable platforms for the page.
-
#redirect? ⇒ Boolean
(also: #redirection?)
`true` if the response is a `3xx` redirect *and* there is a `Location` header field.
-
#status_line ⇒ String
First line of the response.
-
#text? ⇒ Bool
`true` if the response body is textual in nature, `false` if binary, `nil` if could not be determined.
-
#timed_out? ⇒ Boolean
`true` if timed out, `false` otherwise.
- #to_h ⇒ Hash
- #to_page ⇒ Arachni::Page
-
#to_rpc_data ⇒ Hash
Data representing this instance that are suitable the RPC transmission.
-
#to_s ⇒ String
HTTP response string.
- #update_from_typhoeus(response, options = {}) ⇒ Object
Methods inherited from Message
Constructor Details
#initialize(options = {}) ⇒ Response
Returns a new instance of Response.
70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/arachni/http/response.rb', line 70 def initialize( = {} ) super( ) @body ||= '' @code ||= 0 # Holds the redirection responses that eventually led to this one. @redirections ||= [] @time ||= 0.0 end |
Instance Attribute Details
#app_time ⇒ Float
Returns Approximate time the web application took to process the #request.
68 69 70 |
# File 'lib/arachni/http/response.rb', line 68 def app_time @app_time end |
#code ⇒ Integer
Returns HTTP response status code.
26 27 28 |
# File 'lib/arachni/http/response.rb', line 26 def code @code end |
#headers_string ⇒ String
Returns Raw headers.
54 55 56 |
# File 'lib/arachni/http/response.rb', line 54 def headers_string @headers_string end |
#ip_address ⇒ String
Returns IP address of the server.
30 31 32 |
# File 'lib/arachni/http/response.rb', line 30 def ip_address @ip_address end |
#message ⇒ String
Returns HTTP response status message.
34 35 36 |
# File 'lib/arachni/http/response.rb', line 34 def @message end |
#redirections ⇒ Array<Response>
Returns Automatically followed redirections that eventually led to this response.
42 43 44 |
# File 'lib/arachni/http/response.rb', line 42 def redirections @redirections end |
#request ⇒ Request
Returns HTTP Arachni::HTTP::Request which triggered this Arachni::HTTP::Response.
38 39 40 |
# File 'lib/arachni/http/response.rb', line 38 def request @request end |
#return_code ⇒ Symbol
Returns `libcurl` return code.
46 47 48 |
# File 'lib/arachni/http/response.rb', line 46 def return_code @return_code end |
#return_message ⇒ String
Returns `libcurl` return code.
50 51 52 |
# File 'lib/arachni/http/response.rb', line 50 def @return_message end |
#time ⇒ Float
Returns Time, in seconds, it took from the start until the full response was received.
64 65 66 |
# File 'lib/arachni/http/response.rb', line 64 def time @time end |
#total_time ⇒ Float
Returns Total time in seconds for the transfer, including name resolving, TCP connect etc.
59 60 61 |
# File 'lib/arachni/http/response.rb', line 59 def total_time @total_time end |
Class Method Details
.from_rpc_data(data) ⇒ Request
241 242 243 244 245 |
# File 'lib/arachni/http/response.rb', line 241 def self.from_rpc_data( data ) data['request'] = Request.from_rpc_data( data['request'] ) data['return_code'] = data['return_code'].to_sym if data['return_code'] new data end |
.from_typhoeus(response, options = {}) ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/arachni/http/response.rb', line 285 def self.from_typhoeus( response, = {} ) redirections = response.redirections.map do |redirect| rurl = URI.to_absolute( redirect.headers['Location'], response.effective_url ) rurl ||= URI.normalize( response.effective_url ) # Broken redirection, skip it... next if !rurl new( .merge( url: rurl, code: redirect.code, headers: redirect.headers )) end.compact return_code = response.return_code = response. # A write error in this case will be because body reading was aborted # during our own callback in Request#set_body_reader. # # So, this is here just for consistency. if response.return_code == :write_error return_code = :filesize_exceeded = 'Maximum file size exceeded' end new( .merge( url: response.effective_url, code: response.code, ip_address: response.primary_ip, headers: response.headers, headers_string: response.response_headers, body: response.body, redirections: redirections, time: response.time, app_time: (response.timed_out? ? response.time : response.start_transfer_time - response.pretransfer_time).to_f, total_time: response.total_time.to_f, return_code: return_code, return_message: )) end |
Instance Method Details
#==(other) ⇒ Object
247 248 249 |
# File 'lib/arachni/http/response.rb', line 247 def ==( other ) hash == other.hash end |
#body=(body) ⇒ Object
193 194 195 196 197 198 199 200 |
# File 'lib/arachni/http/response.rb', line 193 def body=( body ) @body = body.to_s text_check = text? @body.recode! if text_check.nil? || text_check @body end |
#hash ⇒ Object
251 252 253 |
# File 'lib/arachni/http/response.rb', line 251 def hash to_h.hash end |
#html? ⇒ Boolean
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/arachni/http/response.rb', line 175 def html? # IF we've got a Content-Type that's all we need to know. if (ct = headers.content_type) ct = ct.split( ';' ).first ct.strip! return HTML_CONTENT_TYPES.include?( ct.downcase ) end # Server insists we should only only use the content-type. respect it. return false if headers['X-Content-Type-Options'].to_s.downcase.include?( 'nosniff' ) # If there's a doctype then we're good to go. return true if body.start_with?( '<!DOCTYPE html' ) # Last resort, sniff the content-type from several HTML tags. HTML_IDENTIFIER_REGEXPS.find { |regexp| body =~ regexp } end |
#modified? ⇒ Boolean
Depends on the response code.
Returns `true` if the remote resource has been modified since the date given in the `If-Modified-Since` request header field, `false` otherwise.
133 134 135 |
# File 'lib/arachni/http/response.rb', line 133 def modified? code != 304 end |
#ok? ⇒ Boolean
Returns `true` if the request was performed successfully and the response was received in full, `false` otherwise.
140 141 142 |
# File 'lib/arachni/http/response.rb', line 140 def ok? !return_code || return_code == :ok end |
#parse ⇒ Object
207 208 209 |
# File 'lib/arachni/http/response.rb', line 207 def parse Parser.new self end |
#partial? ⇒ Boolean
Returns `true` if the client could not read the entire response, `false` otherwise.
88 89 90 91 92 93 94 95 |
# File 'lib/arachni/http/response.rb', line 88 def partial? # Streamed response which was aborted before completing. return_code == :partial_file || return_code == :recv_error || # Normal response with some data written, but without reaching # content-length. (code != 0 && timed_out?) end |
#platforms ⇒ Platform
Returns Applicable platforms for the page.
99 100 101 |
# File 'lib/arachni/http/response.rb', line 99 def platforms Platform::Manager[url] end |
#redirect? ⇒ Boolean Also known as: redirection?
Returns `true` if the response is a `3xx` redirect *and* there is a `Location` header field.
119 120 121 |
# File 'lib/arachni/http/response.rb', line 119 def redirect? code >= 300 && code <= 399 && !!headers.location end |
#status_line ⇒ String
Returns First line of the response.
105 106 107 108 |
# File 'lib/arachni/http/response.rb', line 105 def status_line return if !headers_string @status_line ||= headers_string.lines.first.to_s.chomp.freeze end |
#text? ⇒ Bool
Returns `true` if the response body is textual in nature, `false` if binary, `nil` if could not be determined.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/arachni/http/response.rb', line 147 def text? return nil if !@body return nil if @is_text == :inconclusive return @is_text if !@is_text.nil? if (type = headers.content_type) return @is_text = true if type.start_with?( 'text/' ) # Non "text/" nor "application/" content types will surely not be # text-based so bail out early. return @is_text = false if !type.start_with?( 'application/' ) end # Last resort, more resource intensive binary detection. begin @is_text = !@body.binary? rescue ArgumentError @is_text = :inconclusive nil end end |
#timed_out? ⇒ Boolean
Returns `true` if timed out, `false` otherwise.
171 172 173 |
# File 'lib/arachni/http/response.rb', line 171 def timed_out? return_code == :operation_timedout end |
#to_h ⇒ Hash
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/arachni/http/response.rb', line 212 def to_h hash = {} instance_variables.each do |var| hash[var.to_s.gsub( /@/, '' ).to_sym] = instance_variable_get( var ) end hash[:headers] = {}.merge( hash[:headers] ) hash.delete( :normalize_url ) hash.delete( :is_text ) hash.delete( :scope ) hash.delete( :parsed_url ) hash.delete( :redirections ) hash.delete( :request ) hash.delete( :scope ) hash end |
#to_page ⇒ Arachni::Page
203 204 205 |
# File 'lib/arachni/http/response.rb', line 203 def to_page Page.from_response self end |
#to_rpc_data ⇒ Hash
Returns Data representing this instance that are suitable the RPC transmission.
233 234 235 236 237 |
# File 'lib/arachni/http/response.rb', line 233 def to_rpc_data data = to_h data[:request] = request.to_rpc_data data.my_stringify_keys(false) end |
#to_s ⇒ String
Returns HTTP response string.
112 113 114 |
# File 'lib/arachni/http/response.rb', line 112 def to_s "#{headers_string}#{body}" end |
#update_from_typhoeus(response, options = {}) ⇒ Object
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/arachni/http/response.rb', line 255 def update_from_typhoeus( response, = {} ) return_code = response.return_code = response. # A write error in this case will be because body reading was aborted # during our own callback in Request#set_body_reader. # # So, this is here just for consistency. if response.return_code == :write_error return_code = :filesize_exceeded = 'Maximum file size exceeded' end update( .merge( url: response.effective_url, code: response.code, ip_address: response.primary_ip, headers: response.headers, headers_string: response.response_headers, body: response.body, redirections: redirections, time: response.time, app_time: (response.timed_out? ? response.time : response.start_transfer_time - response.pretransfer_time).to_f, total_time: response.total_time.to_f, return_code: return_code, return_message: )) end |