Class: BetterCap::Proxy::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/bettercap/proxy/response.rb

Overview

HTTP response parser.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeResponse

Initialize this response object state.


35
36
37
38
39
40
41
42
43
44
# File 'lib/bettercap/proxy/response.rb', line 35

def initialize
  @content_type = nil
  @charset = 'UTF-8'
  @content_length = nil
  @body = ''
  @code = nil
  @headers = []
  @headers_done = false
  @chunked = false
end

Instance Attribute Details

#bodyObject

Response body.


32
33
34
# File 'lib/bettercap/proxy/response.rb', line 32

def body
  @body
end

#charsetObject (readonly)

Response charset, default to UTF-8.


20
21
22
# File 'lib/bettercap/proxy/response.rb', line 20

def charset
  @charset
end

#chunkedObject (readonly)

True if this is a chunked encoded response, otherwise false.


24
25
26
# File 'lib/bettercap/proxy/response.rb', line 24

def chunked
  @chunked
end

#codeObject

Response status code.


28
29
30
# File 'lib/bettercap/proxy/response.rb', line 28

def code
  @code
end

#content_lengthObject (readonly)

Response content length.


22
23
24
# File 'lib/bettercap/proxy/response.rb', line 22

def content_length
  @content_length
end

#content_typeObject (readonly)

Response content type.


18
19
20
# File 'lib/bettercap/proxy/response.rb', line 18

def content_type
  @content_type
end

#headersObject (readonly)

A list of response headers.


26
27
28
# File 'lib/bettercap/proxy/response.rb', line 26

def headers
  @headers
end

#headers_doneObject (readonly)

True if the parser finished to parse the headers, otherwise false.


30
31
32
# File 'lib/bettercap/proxy/response.rb', line 30

def headers_done
  @headers_done
end

Instance Method Details

#<<(line) ⇒ Object

Parse a single response line.


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/bettercap/proxy/response.rb', line 58

def <<(line)
  # we already parsed the heders, collect response body
  if @headers_done
    @body << line.force_encoding( @charset )
  else
    Logger.debug "  RESPONSE LINE: '#{line.chomp}'"

    # parse the response status
    if @code.nil? and line =~ /^HTTP\/[\d\.]+\s+(.+)/
      @code = $1.chomp

    # parse the content type
    elsif line =~ /^Content-Type:\s*([^;]+).*/i
      @content_type = $1.chomp
      if line =~ /^.+;\s*charset=(.+)/i
        @charset = $1.chomp
      end

    # parse content length
    elsif line =~ /^Content-Length:\s+(\d+)\s*$/i
      @content_length = $1.to_i

    # check if we have a chunked encoding
    elsif line =~ /^Transfer-Encoding:\s*chunked.*$/i
      @chunked = true
      line = nil

    # last line, we're done with the headers
    elsif line.chomp.empty?
      @headers_done = true

    end

    @headers << line.chomp unless line.nil?
  end
end

#convert_webrick_response!(response) ⇒ Object

Convert a webrick response to this class.


47
48
49
50
51
52
53
54
55
# File 'lib/bettercap/proxy/response.rb', line 47

def convert_webrick_response!(response)
  self << "HTTP/#{response.http_version} #{response.code} #{response.msg}"
  response.each do |key,value|
    self << "#{key}: #{value}"
  end
  self << "\n"
  @code = response.code
  @body = response.body || ''
end

#textual?Boolean

Return true if the response content type is textual, otherwise false.

Returns:

  • (Boolean)

96
97
98
# File 'lib/bettercap/proxy/response.rb', line 96

def textual?
  @content_type and ( @content_type =~ /^text\/.+/ or @content_type =~ /^application\/.+/ )
end

#to_sObject

Return a string representation of this response object, patching the Content-Length header if the #body was modified.


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/bettercap/proxy/response.rb', line 102

def to_s
  if textual?
    @headers.map! do |header|
      # update content length in case the body was
      # modified
      if header =~ /Content-Length:\s*(\d+)/i
        Logger.debug "Updating response content length from #{$1} to #{@body.bytesize}"

        "Content-Length: #{@body.bytesize}"
      else
        header
      end
    end
  end

  @headers.join("\n") + "\n" + @body
end