hanami-controller 1.0.0.beta1 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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