syntropy 0.11 → 0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,15 +3,59 @@
3
3
  require 'qeweney'
4
4
 
5
5
  module Syntropy
6
+ # Extensions for the Qeweney::Request class
6
7
  module RequestExtensions
8
+ attr_reader :route_params
9
+ attr_accessor :route
10
+
11
+ # Initializes request with additional fields
12
+ def initialize(headers, adapter)
13
+ @headers = headers
14
+ @adapter = adapter
15
+ @route = nil
16
+ @route_params = {}
17
+ @ctx = nil
18
+ end
19
+
20
+ # Sets up mock request additional fields
21
+ def setup_mock_request
22
+ @route = nil
23
+ @route_params = {}
24
+ @ctx = nil
25
+ end
26
+
27
+ # Returns the request context
7
28
  def ctx
8
29
  @ctx ||= {}
9
30
  end
10
31
 
32
+ # Checks the request's HTTP method against the given accepted values. If not
33
+ # included in the accepted values, raises an exception. Otherwise, returns
34
+ # the request's HTTP method.
35
+ #
36
+ # @param accepted [Array<String>] list of accepted HTTP methods
37
+ # @return [String] request's HTTP method
11
38
  def validate_http_method(*accepted)
12
39
  raise Syntropy::Error.method_not_allowed if !accepted.include?(method)
40
+
41
+ method
13
42
  end
14
43
 
44
+ # Responds according to the given map. The given map defines the responses
45
+ # for each method. The value for each method is either an array containing
46
+ # the body and header values to use as response, or a proc returning such an
47
+ # array. For example:
48
+ #
49
+ # req.respond_by_http_method(
50
+ # 'head' => [nil, headers],
51
+ # 'get' => -> { [IO.read(fn), headers] }
52
+ # )
53
+ #
54
+ # If the request's method is not included in the given map, an exception is
55
+ # raised.
56
+ #
57
+ # @param map [Hash] hash mapping HTTP methods to responses
58
+ # @return [void]
15
59
  def respond_by_http_method(map)
16
60
  value = map[self.method]
17
61
  raise Syntropy::Error.method_not_allowed if !value
@@ -21,6 +65,12 @@ module Syntropy
21
65
  respond(body, headers)
22
66
  end
23
67
 
68
+ # Responds to GET requests with the given body and headers. Otherwise raises
69
+ # an exception.
70
+ #
71
+ # @param body [String, nil] response body
72
+ # @param headers [Hash] response headers
73
+ # @return [void]
24
74
  def respond_on_get(body, headers = {})
25
75
  case self.method
26
76
  when 'head'
@@ -28,10 +78,16 @@ module Syntropy
28
78
  when 'get'
29
79
  respond(body, headers)
30
80
  else
31
- raise Syntropy::Error.method_not_allowed
81
+ raise Syntropy::Error.method_not_allowed
32
82
  end
33
83
  end
34
84
 
85
+ # Responds to POST requests with the given body and headers. Otherwise
86
+ # raises an exception.
87
+ #
88
+ # @param body [String, nil] response body
89
+ # @param headers [Hash] response headers
90
+ # @return [void]
35
91
  def respond_on_post(body, headers = {})
36
92
  case self.method
37
93
  when 'head'
@@ -43,8 +99,38 @@ module Syntropy
43
99
  end
44
100
  end
45
101
 
102
+ # Validates and optionally converts request parameter value for the given
103
+ # parameter name against the given clauses. If no clauses are given,
104
+ # verifies the parameter value is not nil. A clause can be a class, such as
105
+ # String, Integer, etc, in which case the value is converted into the
106
+ # corresponding value. A clause can also be a range, for verifying the value
107
+ # is within the range. A clause can also be an array of two or more clauses,
108
+ # at least one of which should match the value. If the validation fails, an
109
+ # exception is raised. Example:
110
+ #
111
+ # height = req.validate_param(:height, Integer, 1..100)
112
+ #
113
+ # @param name [Symbol] parameter name
114
+ # @clauses [Array] one or more validation clauses
115
+ # @return [any] validated parameter value
46
116
  def validate_param(name, *clauses)
47
- value = query[name]
117
+ validate(query[name], *clauses)
118
+ end
119
+
120
+ # Validates and optionally converts a value against the given clauses. If no
121
+ # clauses are given, verifies the parameter value is not nil. A clause can
122
+ # be a class, such as String, Integer, etc, in which case the value is
123
+ # converted into the corresponding value. A clause can also be a range, for
124
+ # verifying the value is within the range. A clause can also be an array of
125
+ # two or more clauses, at least one of which should match the value. If the
126
+ # validation fails, an exception is raised.
127
+ #
128
+ # @param value [any] value
129
+ # @clauses [Array] one or more validation clauses
130
+ # @return [any] validated value
131
+ def validate(value, *clauses)
132
+ raise Syntropy::ValidationError, 'Validation error' if clauses.empty? && !value
133
+
48
134
  clauses.each do |c|
49
135
  valid = param_is_valid?(value, c)
50
136
  raise(Syntropy::ValidationError, 'Validation error') if !valid
@@ -54,6 +140,20 @@ module Syntropy
54
140
  value
55
141
  end
56
142
 
143
+ # Reads the request body and returns form data.
144
+ #
145
+ # @return [Hash] form data
146
+ def get_form_data
147
+ body = read
148
+ if !body || body.empty?
149
+ raise Syntropy::Error.new(Qeweney::Status::BAD_REQUEST, 'Missing form data')
150
+ end
151
+
152
+ Qeweney::Request.parse_form_data(body, headers)
153
+ rescue Qeweney::BadRequestError
154
+ raise Syntropy::Error.new(Qeweney::Status::BAD_REQUEST, 'Invalid form data')
155
+ end
156
+
57
157
  private
58
158
 
59
159
  BOOL_REGEXP = /^(t|f|true|false|on|off|1|0|yes|no)$/
@@ -61,6 +161,11 @@ module Syntropy
61
161
  INTEGER_REGEXP = /^[+-]?[0-9]+$/
62
162
  FLOAT_REGEXP = /^[+-]?[0-9]+(\.[0-9]+)?$/
63
163
 
164
+ # Returns true the given value matches the given condition.
165
+ #
166
+ # @param value [any] value
167
+ # @param cond [any] condition
168
+ # @return [bool]
64
169
  def param_is_valid?(value, cond)
65
170
  return cond.any? { |c| param_is_valid?(value, c) } if cond.is_a?(Array)
66
171
 
@@ -77,6 +182,11 @@ module Syntropy
77
182
  cond === value
78
183
  end
79
184
 
185
+ # Converts the given value according to the given class.
186
+ #
187
+ # @param value [any] value
188
+ # @param klass [Class] class
189
+ # @return [any] converted value
80
190
  def param_convert(value, klass)
81
191
  if klass == :bool
82
192
  value =~ BOOL_TRUE_REGEXP ? true : false