Class: Amber::Http::Request

Inherits:
Amber::Http show all
Defined in:
lib/amber/http/request.rb

Constant Summary collapse

GET =
"GET"
POST =
"POST"
PUT =
"PUT"
DELETE =
"DELETE"

Instance Attribute Summary collapse

Attributes inherited from Amber::Http

#header

Instance Method Summary collapse

Constructor Details

#initialize(socket) ⇒ Request

Returns a new instance of Request.



9
10
11
12
13
14
15
# File 'lib/amber/http/request.rb', line 9

def initialize(socket)
  super

  @url = ""
  @query = {}
  @body = {}
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



2
3
4
# File 'lib/amber/http/request.rb', line 2

def body
  @body
end

#body_raw_dataObject (readonly)

Returns the value of attribute body_raw_data.



2
3
4
# File 'lib/amber/http/request.rb', line 2

def body_raw_data
  @body_raw_data
end

#methodObject (readonly)

Returns the value of attribute method.



2
3
4
# File 'lib/amber/http/request.rb', line 2

def method
  @method
end

#protocolObject (readonly)

Returns the value of attribute protocol.



2
3
4
# File 'lib/amber/http/request.rb', line 2

def protocol
  @protocol
end

#queryObject (readonly)

Returns the value of attribute query.



2
3
4
# File 'lib/amber/http/request.rb', line 2

def query
  @query
end

#urlObject (readonly)

Returns the value of attribute url.



2
3
4
# File 'lib/amber/http/request.rb', line 2

def url
  @url
end

Instance Method Details

#parse_body(data) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/amber/http/request.rb', line 159

def parse_body(data)
  @body_raw_data = data

  if @header.has_key?("Content-Type")
    content_type = @header["Content-Type"]
    if content_type.include? "application/x-www-form-urlencoded"
      self.parse_form_body(data)
    elsif content_type.include? "multipart/form-data"
      content_type_info = content_type.split("; ")
      content_type_info.each do |info|
        if info.include? "boundary"
          boundary_info = info.split('=')

          if boundary_info.length == 2
            boundary = boundary_info[1]
            self.parse_multipart_form_body(boundary, data)
          end
        end
      end
    end
  end
end

#parse_form_body(data) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/amber/http/request.rb', line 182

def parse_form_body(data)
  form_items = data.split('&')

  form_items.each do |item|
    item_info = item.split('=')
    if item_info.length == 2
      key = URI.decode item_info[0]
      value = URI.decode item_info[1]
      @body[key] = value
    end
  end
end

#parse_form_part(data) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/amber/http/request.rb', line 213

def parse_form_part(data)
  first_of_break = data.index("\r\n\r\n")
  unless first_of_break === nil
     = data.slice(0, first_of_break)
     = .gsub("\r\n", "; ")
     = .split("; ")
    content_disposition = ""
    content_name = ""

    .each do |info|
      if info.include? "Content-Disposition"
        info_array = info.split(': ')
        content_disposition = info_array[1] if info_array.length == 2

      elsif info.include? "name="
        info_array = info.split('=')
        content_name = info_array[1] if info_array.length == 2
      end
    end

    content_body = data.slice(first_of_break + 4, data.length - 4 - first_of_break - 2)

    unless content_name.empty?
      @body[content_name] = content_body
    end
  end
end

#parse_header_item(data) ⇒ Object



140
141
142
143
144
145
146
147
148
# File 'lib/amber/http/request.rb', line 140

def parse_header_item(data)
  header_item = data.split(": ")

  if header_item.length == 2
    @header[header_item[0]] = header_item[1]
  end

  return true
end

#parse_multipart_form_body(boundary, data) ⇒ Object



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/amber/http/request.rb', line 195

def parse_multipart_form_body(boundary, data)
  offset = 0
  boundary_string = "--#{boundary}"

  while offset = data.index(boundary_string, offset)
    next_offset = data.index(boundary_string, offset + 1)

    unless next_offset
      break
    end

    data_part = data.slice(offset + boundary_string.length + 2, next_offset - offset - boundary_string.length - 4)
    self.parse_form_part(data_part)

    offset = next_offset
  end
end

#parse_query(query_string) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/amber/http/request.rb', line 91

def parse_query(query_string)
  query_info = query_string.split "&"
  query_info.each do |query_info_item|
    query_item = query_info_item.split "="
    if query_item.length == 2
      query_item_key = URI.decode query_item[0]
      query_item_value = URI.decode query_item[1]
      if query_item_key.index "[]"
        pure_query_item_key = query_item_key.gsub '[]', ''
        if query_item_key.match /^\w+\[\]$/
          query_value = @query[pure_query_item_key]
          if query_value.is_a? Array
            query_value.push query_item_value
          else
            query_value = [query_item_value]
          end
          @query[pure_query_item_key] = query_value
          next
        end
      end
      @query[query_item_key] = query_item_value
    end
  end
end

#parse_request(data) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/amber/http/request.rb', line 55

def parse_request(data)
  request_info = data.split(' ')

  if request_info.length == 3
    case request_info[0]
    when GET
      @method = GET
    when POST
      @method = POST
    when PUT
      @method = PUT
    when DELETE
      @method = DELETE
    else
      return false
    end

    self.parse_url request_info[1]
    @protocol = request_info[2]
  end

  return true
end

#parse_url(url) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/amber/http/request.rb', line 79

def parse_url(url)
  if url.include? "?"
    url_info = url.split "?"
    @url = url_info[0]
    if url_info.length > 1
      self.parse_query url_info[1]
    end
    return
  end
  @url = url
end

#receiveObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/amber/http/request.rb', line 17

def receive
  unless self.receive_request
    STDERR.puts "Bad request"
    return false
  end

  self.receive_header

  if @header.has_key?("Content-Length")
    content_length = @header["Content-Length"].to_i

    if content_length > 0
      self.receive_body(content_length)
    end
  end

  # p @body_raw_data
  # p @body

  return true
end

#receive_body(size) ⇒ Object



150
151
152
153
154
155
156
157
# File 'lib/amber/http/request.rb', line 150

def receive_body(size)
  data = ""
  while data.length < size
    data << @socket.read(1)
  end
  # data = @socket.recv(size)
  self.parse_body(data)
end

#receive_headerObject



116
117
118
# File 'lib/amber/http/request.rb', line 116

def receive_header
  loop { break unless receive_header_item }
end

#receive_header_itemObject



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/amber/http/request.rb', line 120

def receive_header_item
  last_token = ""
  data = ""

  while buffer = @socket.recv(1)
    if last_token == "\r" && buffer == "\n"
      break
    end

    data << buffer
    last_token = buffer
  end

  if data == "\r"
    return false
  end

  self.parse_header_item(data.chomp)
end

#receive_requestObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/amber/http/request.rb', line 39

def receive_request
  last_token = ""
  data = ""

  while buffer = @socket.recv(1)
    if last_token == "\r" && buffer == "\n"
      break
    end

    data << buffer
    last_token = buffer
  end
  
  self.parse_request(data)
end