Module: RequestDataFiltering

Defined in:
lib/macaw_framework/data_filters/request_data_filtering.rb

Overview

Module containing methods to filter Strings

Constant Summary collapse

VARIABLE_PATTERN =
%r{:[^/]+}

Class Method Summary collapse

Class Method Details

.extract_body(client, body_first_line, content_length, max_body_size = 1_048_576) ⇒ Object

Method responsible for extracting the body from request



92
93
94
95
96
97
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 92

def self.extract_body(client, body_first_line, content_length, max_body_size = 1_048_576)
  raise PayloadTooLargeError if content_length > max_body_size

  body = client&.read(content_length)
  body_first_line << body.to_s
end

.extract_headers(client) ⇒ Object

Method responsible for extracting the headers from request



79
80
81
82
83
84
85
86
87
88
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 79

def self.extract_headers(client)
  header = client.gets&.delete("\n")&.delete("\r")
  headers = {}
  while header&.match(/\A[^:]+:\s*.+/)
    split_header = header.split(':', 2)
    headers[split_header[0].strip] = split_header[1].strip
    header = client.gets&.delete("\n")&.delete("\r")
  end
  [header, headers]
end

.extract_path(path) ⇒ Object

Method responsible for extracting the path from URI



71
72
73
74
75
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 71

def self.extract_path(path)
  return path if path.nil?

  path[0] == '/' ? path[1..].gsub('/', '.') : path.gsub('/', '.')
end

.extract_url_parameters(http_first_line) ⇒ Object

Method responsible for extracting the parameters from URI



101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 101

def self.extract_url_parameters(http_first_line)
  return http_first_line, nil unless http_first_line =~ /\?/

  path_and_parameters = http_first_line.split('?', 2)
  path = "#{path_and_parameters[0]} "
  parameters_array = path_and_parameters[1].split('&')
  parameters_array.map! do |item|
    split_item = item.split('=')
    { sanitize_parameter_name(split_item[0]) => sanitize_parameter_value(split_item[1]) }
  end
  parameters = {}
  parameters_array.each { |item| parameters.merge!(item) }
  [path, parameters]
end

.match_path_with_route(split_path, split_route) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 52

def self.match_path_with_route(split_path, split_route)
  split_route&.each_with_index do |var, index|
    return false if var != split_path[index] && !var.match?(VARIABLE_PATTERN)
  end

  true
end

.parse_request_data(client, routes, max_body_size = 1_048_576) ⇒ Object

Method responsible for extracting information provided by the client like Headers and Body

Raises:

  • (EOFError)


15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 15

def self.parse_request_data(client, routes, max_body_size = 1_048_576)
  first_line = client.gets
  raise EOFError if first_line.nil?

  path, parameters = extract_url_parameters(first_line.gsub(%r{\s*HTTP/\d+(?:\.\d+)?\s*$}i, ''))
  parameters = {} if parameters.nil?

  method_name = sanitize_method_name(path)
  method_name = select_path(method_name, routes, parameters)
  body_first_line, headers = extract_headers(client)
  body = extract_body(client, body_first_line, headers['Content-Length'].to_i, max_body_size)
  [path, method_name, headers, body, parameters]
end

.sanitize_method_name(path) ⇒ Object

Method responsible for sanitizing the method name



62
63
64
65
66
67
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 62

def self.sanitize_method_name(path)
  path = extract_path(path)
  method_name = path&.gsub('/', '.')&.strip&.downcase
  method_name&.gsub!(' ', '')
  method_name
end

.sanitize_parameter_name(name) ⇒ Object

Method responsible for sanitizing the parameter name



118
119
120
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 118

def self.sanitize_parameter_name(name)
  name&.gsub(/[^\w\s]/, '')
end

.sanitize_parameter_value(value) ⇒ Object

Method responsible for sanitizing the parameter value. URL-decodes percent-encoded characters (e.g. %40 → @, %20 → space, + → space).



125
126
127
128
129
130
131
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 125

def self.sanitize_parameter_value(value)
  return nil if value.nil?

  CGI.unescape(value)
rescue ArgumentError
  value
end

.select_path(method_name, routes, parameters) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/macaw_framework/data_filters/request_data_filtering.rb', line 29

def self.select_path(method_name, routes, parameters)
  return method_name if routes.include?(method_name)

  selected_route = nil
  routes.each do |route|
    split_route = route&.split('.')
    split_name = method_name&.split('.')

    next unless split_route&.length == split_name&.length
    next unless match_path_with_route(split_name, split_route)

    selected_route = route
    split_route&.each_with_index do |var, index|
      parameters[var[1..].to_sym] = split_name&.dig(index) if var =~ VARIABLE_PATTERN
    end
    break
  end

  raise EndpointNotMappedError if selected_route.nil?

  selected_route
end