require "./message" require "./method" require "uri" require "json" class Message @@status_line_regex = /(?'method'[A-Z]+) (?'uri'[^ ]+) (?'protocol'(?'protocol_name'[^ ]+)\/(?'protocol_version'[0-9]+.[0-9]+))/ @@header_line_regex = /^(?'name'[^:]+): (?'values'.+)/ @protocol_name = "HTTP" @protocol_version = "1.0" @method : Method = Method::NON_STANDARD @uri : String = "/" @headers : Hash(String, String) = {} of String => String @body : String = "" def parse_message(request : String) protocol_name = Nil protocol_version = Nil method = Method::NON_STANDARD uri = "/" headers = {} of String => String body = "" current_header = "" is_body = false is_status_line = true request.chars.each do |char| if is_body body += char next end current_header += char if current_header == "\r\n" is_body = true next end if current_header.ends_with?("\r\n") # End of header if !is_status_line regexified_header = @@header_line_regex.match(current_header) if regexified_header.nil? raise "Header regex is broken :aie:" end headers[regexified_header["name"]] = regexified_header["values"].gsub({"\r": "", "\n": ""}) else is_status_line = false regexified_status_line = @@status_line_regex.match(current_header) if regexified_status_line.nil? raise "Status line regex is broken :aie:" end method = Method.parse?(regexified_status_line["method"]) uri = regexified_status_line["uri"] protocol_name = regexified_status_line["protocol_name"] protocol_version = regexified_status_line["protocol_version"] end current_header = "" end end return { "protocol_name" => protocol_name, "protocol_version" => protocol_version, "method" => method, "uri" => uri, "headers" => headers, "body" => body } end def parse_form_body(body : String) form_body = Hash(String, String).new() key = "" value = "" is_key = true body.chars.each do |char| if char == '=' is_key = false next end if char == '&' form_body[key] = value[0, value.size - 1] key = "" value = "" next end if is_key key += char else value += char end end form_body[key] = value return form_body end def is_form_body return "application/x-www-form-urlencoded" == @headers["Content-Type"]? end def is_json_body return "application/json" == @headers["Content-Type"]? end def get_body if is_json_body return Hash(String, JSON::Any).from_json @body elsif is_form_body return parse_form_body @body end end def header(header : String) return @headers[header]? end def headers return @headers end def body : String return @body end def method : Method return @method end def uri: String return @uri end end