http 6.0.0-java

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.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +267 -0
  3. data/CONTRIBUTING.md +26 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.md +263 -0
  6. data/SECURITY.md +17 -0
  7. data/UPGRADING.md +491 -0
  8. data/http.gemspec +48 -0
  9. data/lib/http/base64.rb +22 -0
  10. data/lib/http/chainable/helpers.rb +62 -0
  11. data/lib/http/chainable/verbs.rb +136 -0
  12. data/lib/http/chainable.rb +377 -0
  13. data/lib/http/client.rb +230 -0
  14. data/lib/http/connection/internals.rb +141 -0
  15. data/lib/http/connection.rb +265 -0
  16. data/lib/http/content_type.rb +89 -0
  17. data/lib/http/errors.rb +67 -0
  18. data/lib/http/feature.rb +86 -0
  19. data/lib/http/features/auto_deflate.rb +230 -0
  20. data/lib/http/features/auto_inflate.rb +64 -0
  21. data/lib/http/features/caching/entry.rb +178 -0
  22. data/lib/http/features/caching/in_memory_store.rb +63 -0
  23. data/lib/http/features/caching.rb +216 -0
  24. data/lib/http/features/digest_auth.rb +234 -0
  25. data/lib/http/features/instrumentation.rb +149 -0
  26. data/lib/http/features/logging.rb +231 -0
  27. data/lib/http/features/normalize_uri.rb +34 -0
  28. data/lib/http/features/raise_error.rb +37 -0
  29. data/lib/http/form_data/composite_io.rb +106 -0
  30. data/lib/http/form_data/file.rb +95 -0
  31. data/lib/http/form_data/multipart/param.rb +62 -0
  32. data/lib/http/form_data/multipart.rb +106 -0
  33. data/lib/http/form_data/part.rb +52 -0
  34. data/lib/http/form_data/readable.rb +58 -0
  35. data/lib/http/form_data/urlencoded.rb +175 -0
  36. data/lib/http/form_data/version.rb +8 -0
  37. data/lib/http/form_data.rb +102 -0
  38. data/lib/http/headers/known.rb +90 -0
  39. data/lib/http/headers/normalizer.rb +50 -0
  40. data/lib/http/headers.rb +343 -0
  41. data/lib/http/mime_type/adapter.rb +43 -0
  42. data/lib/http/mime_type/json.rb +41 -0
  43. data/lib/http/mime_type.rb +96 -0
  44. data/lib/http/options/definitions.rb +189 -0
  45. data/lib/http/options.rb +241 -0
  46. data/lib/http/redirector.rb +157 -0
  47. data/lib/http/request/body.rb +181 -0
  48. data/lib/http/request/builder.rb +184 -0
  49. data/lib/http/request/proxy.rb +83 -0
  50. data/lib/http/request/writer.rb +186 -0
  51. data/lib/http/request.rb +375 -0
  52. data/lib/http/response/body.rb +172 -0
  53. data/lib/http/response/inflater.rb +60 -0
  54. data/lib/http/response/parser.rb +223 -0
  55. data/lib/http/response/status/reasons.rb +79 -0
  56. data/lib/http/response/status.rb +263 -0
  57. data/lib/http/response.rb +350 -0
  58. data/lib/http/retriable/delay_calculator.rb +91 -0
  59. data/lib/http/retriable/errors.rb +35 -0
  60. data/lib/http/retriable/performer.rb +197 -0
  61. data/lib/http/session.rb +280 -0
  62. data/lib/http/timeout/global.rb +229 -0
  63. data/lib/http/timeout/null.rb +225 -0
  64. data/lib/http/timeout/per_operation.rb +197 -0
  65. data/lib/http/uri/normalizer.rb +82 -0
  66. data/lib/http/uri/parsing.rb +182 -0
  67. data/lib/http/uri.rb +376 -0
  68. data/lib/http/version.rb +6 -0
  69. data/lib/http.rb +36 -0
  70. data/sig/deps.rbs +122 -0
  71. data/sig/http.rbs +1619 -0
  72. data/test/http/base64_test.rb +28 -0
  73. data/test/http/client_test.rb +739 -0
  74. data/test/http/connection_test.rb +1533 -0
  75. data/test/http/content_type_test.rb +190 -0
  76. data/test/http/errors_test.rb +28 -0
  77. data/test/http/feature_test.rb +49 -0
  78. data/test/http/features/auto_deflate_test.rb +317 -0
  79. data/test/http/features/auto_inflate_test.rb +213 -0
  80. data/test/http/features/caching_test.rb +942 -0
  81. data/test/http/features/digest_auth_test.rb +996 -0
  82. data/test/http/features/instrumentation_test.rb +246 -0
  83. data/test/http/features/logging_test.rb +654 -0
  84. data/test/http/features/normalize_uri_test.rb +41 -0
  85. data/test/http/features/raise_error_test.rb +77 -0
  86. data/test/http/form_data/composite_io_test.rb +215 -0
  87. data/test/http/form_data/file_test.rb +255 -0
  88. data/test/http/form_data/fixtures/the-http-gem.info +1 -0
  89. data/test/http/form_data/multipart_test.rb +303 -0
  90. data/test/http/form_data/part_test.rb +90 -0
  91. data/test/http/form_data/urlencoded_test.rb +164 -0
  92. data/test/http/form_data_test.rb +232 -0
  93. data/test/http/headers/normalizer_test.rb +93 -0
  94. data/test/http/headers_test.rb +888 -0
  95. data/test/http/mime_type/json_test.rb +39 -0
  96. data/test/http/mime_type_test.rb +150 -0
  97. data/test/http/options/base_uri_test.rb +148 -0
  98. data/test/http/options/body_test.rb +21 -0
  99. data/test/http/options/features_test.rb +38 -0
  100. data/test/http/options/form_test.rb +21 -0
  101. data/test/http/options/headers_test.rb +32 -0
  102. data/test/http/options/json_test.rb +21 -0
  103. data/test/http/options/merge_test.rb +78 -0
  104. data/test/http/options/new_test.rb +37 -0
  105. data/test/http/options/proxy_test.rb +32 -0
  106. data/test/http/options_test.rb +575 -0
  107. data/test/http/redirector_test.rb +639 -0
  108. data/test/http/request/body_test.rb +318 -0
  109. data/test/http/request/builder_test.rb +623 -0
  110. data/test/http/request/writer_test.rb +391 -0
  111. data/test/http/request_test.rb +1733 -0
  112. data/test/http/response/body_test.rb +292 -0
  113. data/test/http/response/parser_test.rb +105 -0
  114. data/test/http/response/status_test.rb +322 -0
  115. data/test/http/response_test.rb +502 -0
  116. data/test/http/retriable/delay_calculator_test.rb +194 -0
  117. data/test/http/retriable/errors_test.rb +71 -0
  118. data/test/http/retriable/performer_test.rb +551 -0
  119. data/test/http/session_test.rb +424 -0
  120. data/test/http/timeout/global_test.rb +239 -0
  121. data/test/http/timeout/null_test.rb +218 -0
  122. data/test/http/timeout/per_operation_test.rb +220 -0
  123. data/test/http/uri/normalizer_test.rb +89 -0
  124. data/test/http/uri_test.rb +1140 -0
  125. data/test/http/version_test.rb +15 -0
  126. data/test/http_test.rb +818 -0
  127. data/test/regression_tests.rb +27 -0
  128. data/test/support/capture_warning.rb +10 -0
  129. data/test/support/dummy_server/encoding_routes.rb +47 -0
  130. data/test/support/dummy_server/routes.rb +201 -0
  131. data/test/support/dummy_server/servlet.rb +81 -0
  132. data/test/support/dummy_server.rb +200 -0
  133. data/test/support/fakeio.rb +21 -0
  134. data/test/support/http_handling_shared/connection_reuse_tests.rb +97 -0
  135. data/test/support/http_handling_shared/timeout_tests.rb +134 -0
  136. data/test/support/http_handling_shared.rb +11 -0
  137. data/test/support/proxy_server.rb +207 -0
  138. data/test/support/servers/runner.rb +67 -0
  139. data/test/support/simplecov.rb +28 -0
  140. data/test/support/ssl_helper.rb +108 -0
  141. data/test/test_helper.rb +38 -0
  142. metadata +218 -0
@@ -0,0 +1,223 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "llhttp"
4
+
5
+ module HTTP
6
+ class Response
7
+ # HTTP response parser backed by LLHttp
8
+ # @api private
9
+ class Parser
10
+ # The underlying LLHttp parser
11
+ # @return [LLHttp::Parser] the underlying parser
12
+ # @api private
13
+ attr_reader :parser
14
+
15
+ # The parsed response headers
16
+ # @return [HTTP::Headers] the parsed headers
17
+ # @api private
18
+ attr_reader :headers
19
+
20
+ # The parsed HTTP status code
21
+ # @return [Integer, nil] the parsed status code
22
+ # @api private
23
+ attr_reader :status_code
24
+
25
+ # The parsed HTTP version string
26
+ # @return [String, nil] the parsed HTTP version
27
+ # @api private
28
+ attr_reader :http_version
29
+
30
+ # Create a new response parser
31
+ # @return [Parser]
32
+ # @api private
33
+ def initialize
34
+ @handler = Handler.new(self)
35
+ @parser = LLHttp::Parser.new(@handler, type: :response)
36
+ reset
37
+ end
38
+
39
+ # Reset parser to initial state
40
+ # @return [void]
41
+ # @api private
42
+ def reset
43
+ @parser.reset
44
+ @handler.reset
45
+ @header_finished = false
46
+ @message_finished = false
47
+ @headers = Headers.new
48
+ @chunk = nil
49
+ @status_code = nil
50
+ @http_version = nil
51
+ end
52
+
53
+ # Feed data into the parser
54
+ # @return [Parser]
55
+ # @api private
56
+ def add(data)
57
+ parser << data
58
+
59
+ self
60
+ rescue LLHttp::Error => e
61
+ raise IOError, e.message
62
+ end
63
+
64
+ # @see #add
65
+ # @api private
66
+ alias << add
67
+
68
+ # Reset parser state for informational (1xx) responses
69
+ # @return [void]
70
+ # @api private
71
+ def reset_for_informational
72
+ @handler.reset
73
+ @header_finished = false
74
+ @message_finished = false
75
+ @headers = Headers.new
76
+ @chunk = nil
77
+ @status_code = nil
78
+ @http_version = nil
79
+ end
80
+
81
+ # Mark headers as finished
82
+ # @return [void]
83
+ # @api private
84
+ def mark_header_finished
85
+ @header_finished = true
86
+ @status_code = @parser.status_code
87
+ @http_version = "#{@parser.http_major}.#{@parser.http_minor}"
88
+ end
89
+
90
+ # Check if headers have been parsed
91
+ # @return [Boolean]
92
+ # @api private
93
+ def headers?
94
+ @header_finished
95
+ end
96
+
97
+ # Add a parsed header field and value
98
+ # @return [void]
99
+ # @api private
100
+ def add_header(name, value)
101
+ @headers.add(name, value)
102
+ end
103
+
104
+ # Mark the message as fully parsed
105
+ # @return [void]
106
+ # @api private
107
+ def mark_message_finished
108
+ @message_finished = true
109
+ end
110
+
111
+ # Check if the full message has been parsed
112
+ # @return [Boolean]
113
+ # @api private
114
+ def finished?
115
+ @message_finished
116
+ end
117
+
118
+ # Append a body chunk to the buffer
119
+ # @return [void]
120
+ # @api private
121
+ def add_body(chunk)
122
+ if @chunk
123
+ @chunk << chunk
124
+ else
125
+ @chunk = chunk
126
+ end
127
+ end
128
+
129
+ # Read up to size bytes from the body buffer
130
+ # @return [String, nil]
131
+ # @api private
132
+ def read(size)
133
+ return if @chunk.nil?
134
+
135
+ if @chunk.bytesize <= size
136
+ chunk = @chunk
137
+ @chunk = nil
138
+ else
139
+ chunk = @chunk.byteslice(0, size)
140
+ @chunk[0, size] = ""
141
+ end
142
+
143
+ chunk
144
+ end
145
+
146
+ # Delegate handler for LLHttp parser callbacks
147
+ # @api private
148
+ class Handler < LLHttp::Delegate
149
+ # Create a new parser handler
150
+ # @return [Handler]
151
+ # @api private
152
+ def initialize(target)
153
+ @target = target
154
+ super()
155
+ reset
156
+ end
157
+
158
+ # Reset handler state
159
+ # @return [void]
160
+ # @api private
161
+ def reset
162
+ @reading_header_value = false
163
+ @field_value = +""
164
+ @field = +""
165
+ end
166
+
167
+ # Handle a header field token
168
+ # @return [void]
169
+ # @api private
170
+ def on_header_field(field)
171
+ append_header if @reading_header_value
172
+ @field << field
173
+ end
174
+
175
+ # Handle a header value token
176
+ # @return [void]
177
+ # @api private
178
+ def on_header_value(value)
179
+ @reading_header_value = true
180
+ @field_value << value
181
+ end
182
+
183
+ # Handle headers complete callback
184
+ # @return [void]
185
+ # @api private
186
+ def on_headers_complete
187
+ append_header if @reading_header_value
188
+ @target.mark_header_finished
189
+ end
190
+
191
+ # Handle body data callback
192
+ # @return [void]
193
+ # @api private
194
+ def on_body(body)
195
+ @target.add_body(body)
196
+ end
197
+
198
+ # Handle message complete callback
199
+ # @return [void]
200
+ # @api private
201
+ def on_message_complete
202
+ if Integer(@target.status_code) < 200
203
+ @target.reset_for_informational
204
+ else
205
+ @target.mark_message_finished
206
+ end
207
+ end
208
+
209
+ private
210
+
211
+ # Flush the current header to the parser
212
+ # @return [void]
213
+ # @api private
214
+ def append_header
215
+ @target.add_header(@field, @field_value)
216
+ @reading_header_value = false
217
+ @field_value = +""
218
+ @field = +""
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ # AUTO-GENERATED FILE, DO NOT CHANGE IT MANUALLY
4
+
5
+ module HTTP
6
+ class Response
7
+ class Status
8
+ # Code to Reason map
9
+ #
10
+ # @example Usage
11
+ #
12
+ # REASONS[400] # => "Bad Request"
13
+ # REASONS[414] # => "Request-URI Too Long"
14
+ #
15
+ # @return [Hash<Fixnum => String>]
16
+ REASONS = {
17
+ 100 => "Continue",
18
+ 101 => "Switching Protocols",
19
+ 102 => "Processing",
20
+ 200 => "OK",
21
+ 201 => "Created",
22
+ 202 => "Accepted",
23
+ 203 => "Non-Authoritative Information",
24
+ 204 => "No Content",
25
+ 205 => "Reset Content",
26
+ 206 => "Partial Content",
27
+ 207 => "Multi-Status",
28
+ 208 => "Already Reported",
29
+ 226 => "IM Used",
30
+ 300 => "Multiple Choices",
31
+ 301 => "Moved Permanently",
32
+ 302 => "Found",
33
+ 303 => "See Other",
34
+ 304 => "Not Modified",
35
+ 305 => "Use Proxy",
36
+ 307 => "Temporary Redirect",
37
+ 308 => "Permanent Redirect",
38
+ 400 => "Bad Request",
39
+ 401 => "Unauthorized",
40
+ 402 => "Payment Required",
41
+ 403 => "Forbidden",
42
+ 404 => "Not Found",
43
+ 405 => "Method Not Allowed",
44
+ 406 => "Not Acceptable",
45
+ 407 => "Proxy Authentication Required",
46
+ 408 => "Request Timeout",
47
+ 409 => "Conflict",
48
+ 410 => "Gone",
49
+ 411 => "Length Required",
50
+ 412 => "Precondition Failed",
51
+ 413 => "Payload Too Large",
52
+ 414 => "URI Too Long",
53
+ 415 => "Unsupported Media Type",
54
+ 416 => "Range Not Satisfiable",
55
+ 417 => "Expectation Failed",
56
+ 421 => "Misdirected Request",
57
+ 422 => "Unprocessable Entity",
58
+ 423 => "Locked",
59
+ 424 => "Failed Dependency",
60
+ 426 => "Upgrade Required",
61
+ 428 => "Precondition Required",
62
+ 429 => "Too Many Requests",
63
+ 431 => "Request Header Fields Too Large",
64
+ 451 => "Unavailable For Legal Reasons",
65
+ 500 => "Internal Server Error",
66
+ 501 => "Not Implemented",
67
+ 502 => "Bad Gateway",
68
+ 503 => "Service Unavailable",
69
+ 504 => "Gateway Timeout",
70
+ 505 => "HTTP Version Not Supported",
71
+ 506 => "Variant Also Negotiates",
72
+ 507 => "Insufficient Storage",
73
+ 508 => "Loop Detected",
74
+ 510 => "Not Extended",
75
+ 511 => "Network Authentication Required"
76
+ }.each_value(&:freeze).freeze
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,263 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ require "http/response/status/reasons"
6
+
7
+ module HTTP
8
+ class Response
9
+ # Represents an HTTP response status code with reason phrase
10
+ class Status
11
+ include Comparable
12
+ extend Forwardable
13
+
14
+ class << self
15
+ # Coerces given value to Status
16
+ #
17
+ # @example
18
+ # Status.coerce(:bad_request) # => Status.new(400)
19
+ #
20
+ # @raise [Error] if coercion is impossible
21
+ # @param [Symbol, #to_i] object
22
+ # @return [Status]
23
+ # @api public
24
+ def coerce(object)
25
+ code = case object
26
+ when String then SYMBOL_CODES.fetch(symbolize(object), nil)
27
+ when Symbol then SYMBOL_CODES.fetch(object, nil)
28
+ when Numeric then object
29
+ end
30
+
31
+ return new code if code
32
+
33
+ raise Error, "Can't coerce #{object.class}(#{object}) to #{self}"
34
+ end
35
+ alias [] coerce
36
+
37
+ private
38
+
39
+ # Symbolizes given string
40
+ #
41
+ # @param [#to_s] str
42
+ # @return [Symbol]
43
+ # @api private
44
+ def symbolize(str)
45
+ str.downcase.tr("- ", "_").to_sym
46
+ end
47
+ end
48
+
49
+ # Code to Symbol map
50
+ #
51
+ # @example Usage
52
+ #
53
+ # SYMBOLS[400] # => :bad_request
54
+ # SYMBOLS[414] # => :request_uri_too_long
55
+ # SYMBOLS[418] # => :im_a_teapot
56
+ #
57
+ # @return [Hash<Fixnum => Symbol>]
58
+ SYMBOLS = REASONS.transform_values { |v| symbolize(v) }.freeze
59
+
60
+ # Reversed {SYMBOLS} map.
61
+ #
62
+ # @example Usage
63
+ #
64
+ # SYMBOL_CODES[:bad_request] # => 400
65
+ # SYMBOL_CODES[:request_uri_too_long] # => 414
66
+ # SYMBOL_CODES[:im_a_teapot] # => 418
67
+ #
68
+ # @return [Hash<Symbol => Fixnum>]
69
+ SYMBOL_CODES = SYMBOLS.to_h { |k, v| [v, k] }.freeze
70
+
71
+ # The numeric status code
72
+ #
73
+ # @example
74
+ # status.code # => 200
75
+ #
76
+ # @return [Fixnum] status code
77
+ # @api public
78
+ attr_reader :code
79
+
80
+ # @!method to_i
81
+ # Convert status to Integer
82
+ # @example
83
+ # status.to_i # => 200
84
+ # @return [Integer]
85
+ # @api public
86
+
87
+ # @!method to_int
88
+ # Implicit conversion to Integer
89
+ # @example
90
+ # status.to_int # => 200
91
+ # @return [Integer]
92
+ # @api public
93
+ def_delegators :@code, :to_i, :to_int
94
+
95
+ # Create a new Status from a value that responds to #to_i
96
+ #
97
+ # @example
98
+ # Status.new(200)
99
+ #
100
+ # @param [#to_i] obj
101
+ # @return [Status]
102
+ # @api public
103
+ def initialize(obj)
104
+ raise TypeError, "Expected #{obj.inspect} to respond to #to_i" unless obj.respond_to?(:to_i)
105
+
106
+ @code = obj.to_i
107
+ end
108
+
109
+ # Compare status codes for ordering
110
+ #
111
+ # @example
112
+ # Status.new(200) <=> Status.new(404) # => -1
113
+ #
114
+ # @param [#to_i] other
115
+ # @return [Integer, nil]
116
+ # @api public
117
+ def <=>(other)
118
+ return nil unless other.respond_to?(:to_i)
119
+
120
+ code <=> other.to_i
121
+ end
122
+
123
+ # Hash value based on status code
124
+ #
125
+ # @example
126
+ # Status.new(200).hash
127
+ #
128
+ # @return [Integer]
129
+ # @api public
130
+ def hash
131
+ code.hash
132
+ end
133
+
134
+ # Return the reason phrase for the status code
135
+ #
136
+ # @example
137
+ # status.reason # => "OK"
138
+ #
139
+ # @see REASONS
140
+ # @return [String, nil] status message
141
+ # @api public
142
+ def reason
143
+ REASONS[code]
144
+ end
145
+
146
+ # Return string representation of HTTP status
147
+ #
148
+ # @example
149
+ # status.to_s # => "200 OK"
150
+ #
151
+ # @return [String]
152
+ # @api public
153
+ def to_s
154
+ reason ? "#{code} #{reason}" : code.to_s
155
+ end
156
+
157
+ # Check if status code is informational (1XX)
158
+ #
159
+ # @example
160
+ # status.informational? # => false
161
+ #
162
+ # @return [Boolean]
163
+ # @api public
164
+ def informational?
165
+ 100 <= code && code < 200
166
+ end
167
+
168
+ # Check if status code is successful (2XX)
169
+ #
170
+ # @example
171
+ # status.success? # => true
172
+ #
173
+ # @return [Boolean]
174
+ # @api public
175
+ def success?
176
+ 200 <= code && code < 300
177
+ end
178
+
179
+ # Check if status code is redirection (3XX)
180
+ #
181
+ # @example
182
+ # status.redirect? # => false
183
+ #
184
+ # @return [Boolean]
185
+ # @api public
186
+ def redirect?
187
+ 300 <= code && code < 400
188
+ end
189
+
190
+ # Check if status code is client error (4XX)
191
+ #
192
+ # @example
193
+ # status.client_error? # => false
194
+ #
195
+ # @return [Boolean]
196
+ # @api public
197
+ def client_error?
198
+ 400 <= code && code < 500
199
+ end
200
+
201
+ # Check if status code is server error (5XX)
202
+ #
203
+ # @example
204
+ # status.server_error? # => false
205
+ #
206
+ # @return [Boolean]
207
+ # @api public
208
+ def server_error?
209
+ 500 <= code && code < 600
210
+ end
211
+
212
+ # Symbolized {#reason}
213
+ #
214
+ # @example
215
+ # status.to_sym # => :ok
216
+ #
217
+ # @return [nil] unless code is well-known (see REASONS)
218
+ # @return [Symbol]
219
+ # @api public
220
+ def to_sym
221
+ SYMBOLS[code]
222
+ end
223
+
224
+ # Printable version of HTTP Status
225
+ #
226
+ # @example
227
+ # status.inspect # => "#<HTTP::Response::Status 200 OK>"
228
+ #
229
+ # (see String#inspect)
230
+ # @return [String]
231
+ # @api public
232
+ def inspect
233
+ "#<#{self.class} #{self}>"
234
+ end
235
+
236
+ # Pattern matching interface for matching against status code and reason
237
+ #
238
+ # @example
239
+ # case response.status
240
+ # in { code: 200..299 }
241
+ # "success"
242
+ # in { code: 400.. }
243
+ # "error"
244
+ # end
245
+ #
246
+ # @param keys [Array<Symbol>, nil] keys to extract, or nil for all
247
+ # @return [Hash{Symbol => Object}]
248
+ # @api public
249
+ def deconstruct_keys(keys)
250
+ hash = { code: code, reason: reason }
251
+ keys ? hash.slice(*keys) : hash
252
+ end
253
+
254
+ SYMBOLS.each do |code, symbol|
255
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
256
+ def #{symbol}? # def bad_request?
257
+ #{code} == code # 400 == code
258
+ end # end
259
+ RUBY
260
+ end
261
+ end
262
+ end
263
+ end