hanami-controller 1.3.3 → 2.0.0.alpha1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -7
- data/README.md +295 -537
- data/hanami-controller.gemspec +3 -3
- data/lib/hanami/action.rb +653 -38
- data/lib/hanami/action/base_params.rb +2 -2
- data/lib/hanami/action/cache.rb +1 -139
- data/lib/hanami/action/cache/cache_control.rb +4 -4
- data/lib/hanami/action/cache/conditional_get.rb +4 -5
- data/lib/hanami/action/cache/directives.rb +1 -1
- data/lib/hanami/action/cache/expires.rb +3 -3
- data/lib/hanami/action/cookie_jar.rb +3 -3
- data/lib/hanami/action/cookies.rb +3 -62
- data/lib/hanami/action/flash.rb +2 -2
- data/lib/hanami/action/glue.rb +5 -31
- data/lib/hanami/action/halt.rb +12 -0
- data/lib/hanami/action/mime.rb +77 -491
- data/lib/hanami/action/params.rb +3 -3
- data/lib/hanami/action/rack/file.rb +1 -1
- data/lib/hanami/action/request.rb +30 -20
- data/lib/hanami/action/response.rb +174 -0
- data/lib/hanami/action/session.rb +8 -117
- data/lib/hanami/action/validatable.rb +2 -2
- data/lib/hanami/controller.rb +0 -210
- data/lib/hanami/controller/configuration.rb +51 -506
- data/lib/hanami/controller/version.rb +1 -1
- metadata +12 -21
- data/lib/hanami/action/callable.rb +0 -92
- data/lib/hanami/action/callbacks.rb +0 -214
- data/lib/hanami/action/configurable.rb +0 -50
- data/lib/hanami/action/exposable.rb +0 -126
- data/lib/hanami/action/exposable/guard.rb +0 -104
- data/lib/hanami/action/head.rb +0 -121
- data/lib/hanami/action/rack.rb +0 -411
- data/lib/hanami/action/rack/callable.rb +0 -47
- data/lib/hanami/action/rack/errors.rb +0 -53
- data/lib/hanami/action/redirect.rb +0 -59
- data/lib/hanami/action/throwable.rb +0 -169
data/lib/hanami/action/mime.rb
CHANGED
@@ -1,56 +1,23 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "hanami/utils"
|
2
|
+
require "rack/utils"
|
3
|
+
require "rack/mime"
|
4
4
|
|
5
5
|
module Hanami
|
6
|
-
|
7
|
-
# Mime type API
|
8
|
-
#
|
9
|
-
# @since 0.1.0
|
10
|
-
#
|
11
|
-
# @see Hanami::Action::Mime::ClassMethods#accept
|
6
|
+
class Action
|
12
7
|
module Mime
|
13
|
-
|
14
|
-
|
15
|
-
# @since 0.1.0
|
16
|
-
# @api private
|
17
|
-
HTTP_ACCEPT = 'HTTP_ACCEPT'.freeze
|
18
|
-
|
19
|
-
# The key that returns content mime type from the Rack env
|
20
|
-
#
|
21
|
-
# @since 1.2.0
|
22
|
-
# @api private
|
23
|
-
HTTP_CONTENT_TYPE = 'CONTENT_TYPE'.freeze
|
24
|
-
|
8
|
+
DEFAULT_CONTENT_TYPE = 'application/octet-stream'.freeze
|
9
|
+
DEFAULT_CHARSET = 'utf-8'.freeze
|
25
10
|
# The header key to set the mime type of the response
|
26
11
|
#
|
27
12
|
# @since 0.1.0
|
28
13
|
# @api private
|
29
14
|
CONTENT_TYPE = 'Content-Type'.freeze
|
30
15
|
|
31
|
-
# The default mime type for an incoming HTTP request
|
32
|
-
#
|
33
|
-
# @since 0.1.0
|
34
|
-
# @api private
|
35
|
-
DEFAULT_ACCEPT = '*/*'.freeze
|
36
|
-
|
37
|
-
# The default mime type that is returned in the response
|
38
|
-
#
|
39
|
-
# @since 0.1.0
|
40
|
-
# @api private
|
41
|
-
DEFAULT_CONTENT_TYPE = 'application/octet-stream'.freeze
|
42
|
-
|
43
|
-
# The default charset that is returned in the response
|
44
|
-
#
|
45
|
-
# @since 0.3.0
|
46
|
-
# @api private
|
47
|
-
DEFAULT_CHARSET = 'utf-8'.freeze
|
48
|
-
|
49
16
|
# Most commom MIME Types used for responses
|
50
17
|
#
|
51
18
|
# @since 1.0.0
|
52
19
|
# @api private
|
53
|
-
|
20
|
+
TYPES = {
|
54
21
|
txt: 'text/plain',
|
55
22
|
html: 'text/html',
|
56
23
|
json: 'application/json',
|
@@ -102,496 +69,115 @@ module Hanami
|
|
102
69
|
xml: 'application/xml',
|
103
70
|
xslt: 'application/xslt+xml',
|
104
71
|
yml: 'text/yaml',
|
105
|
-
zip: 'application/zip'
|
72
|
+
zip: 'application/zip'
|
73
|
+
}.freeze
|
106
74
|
|
107
|
-
|
108
|
-
|
109
|
-
#
|
110
|
-
# @param base [Class] the target action
|
111
|
-
#
|
112
|
-
# @since 0.1.0
|
113
|
-
# @api private
|
114
|
-
#
|
115
|
-
# @see http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-included
|
116
|
-
def self.included(base)
|
117
|
-
base.class_eval do
|
118
|
-
extend ClassMethods
|
119
|
-
prepend InstanceMethods
|
120
|
-
end
|
75
|
+
def self.content_type_with_charset(content_type, charset)
|
76
|
+
"#{content_type}; charset=#{charset}"
|
121
77
|
end
|
122
78
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
# @param formats[Array<Symbol>] one or more symbols representing mime type(s)
|
137
|
-
#
|
138
|
-
# @raise [Hanami::Controller::UnknownFormatError] if the symbol cannot
|
139
|
-
# be converted into a mime type
|
140
|
-
#
|
141
|
-
# @since 0.1.0
|
142
|
-
#
|
143
|
-
# @see Hanami::Controller::Configuration#format
|
144
|
-
#
|
145
|
-
# @example
|
146
|
-
# require 'hanami/controller'
|
147
|
-
#
|
148
|
-
# class Show
|
149
|
-
# include Hanami::Action
|
150
|
-
# accept :html, :json
|
151
|
-
#
|
152
|
-
# def call(params)
|
153
|
-
# # ...
|
154
|
-
# end
|
155
|
-
# end
|
156
|
-
#
|
157
|
-
# # When called with "*/*" => 200
|
158
|
-
# # When called with "text/html" => 200
|
159
|
-
# # When called with "application/json" => 200
|
160
|
-
# # When called with "application/xml" => 406
|
161
|
-
def accept(*formats)
|
162
|
-
mime_types = formats.map do |format|
|
163
|
-
format_to_mime_type(format)
|
164
|
-
end
|
165
|
-
|
166
|
-
configuration.restrict_mime_types!(mime_types)
|
167
|
-
|
168
|
-
before do
|
169
|
-
unless mime_types.find {|mt| accept?(mt) }
|
170
|
-
halt 406
|
171
|
-
end
|
172
|
-
end
|
79
|
+
# Use for setting Content-Type
|
80
|
+
# If the request has the ACCEPT header it will try to return the best Content-Type based
|
81
|
+
# on the content of the ACCEPT header taking in consideration the weights
|
82
|
+
#
|
83
|
+
# If no ACCEPT header it will check the default response_format, then the default request format and
|
84
|
+
# lastly it will fallback to DEFAULT_CONTENT_TYPE
|
85
|
+
#
|
86
|
+
# @return [String]
|
87
|
+
def self.content_type(configuration, request, accepted_mime_types)
|
88
|
+
if request.accept_header?
|
89
|
+
type = best_q_match(request.accept, accepted_mime_types)
|
90
|
+
return type if type
|
173
91
|
end
|
174
92
|
|
175
|
-
|
176
|
-
#
|
177
|
-
# @param formats[Array<Symbol>] one or more symbols representing mime type(s)
|
178
|
-
#
|
179
|
-
# @since 1.2.0
|
180
|
-
#
|
181
|
-
# @example
|
182
|
-
# require 'hanami/controller'
|
183
|
-
#
|
184
|
-
# class Upload
|
185
|
-
# include Hanami::Action
|
186
|
-
# content_type :json
|
187
|
-
#
|
188
|
-
# def call(params)
|
189
|
-
# # ...
|
190
|
-
# end
|
191
|
-
# end
|
192
|
-
#
|
193
|
-
# # When called with "text/html" => 415
|
194
|
-
# # When called with "application/json" => 200
|
195
|
-
def content_type(*formats)
|
196
|
-
mime_types = formats.map { |format| format_to_mime_type(format) }
|
197
|
-
|
198
|
-
before do
|
199
|
-
mime_type = @_env[HTTP_CONTENT_TYPE] || default_content_type || DEFAULT_CONTENT_TYPE
|
200
|
-
|
201
|
-
if mime_types.none? {|mt| ::Rack::Mime.match?(mime_type, mt) }
|
202
|
-
halt 415
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
93
|
+
default_response_type(configuration) || default_content_type(configuration) || DEFAULT_CONTENT_TYPE
|
206
94
|
end
|
207
95
|
|
208
|
-
|
209
|
-
|
210
|
-
module InstanceMethods
|
211
|
-
# @since 0.7.0
|
212
|
-
# @api private
|
213
|
-
def initialize(*)
|
214
|
-
super
|
215
|
-
@content_type = nil
|
216
|
-
@charset = nil
|
217
|
-
end
|
96
|
+
def self.charset(default_charset)
|
97
|
+
default_charset || DEFAULT_CHARSET
|
218
98
|
end
|
219
99
|
|
220
|
-
|
221
|
-
|
222
|
-
# The framework automatically detects the request mime type, and returns
|
223
|
-
# the corresponding format.
|
224
|
-
#
|
225
|
-
# However, if this value was explicitly set by `#format=`, it will return
|
226
|
-
# that value
|
227
|
-
#
|
228
|
-
# @return [Symbol] a symbol that corresponds to the content type
|
229
|
-
#
|
230
|
-
# @since 0.2.0
|
231
|
-
#
|
232
|
-
# @see Hanami::Action::Mime#format=
|
233
|
-
# @see Hanami::Action::Mime#content_type
|
234
|
-
#
|
235
|
-
# @example Default scenario
|
236
|
-
# require 'hanami/controller'
|
237
|
-
#
|
238
|
-
# class Show
|
239
|
-
# include Hanami::Action
|
240
|
-
#
|
241
|
-
# def call(params)
|
242
|
-
# end
|
243
|
-
# end
|
244
|
-
#
|
245
|
-
# action = Show.new
|
246
|
-
#
|
247
|
-
# _, headers, _ = action.call({ 'HTTP_ACCEPT' => 'text/html' })
|
248
|
-
# headers['Content-Type'] # => 'text/html'
|
249
|
-
# action.format # => :html
|
250
|
-
#
|
251
|
-
# @example Set value
|
252
|
-
# require 'hanami/controller'
|
253
|
-
#
|
254
|
-
# class Show
|
255
|
-
# include Hanami::Action
|
256
|
-
#
|
257
|
-
# def call(params)
|
258
|
-
# self.format = :xml
|
259
|
-
# end
|
260
|
-
# end
|
261
|
-
#
|
262
|
-
# action = Show.new
|
263
|
-
#
|
264
|
-
# _, headers, _ = action.call({ 'HTTP_ACCEPT' => 'text/html' })
|
265
|
-
# headers['Content-Type'] # => 'application/xml'
|
266
|
-
# action.format # => :xml
|
267
|
-
def format
|
268
|
-
@format ||= detect_format
|
100
|
+
def self.default_response_type(configuration)
|
101
|
+
format_to_mime_type(configuration.default_response_format, configuration)
|
269
102
|
end
|
270
103
|
|
271
|
-
|
272
|
-
|
273
|
-
# It prefers, in order:
|
274
|
-
# * Explicit set value (see Hanami::Action::Mime#format=)
|
275
|
-
# * Weighted value from Accept header based on all known MIME Types:
|
276
|
-
# - Custom registered MIME Types (see Hanami::Controller::Configuration#format)
|
277
|
-
# * Configured default content type (see Hanami::Controller::Configuration#default_response_format)
|
278
|
-
# * Hard-coded default content type (see Hanami::Action::Mime::DEFAULT_CONTENT_TYPE)
|
279
|
-
#
|
280
|
-
# To override the value, use <tt>#format=</tt>
|
281
|
-
#
|
282
|
-
# @return [String] the content type from the request.
|
283
|
-
#
|
284
|
-
# @since 0.1.0
|
285
|
-
#
|
286
|
-
# @see Hanami::Action::Mime#format=
|
287
|
-
# @see Hanami::Configuration#default_request_format
|
288
|
-
# @see Hanami::Action::Mime#default_content_type
|
289
|
-
# @see Hanami::Action::Mime#DEFAULT_CONTENT_TYPE
|
290
|
-
# @see Hanami::Controller::Configuration#format
|
291
|
-
# @see Hanami::Controller::Configuration#default_response_format
|
292
|
-
#
|
293
|
-
# @example
|
294
|
-
# require 'hanami/controller'
|
295
|
-
#
|
296
|
-
# class Show
|
297
|
-
# include Hanami::Action
|
298
|
-
#
|
299
|
-
# def call(params)
|
300
|
-
# # ...
|
301
|
-
# content_type # => 'text/html'
|
302
|
-
# end
|
303
|
-
# end
|
304
|
-
def content_type
|
305
|
-
return @content_type unless @content_type.nil?
|
306
|
-
@content_type = content_type_from_accept_header if accept_header?
|
307
|
-
@content_type || default_response_type || default_content_type || DEFAULT_CONTENT_TYPE
|
104
|
+
def self.default_content_type(configuration)
|
105
|
+
format_to_mime_type(configuration.default_request_format, configuration)
|
308
106
|
end
|
309
107
|
|
310
|
-
|
311
|
-
|
312
|
-
# @return [String] the charset of the request.
|
313
|
-
#
|
314
|
-
# @since 0.3.0
|
315
|
-
#
|
316
|
-
# @example
|
317
|
-
# require 'hanami/controller'
|
318
|
-
#
|
319
|
-
# class Show
|
320
|
-
# include Hanami::Action
|
321
|
-
#
|
322
|
-
# def call(params)
|
323
|
-
# # ...
|
324
|
-
# self.charset = 'koi8-r'
|
325
|
-
# end
|
326
|
-
# end
|
327
|
-
def charset=(value)
|
328
|
-
@charset = value
|
329
|
-
end
|
108
|
+
def self.format_to_mime_type(format, configuration)
|
109
|
+
return if format.nil?
|
330
110
|
|
331
|
-
|
332
|
-
|
333
|
-
# It prefers, in order:
|
334
|
-
# * Explicit set value (see #charset=)
|
335
|
-
# * Default configuration charset
|
336
|
-
# * Default content type
|
337
|
-
#
|
338
|
-
# To override the value, use <tt>#charset=</tt>
|
339
|
-
#
|
340
|
-
# @return [String] the charset of the request.
|
341
|
-
#
|
342
|
-
# @since 0.3.0
|
343
|
-
#
|
344
|
-
# @see Hanami::Action::Mime#charset=
|
345
|
-
# @see Hanami::Configuration#default_charset
|
346
|
-
# @see Hanami::Action::Mime#default_charset
|
347
|
-
# @see Hanami::Action::Mime#DEFAULT_CHARSET
|
348
|
-
#
|
349
|
-
# @example
|
350
|
-
# require 'hanami/controller'
|
351
|
-
#
|
352
|
-
# class Show
|
353
|
-
# include Hanami::Action
|
354
|
-
#
|
355
|
-
# def call(params)
|
356
|
-
# # ...
|
357
|
-
# charset # => 'text/html'
|
358
|
-
# end
|
359
|
-
# end
|
360
|
-
def charset
|
361
|
-
@charset || default_charset || DEFAULT_CHARSET
|
111
|
+
configuration.mime_type_for(format) ||
|
112
|
+
TYPES.fetch(format) { raise Hanami::Controller::UnknownFormatError.new(format) }
|
362
113
|
end
|
363
114
|
|
364
|
-
|
365
|
-
|
366
|
-
# Finalize the response by setting the current content type
|
115
|
+
# Transforms MIME Types to symbol
|
116
|
+
# Used for setting the format of the response
|
367
117
|
#
|
368
|
-
# @
|
369
|
-
# @
|
118
|
+
# @see Hanami::Action::Mime#finish
|
119
|
+
# @example
|
120
|
+
# detect_format("text/html; charset=utf-8", configuration) #=> :html
|
370
121
|
#
|
371
|
-
# @
|
372
|
-
def
|
373
|
-
|
374
|
-
|
122
|
+
# @return [Symbol, nil]
|
123
|
+
def self.detect_format(content_type, configuration)
|
124
|
+
return if content_type.nil?
|
125
|
+
ct = content_type.split(";").first
|
126
|
+
configuration.format_for(ct) || format_for(ct)
|
375
127
|
end
|
376
128
|
|
377
|
-
|
378
|
-
|
379
|
-
# The framework detects the `HTTP_ACCEPT` header of the request and sets
|
380
|
-
# the proper `Content-Type` header in the response.
|
381
|
-
# Within this default scenario, `#format` returns a symbol that
|
382
|
-
# corresponds to `#content_type`.
|
383
|
-
# For instance, if a client sends an `HTTP_ACCEPT` with `text/html`,
|
384
|
-
# `#content_type` will return `text/html` and `#format` `:html`.
|
385
|
-
#
|
386
|
-
# However, it's possible to override what the framework have detected.
|
387
|
-
# If a client asks for an `HTTP_ACCEPT` `*/*`, but we want to force the
|
388
|
-
# response to be a `text/html` we can use this method.
|
389
|
-
#
|
390
|
-
# When the format is set, the framework searches for a corresponding mime
|
391
|
-
# type to be set as the `Content-Type` header of the response.
|
392
|
-
# This lookup is performed first in the configuration, and then in
|
393
|
-
# `Hanami::Action::Mime::MIME_TYPES`. If the lookup fails, it raises an error.
|
394
|
-
#
|
395
|
-
# PERFORMANCE: Because `Hanami::Controller::Configuration#formats` is
|
396
|
-
# smaller and looked up first than `Hanami::Action::Mime::MIME_TYPES`,
|
397
|
-
# we suggest to configure the most common mime types used by your
|
398
|
-
# application, **even if they are already present in that Rack constant**.
|
399
|
-
#
|
400
|
-
# @param format [#to_sym] the format
|
401
|
-
#
|
402
|
-
# @return [void]
|
403
|
-
#
|
404
|
-
# @raise [TypeError] if the format cannot be coerced into a Symbol
|
405
|
-
# @raise [Hanami::Controller::UnknownFormatError] if the format doesn't
|
406
|
-
# have a corresponding mime type
|
407
|
-
#
|
408
|
-
# @since 0.2.0
|
409
|
-
#
|
410
|
-
# @see Hanami::Action::Mime#format
|
411
|
-
# @see Hanami::Action::Mime#content_type
|
412
|
-
# @see Hanami::Controller::Configuration#format
|
413
|
-
#
|
414
|
-
# @example Default scenario
|
415
|
-
# require 'hanami/controller'
|
416
|
-
#
|
417
|
-
# class Show
|
418
|
-
# include Hanami::Action
|
419
|
-
#
|
420
|
-
# def call(params)
|
421
|
-
# end
|
422
|
-
# end
|
423
|
-
#
|
424
|
-
# action = Show.new
|
425
|
-
#
|
426
|
-
# _, headers, _ = action.call({ 'HTTP_ACCEPT' => '*/*' })
|
427
|
-
# headers['Content-Type'] # => 'application/octet-stream'
|
428
|
-
# action.format # => :all
|
429
|
-
#
|
430
|
-
# _, headers, _ = action.call({ 'HTTP_ACCEPT' => 'text/html' })
|
431
|
-
# headers['Content-Type'] # => 'text/html'
|
432
|
-
# action.format # => :html
|
433
|
-
#
|
434
|
-
# @example Simple usage
|
435
|
-
# require 'hanami/controller'
|
436
|
-
#
|
437
|
-
# class Show
|
438
|
-
# include Hanami::Action
|
439
|
-
#
|
440
|
-
# def call(params)
|
441
|
-
# # ...
|
442
|
-
# self.format = :json
|
443
|
-
# end
|
444
|
-
# end
|
445
|
-
#
|
446
|
-
# action = Show.new
|
447
|
-
#
|
448
|
-
# _, headers, _ = action.call({ 'HTTP_ACCEPT' => '*/*' })
|
449
|
-
# headers['Content-Type'] # => 'application/json'
|
450
|
-
# action.format # => :json
|
451
|
-
#
|
452
|
-
# @example Unknown format
|
453
|
-
# require 'hanami/controller'
|
454
|
-
#
|
455
|
-
# class Show
|
456
|
-
# include Hanami::Action
|
457
|
-
#
|
458
|
-
# def call(params)
|
459
|
-
# # ...
|
460
|
-
# self.format = :unknown
|
461
|
-
# end
|
462
|
-
# end
|
463
|
-
#
|
464
|
-
# action = Show.new
|
465
|
-
# action.call({ 'HTTP_ACCEPT' => '*/*' })
|
466
|
-
# # => raise Hanami::Controller::UnknownFormatError
|
467
|
-
#
|
468
|
-
# @example Custom mime type/format
|
469
|
-
# require 'hanami/controller'
|
470
|
-
#
|
471
|
-
# Hanami::Controller.configure do
|
472
|
-
# format :custom, 'application/custom'
|
473
|
-
# end
|
474
|
-
#
|
475
|
-
# class Show
|
476
|
-
# include Hanami::Action
|
477
|
-
#
|
478
|
-
# def call(params)
|
479
|
-
# # ...
|
480
|
-
# self.format = :custom
|
481
|
-
# end
|
482
|
-
# end
|
483
|
-
#
|
484
|
-
# _, headers, _ = action.call({ 'HTTP_ACCEPT' => '*/*' })
|
485
|
-
# headers['Content-Type'] # => 'application/custom'
|
486
|
-
# action.format # => :custom
|
487
|
-
def format=(format)
|
488
|
-
@format = Utils::Kernel.Symbol(format)
|
489
|
-
@content_type = self.class.format_to_mime_type(@format)
|
129
|
+
def self.format_for(content_type)
|
130
|
+
TYPES.key(content_type)
|
490
131
|
end
|
491
132
|
|
492
|
-
#
|
493
|
-
#
|
494
|
-
# @return [Boolean] true if the given mime type matches Accept
|
495
|
-
#
|
496
|
-
# @since 0.1.0
|
497
|
-
#
|
133
|
+
# Transforms symbols to MIME Types
|
498
134
|
# @example
|
499
|
-
#
|
500
|
-
#
|
501
|
-
# class Show
|
502
|
-
# include Hanami::Action
|
503
|
-
#
|
504
|
-
# def call(params)
|
505
|
-
# # ...
|
506
|
-
# # @_env['HTTP_ACCEPT'] # => 'text/html,application/xhtml+xml,application/xml;q=0.9'
|
507
|
-
#
|
508
|
-
# accept?('text/html') # => true
|
509
|
-
# accept?('application/xml') # => true
|
510
|
-
# accept?('application/json') # => false
|
511
|
-
#
|
135
|
+
# restrict_mime_types(configuration, [:json]) #=> ["application/json"]
|
512
136
|
#
|
137
|
+
# @return [Array<String>, nil]
|
513
138
|
#
|
514
|
-
#
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
# end
|
521
|
-
def accept?(mime_type)
|
522
|
-
!!::Rack::Utils.q_values(accept).find do |mime, _|
|
523
|
-
::Rack::Mime.match?(mime_type, mime)
|
139
|
+
# @raise [Hanami::Controller::UnknownFormatError] if the format is invalid
|
140
|
+
def self.restrict_mime_types(configuration, accepted_formats)
|
141
|
+
return if accepted_formats.empty?
|
142
|
+
|
143
|
+
mime_types = accepted_formats.map do |format|
|
144
|
+
format_to_mime_type(format, configuration)
|
524
145
|
end
|
525
|
-
end
|
526
146
|
|
527
|
-
|
528
|
-
# @api private
|
529
|
-
def accept
|
530
|
-
@accept ||= @_env[HTTP_ACCEPT] || DEFAULT_ACCEPT
|
531
|
-
end
|
147
|
+
accepted_mime_types = mime_types & configuration.mime_types
|
532
148
|
|
533
|
-
|
534
|
-
|
535
|
-
# @return [TrueClass,FalseClass] the result of the check
|
536
|
-
#
|
537
|
-
# @since 0.8.0
|
538
|
-
# @api private
|
539
|
-
def accept_header?
|
540
|
-
accept != DEFAULT_ACCEPT
|
149
|
+
return if accepted_mime_types.empty?
|
150
|
+
accepted_mime_types
|
541
151
|
end
|
542
152
|
|
543
|
-
#
|
544
|
-
#
|
545
|
-
# or the custom registered ones (see Hanami::Controller::Configuration#format).
|
153
|
+
# Use for checking the Content-Type header to make sure is valid based
|
154
|
+
# on the accepted_mime_types
|
546
155
|
#
|
547
|
-
#
|
156
|
+
# If no Content-Type is sent in the request it will check the default_request_format
|
548
157
|
#
|
549
|
-
# @
|
550
|
-
|
551
|
-
|
552
|
-
# @see Hanami::Action::Mime#MIME_TYPES
|
553
|
-
# @see Hanami::Controller::Configuration#format
|
554
|
-
#
|
555
|
-
# @api private
|
556
|
-
def content_type_from_accept_header
|
557
|
-
best_q_match(accept, configuration.mime_types)
|
558
|
-
end
|
559
|
-
|
560
|
-
# @since 0.5.0
|
561
|
-
# @api private
|
562
|
-
def default_response_type
|
563
|
-
self.class.format_to_mime_type(configuration.default_response_format) if configuration.default_response_format
|
564
|
-
end
|
565
|
-
|
566
|
-
# @since 0.2.0
|
567
|
-
# @api private
|
568
|
-
def default_content_type
|
569
|
-
self.class.format_to_mime_type(
|
570
|
-
configuration.default_request_format
|
571
|
-
) if configuration.default_request_format
|
572
|
-
end
|
158
|
+
# @return [TrueClass, FalseClass]
|
159
|
+
def self.accepted_mime_type?(request, accepted_mime_types, configuration)
|
160
|
+
mime_type = request.env[CONTENT_TYPE] || default_content_type(configuration) || DEFAULT_CONTENT_TYPE
|
573
161
|
|
574
|
-
|
575
|
-
# @api private
|
576
|
-
def detect_format
|
577
|
-
configuration.format_for(content_type) || MIME_TYPES.key(content_type)
|
162
|
+
!accepted_mime_types.find { |mt| ::Rack::Mime.match?(mt, mime_type) }.nil?
|
578
163
|
end
|
579
164
|
|
580
|
-
#
|
581
|
-
#
|
582
|
-
|
583
|
-
|
165
|
+
# Use for setting the content_type and charset if the response
|
166
|
+
#
|
167
|
+
# @see Hanami::Action::Mime#call
|
168
|
+
#
|
169
|
+
# @return [String]
|
170
|
+
def self.calculate_content_type_with_charset(configuration, request, accepted_mime_types)
|
171
|
+
charset = self.charset(configuration.default_charset)
|
172
|
+
content_type = self.content_type(configuration, request, accepted_mime_types)
|
173
|
+
content_type_with_charset(content_type, charset)
|
584
174
|
end
|
585
175
|
|
586
|
-
#
|
587
|
-
# @api private
|
588
|
-
def content_type_with_charset
|
589
|
-
"#{content_type}; charset=#{charset}"
|
590
|
-
end
|
176
|
+
# private
|
591
177
|
|
592
178
|
# Patched version of <tt>Rack::Utils.best_q_match</tt>.
|
593
179
|
#
|
594
|
-
# @since 0.
|
180
|
+
# @since 2.0.0
|
595
181
|
# @api private
|
596
182
|
#
|
597
183
|
# @see http://www.rubydoc.info/gems/rack/Rack/Utils#best_q_match-class_method
|
@@ -599,7 +185,7 @@ module Hanami
|
|
599
185
|
# @see https://github.com/hanami/controller/issues/59
|
600
186
|
# @see https://github.com/hanami/controller/issues/104
|
601
187
|
# @see https://github.com/hanami/controller/issues/275
|
602
|
-
def best_q_match(q_value_header, available_mimes)
|
188
|
+
def self.best_q_match(q_value_header, available_mimes = TYPES.values)
|
603
189
|
::Rack::Utils.q_values(q_value_header).each_with_index.map do |(req_mime, quality), index|
|
604
190
|
match = available_mimes.find { |am| ::Rack::Mime.match?(am, req_mime) }
|
605
191
|
next unless match
|