Class: BetterCap::Proxy::Request

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

Overview

HTTP request parser.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(default_port = 80) ⇒ Request

Initialize this object setting #port to default_port.


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

def initialize( default_port = 80 )
  @lines  = []
  @verb   = nil
  @url    = nil
  @host   = nil
  @port   = default_port
  @headers = {}
  @content_length = 0
  @body   = nil
end

Instance Attribute Details

#bodyObject (readonly)

Request body.


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

def body
  @body
end

#content_lengthObject (readonly)

Content length.


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

def content_length
  @content_length
end

#headersObject (readonly)

Request headers hash.


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

def headers
  @headers
end

#hostObject (readonly)

Hostname.


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

def host
  @host
end

#linesObject (readonly)

Patched request lines.


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

def lines
  @lines
end

#portObject (readonly)

Request port.


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

def port
  @port
end

#urlObject (readonly)

Request URL.


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

def url
  @url
end

#verbObject (readonly)

HTTP verb.


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

def verb
  @verb
end

Instance Method Details

#<<(line) ⇒ Object

Parse a single request line, patch it if needed and append it to #lines.


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/bettercap/proxy/request.rb', line 70

def <<(line)
  line = line.chomp

  Logger.debug "  REQUEST LINE: '#{line}'"

  # is this the first line '<VERB> <URI> HTTP/<VERSION>' ?
  if @url.nil? and line =~ /^(\w+)\s+(\S+)\s+HTTP\/[\d\.]+\s*$/
    @verb    = $1
    @url     = $2

    # fix url
    if @url.include? '://'
      uri = URI::parse @url
      @url = "#{uri.path}" + ( uri.query ? "?#{uri.query}" : '' )
    end

    line = "#{@verb} #{@url} HTTP/1.1"
  # get the host header value
  elsif line =~ /^Host:\s*(.*)$/
    @host = $1
    if host =~ /([^:]*):([0-9]*)$/
      @host = $1
      @port = $2.to_i
    end
  # parse content length, this will speed up data streaming
  elsif line =~ /^Content-Length:\s+(\d+)\s*$/i
    @content_length = $1.to_i
  # we don't want to have hundreds of threads running
  elsif line =~ /^Connection: keep-alive/i
    line = 'Connection: close'
  elsif line =~ /^Proxy-Connection: (.+)/i
    line = "Connection: #{$1}"
  # disable gzip, chunked, etc encodings
  elsif line =~ /^Accept-Encoding:.*/i
    line = 'Accept-Encoding: identity'
  end

  # collect headers
  if line =~ /^([^:\s]+)\s*:\s*(.+)$/i
    @headers[$1] = $2
  end

  @lines << line
end

#post?Boolean

Return true if this is a POST request, otherwise false.

Returns:

  • (Boolean)

116
117
118
# File 'lib/bettercap/proxy/request.rb', line 116

def post?
  @verb == 'POST'
end

#read(sock) ⇒ Object

Read lines from the sock socket and parse them. Will raise an exception if the #hostname can not be parsed.


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/bettercap/proxy/request.rb', line 48

def read(sock)
  # read the first line
  self << sock.readline

  loop do
    line = sock.readline
    self << line

    if line.chomp == ''
      break
    end
  end

  raise "Couldn't extract host from the request." unless @host

  # keep reading the request body if needed
  if @content_length > 0
    @body = sock.read(@content_length)
  end
end

#to_sObject

Return a string representation of the HTTP request.


121
122
123
# File 'lib/bettercap/proxy/request.rb', line 121

def to_s
  @lines.join("\n") + "\n" + ( @body || '' )
end