class Amber::Http::Request

Constants

DELETE
GET
POST
PUT

Attributes

body[R]
body_raw_data[R]
method[R]
protocol[R]
query[R]
url[R]

Public Class Methods

new(socket) click to toggle source
Calls superclass method Amber::Http::new
# File lib/amber/http/request.rb, line 9
def initialize(socket)
  super

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

Public Instance Methods

parse_body(data) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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
    content_info_data = data.slice(0, first_of_break)
    content_info_data = content_info_data.gsub("\r\n", "; ")
    content_info = content_info_data.split("; ")
    content_disposition = ""
    content_name = ""

    content_info.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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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
receive() click to toggle source
# 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) click to toggle source
# 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_header() click to toggle source
# File lib/amber/http/request.rb, line 116
def receive_header
  loop { break unless receive_header_item }
end
receive_header_item() click to toggle source
# 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_request() click to toggle source
# 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