hanami-controller 1.0.0.beta1 → 1.0.0.beta2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f0fb43da2ad920ba9c799b41f4ccfc87eb5b438
4
- data.tar.gz: 294e4ed9ebf6e18c13c52d560efb181f69ded99b
3
+ metadata.gz: a55f1d51fe4e8c7f3d631f070eab1233fadc0c3e
4
+ data.tar.gz: c9eb6f944227efb95943885e866adf40be3614dd
5
5
  SHA512:
6
- metadata.gz: 6b7ce52381b3e383caf8a169f9c40af67e8a8a546503c89d0b3b7642fe8e36321ab3bf5bee8d844d9e26ace64d5c1c49f894f642b469dcac63c712d5025246b0
7
- data.tar.gz: f6e6cfe2e117ce0d3946b308b2684dfd53ae31783510ec143f10cd9959e671338abe613bc70ef2070a2c5ecdd1383fbcffad76070cfd76e457ebf218be22759e
6
+ metadata.gz: 01cbf64f7661609247d8eeb2ed3b73168a0e21dbcd69f48f60bd79d828db788099bdd70f4192a47090e8babd007faa75ac50d6d480dc9235d5aa39a1fe141961
7
+ data.tar.gz: f24e1ee54fe5b990d4261c92889d602dd9e6fd9dfaef31dc975a6ff122a32ffc69c5c806b07cc24931919dac68d2a7ad152b841c9a1c61f61c6a3627fadc99cb
data/CHANGELOG.md CHANGED
@@ -1,7 +1,17 @@
1
1
  # Hanami::Controller
2
2
  Complete, fast and testable actions for Rack
3
3
 
4
- ## v1.0.0beta1 - 2017-02-14
4
+ ## v1.0.0.beta2 - 2017-03-02
5
+ ### Added
6
+ - [Marcello Rocha] Add `Action#unsafe_send_file` to send files outside of the public directory of a project
7
+
8
+ ### Fixed
9
+ - [Anton Davydov] Ensure HTTP Cache to not crash when `HTTP_IF_MODIFIED_SINCE` and `HTTP_IF_NONE_MATCH` have blank values
10
+ - [Luca Guidi] Keep flash values after a redirect
11
+ - [Craig M. Wellington & Luca Guidi] Ensure to return 404 when `Action#send_file` cannot find a file with a globbed route
12
+ - [Luca Guidi] Don't mutate Rack env when sending files
13
+
14
+ ## v1.0.0.beta1 - 2017-02-14
5
15
  ### Added
6
16
  - [Luca Guidi] Official support for Ruby: MRI 2.4
7
17
 
@@ -56,7 +56,7 @@ module Hanami
56
56
  end
57
57
 
58
58
  def fresh?
59
- modified_since && Time.httpdate(modified_since).to_i >= @value.to_i
59
+ !Hanami::Utils::Blank.blank?(modified_since) && Time.httpdate(modified_since).to_i >= @value.to_i
60
60
  end
61
61
 
62
62
  def header
@@ -31,6 +31,7 @@ module Hanami
31
31
  @session = session
32
32
  @request_id = request_id
33
33
  @last_request_id = session[LAST_REQUEST_KEY]
34
+ @merged = {}
34
35
 
35
36
  session[SESSION_KEY] ||= {}
36
37
  session[SESSION_KEY][request_id] ||= {}
@@ -54,7 +55,7 @@ module Hanami
54
55
  # @since 0.3.0
55
56
  # @api private
56
57
  def [](key)
57
- last_request_flash.merge(data).fetch(key) do
58
+ @merged.fetch(key) do
58
59
  _values.find {|data| !data[key].nil? }
59
60
  end
60
61
  end
@@ -73,8 +74,9 @@ module Hanami
73
74
  # It may happen that `#flash` is nil, and those two methods will fail
74
75
  unless flash.nil?
75
76
  expire_stale!
76
- set_last_request_id!
77
77
  remove!
78
+ merge!
79
+ set_last_request_id!
78
80
  end
79
81
  end
80
82
 
@@ -89,6 +91,13 @@ module Hanami
89
91
  _values.all?(&:empty?)
90
92
  end
91
93
 
94
+ # @return [String]
95
+ #
96
+ # @since 1.0.0.beta2
97
+ def inspect
98
+ "#<#{self.class}:#{'0x%x' % (__id__ << 1)} #{@merged.inspect}>"
99
+ end
100
+
92
101
  private
93
102
 
94
103
  # The flash registry that holds the data for **all** the recent requests
@@ -135,6 +144,14 @@ module Hanami
135
144
  @session.delete(SESSION_KEY) if empty?
136
145
  end
137
146
 
147
+ # @since 1.0.0.beta2
148
+ # @api private
149
+ #
150
+ # @see Hanami::Action::Flash#[]
151
+ def merge!
152
+ @merged = last_request_flash.merge(data)
153
+ end
154
+
138
155
  # Values from all the stored requests
139
156
  #
140
157
  # @return [Array]
@@ -10,12 +10,36 @@ module Hanami
10
10
  #
11
11
  # @since 0.1.0
12
12
  module Rack
13
+ # Rack SPEC response code
14
+ #
15
+ # @since 1.0.0.beta2
16
+ # @api private
17
+ RESPONSE_CODE = 0
18
+
19
+ # Rack SPEC response headers
20
+ #
21
+ # @since 1.0.0.beta2
22
+ # @api private
23
+ RESPONSE_HEADERS = 1
24
+
25
+ # Rack SPEC response body
26
+ #
27
+ # @since 1.0.0.beta2
28
+ # @api private
29
+ RESPONSE_BODY = 2
30
+
13
31
  # The default HTTP response code
14
32
  #
15
33
  # @since 0.1.0
16
34
  # @api private
17
35
  DEFAULT_RESPONSE_CODE = 200
18
36
 
37
+ # Not Found
38
+ #
39
+ # @since 1.0.0.beta2
40
+ # @api private
41
+ NOT_FOUND = 404
42
+
19
43
  # The default Rack response body
20
44
  #
21
45
  # @since 0.1.0
@@ -36,6 +60,19 @@ module Hanami
36
60
  # @api private
37
61
  REQUEST_METHOD = 'REQUEST_METHOD'.freeze
38
62
 
63
+ # The Content-Length HTTP header
64
+ #
65
+ # @since 1.0.0.beta2
66
+ # @api private
67
+ CONTENT_LENGTH = 'Content-Length'.freeze
68
+
69
+ # The non-standard HTTP header to pass the control over when a resource
70
+ # cannot be found by the current endpoint
71
+ #
72
+ # @since 1.0.0.beta2
73
+ # @api private
74
+ X_CASCADE = 'X-Cascade'.freeze
75
+
39
76
  # HEAD request
40
77
  #
41
78
  # @since 0.3.2
@@ -257,6 +294,7 @@ module Hanami
257
294
  end
258
295
 
259
296
  # Send a file as response.
297
+ # <tt>This method only sends files from the public directory</tt>
260
298
  #
261
299
  # It automatically handle the following cases:
262
300
  #
@@ -282,9 +320,37 @@ module Hanami
282
320
  # end
283
321
  # end
284
322
  def send_file(path)
285
- result = File.new(path, self.class.configuration.public_directory).call(@_env)
286
- headers.merge!(result[1])
287
- halt result[0], result[2]
323
+ _send_file(
324
+ File.new(path, self.class.configuration.public_directory).call(@_env)
325
+ )
326
+ end
327
+
328
+ # Send a file as response from anywhere in the file system.
329
+ #
330
+ # @see Hanami::Action::Rack#send_file
331
+ #
332
+ # @param path [String, Pathname] path to the file to be sent
333
+ # @return [void]
334
+ #
335
+ # @since 1.0.0.beta2
336
+ #
337
+ # @example
338
+ # require 'hanami/controller'
339
+ #
340
+ # class Show
341
+ # include Hanami::Action
342
+ #
343
+ # def call(params)
344
+ # # ...
345
+ # unsafe_send_file Pathname.new('/tmp/path/to/file')
346
+ # end
347
+ # end
348
+ def unsafe_send_file(path)
349
+ directory = self.class.configuration.root_directory if Pathname.new(path).relative?
350
+
351
+ _send_file(
352
+ File.new(path, directory).call(@_env)
353
+ )
288
354
  end
289
355
 
290
356
  # Check if the current request is a HEAD
@@ -303,6 +369,20 @@ module Hanami
303
369
  def request_method
304
370
  @_env[REQUEST_METHOD]
305
371
  end
372
+
373
+ # @since 1.0.0.beta2
374
+ # @api private
375
+ def _send_file(response)
376
+ headers.merge!(response[RESPONSE_HEADERS])
377
+
378
+ if response[RESPONSE_CODE] == NOT_FOUND
379
+ headers.delete(X_CASCADE)
380
+ headers.delete(CONTENT_LENGTH)
381
+ halt NOT_FOUND
382
+ else
383
+ halt response[RESPONSE_CODE], response[RESPONSE_BODY]
384
+ end
385
+ end
306
386
  end
307
387
  end
308
388
  end
@@ -10,7 +10,6 @@ module Hanami
10
10
  #
11
11
  # @see Hanami::Action::Rack#send_file
12
12
  class File
13
-
14
13
  # The key that returns path info from the Rack env
15
14
  #
16
15
  # @since 1.0.0.beta1
@@ -22,14 +21,16 @@ module Hanami
22
21
  # @since 0.4.3
23
22
  # @api private
24
23
  def initialize(path, root)
25
- @file = ::Rack::File.new(root)
26
- @path = path
24
+ @file = ::Rack::File.new(root.to_s)
25
+ @path = path.to_s
27
26
  end
28
27
 
29
28
  # @since 0.4.3
30
29
  # @api private
31
30
  def call(env)
31
+ env = env.dup
32
32
  env[PATH_INFO] = @path
33
+
33
34
  @file.get(env)
34
35
  rescue Errno::ENOENT
35
36
  [404, {}, nil]
@@ -651,11 +651,15 @@ module Hanami
651
651
  @formats.key(format)
652
652
  end
653
653
 
654
+ # @api private
655
+ # @since 1.0.0.beta2
656
+ attr_reader :root_directory
657
+
654
658
  def public_directory(value = nil)
655
659
  if value.nil?
656
660
  @public_directory
657
661
  else
658
- @public_directory = Pathname.new(Dir.pwd).join(value).to_s
662
+ @public_directory = root_directory.join(value).to_s
659
663
  end
660
664
  end
661
665
 
@@ -706,7 +710,8 @@ module Hanami
706
710
  @default_charset = nil
707
711
  @default_headers = {}
708
712
  @cookies = {}
709
- @public_directory = ::File.join(Dir.pwd, "public")
713
+ @root_directory = ::Pathname.new(Dir.pwd).realpath
714
+ @public_directory = root_directory.join(DEFAULT_PUBLIC_DIRECTORY).to_s
710
715
  @action_module = ::Hanami::Action
711
716
  end
712
717
 
@@ -3,6 +3,6 @@ module Hanami
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '1.0.0.beta1'.freeze
6
+ VERSION = '1.0.0.beta2'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta1
4
+ version: 1.0.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-02-14 00:00:00.000000000 Z
13
+ date: 2017-03-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rack