roda 3.101.0 → 3.102.0

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
  SHA256:
3
- metadata.gz: a7b1458c27a93cf829302766fa6299abadc1b52a7cc45375c23e588d0a28bbf7
4
- data.tar.gz: d9312bd50698b9eba385272903d3c12a04f5d699185f299b5ddc250fdcbac2ac
3
+ metadata.gz: f36503d930c18c02148a0da9c30d8f7166790402e04a4220e5a792dc2502779a
4
+ data.tar.gz: 533b40ec81263d73cbcf60d3a9807434ba0ca1a0d92ee1ca3fc59226edc80c96
5
5
  SHA512:
6
- metadata.gz: 1483575934392739f5ee8c79cd74ca78f434ba9d798d9c2066f24f737f39fbfd0c0ad818acbd28b113ffaedf7751b3c45302ee17f8590c1dd47d6072de785453
7
- data.tar.gz: 20f6bc4308bcebd17abc063c4303487d80fd2ac63a1a35b35b99ae0ed2a2a82cf2c5effb480464817a3c1fbed343006a74547743022b1b2e2717c16164f06740
6
+ metadata.gz: 0afa286317e707bd64e903fe6d5225d17a499606fdc71253769795818505793a0a12d42f8999c5eb8e678481da09d82aacb495b7a228ab47a6437b721807f57b
7
+ data.tar.gz: 14e94a735b1f88e45ff4c2c21b4c3acb7d96cf75f3435695b0c13a0f22471f6c619d3b0915b2794dff745ea88a333c0fd5e629c9566326f5e15d8b4cedd2be32
@@ -5,7 +5,7 @@ class Roda
5
5
  module RodaPlugins
6
6
  # The host_authorization plugin allows configuring an authorized host or
7
7
  # an array of authorized hosts. Then in the routing tree, you can check
8
- # whether the request uses an authorized host via the +check_host_authorized!+
8
+ # whether the request uses an authorized host via the +check_host_authorization!+
9
9
  # method.
10
10
  #
11
11
  # If the request doesn't match one of the authorized hosts, the
@@ -16,7 +16,7 @@ class Roda
16
16
  # By default, an empty response using status 403 will be returned for requests
17
17
  # with unauthorized hosts.
18
18
  #
19
- # Because +check_host_authorized!+ is an instance method, you can easily choose
19
+ # Because +check_host_authorization!+ is an instance method, you can easily choose
20
20
  # to only check for authorization in certain routes, or to check it after
21
21
  # other processing. For example, you could check for authorized hosts after
22
22
  # serving static files, since the serving of static files should not be
@@ -24,7 +24,7 @@ class Roda
24
24
  #
25
25
  # = Usage
26
26
  #
27
- # In your routing tree, call the +check_host_authorized!+ method at the point you
27
+ # In your routing tree, call the +check_host_authorization!+ method at the point you
28
28
  # want to check for authorized hosts:
29
29
  #
30
30
  # plugin :host_authorization, 'www.example.com'
@@ -32,7 +32,7 @@ class Roda
32
32
  #
33
33
  # route do |r|
34
34
  # r.public
35
- # check_host_authorized!
35
+ # check_host_authorization!
36
36
  #
37
37
  # # ...
38
38
  # end
@@ -153,4 +153,3 @@ class Roda
153
153
  register_plugin(:host_authorization, HostAuthorization)
154
154
  end
155
155
  end
156
-
@@ -0,0 +1,94 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'rack/mime'
4
+
5
+ #
6
+ class Roda
7
+ module RodaPlugins
8
+ # The attachment plugin adds a response.attachment method.
9
+ # When called with no filename, +attachment+ sets the Content-Disposition
10
+ # to attachment. When called with a filename,+attachment+ sets the Content-Disposition
11
+ # to attachment with the appropriate filename parameter, and if the filename
12
+ # extension is recognized, this also sets the Content-Type to the appropriate
13
+ # MIME type if not already set.
14
+ #
15
+ # # set Content-Disposition to 'attachment'
16
+ # response.attachment
17
+ #
18
+ # # set Content-Disposition to 'attachment; filename="a.csv"',
19
+ # # also set Content-Type to 'text/csv'
20
+ # response.attachment 'a.csv'
21
+ #
22
+ # == License
23
+ #
24
+ # The implementation was originally taken from Sinatra,
25
+ # which is also released under the MIT License:
26
+ #
27
+ # Copyright (c) 2007, 2008, 2009 Blake Mizerany
28
+ # Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
29
+ #
30
+ # Permission is hereby granted, free of charge, to any person
31
+ # obtaining a copy of this software and associated documentation
32
+ # files (the "Software"), to deal in the Software without
33
+ # restriction, including without limitation the rights to use,
34
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ # copies of the Software, and to permit persons to whom the
36
+ # Software is furnished to do so, subject to the following
37
+ # conditions:
38
+ #
39
+ # The above copyright notice and this permission notice shall be
40
+ # included in all copies or substantial portions of the Software.
41
+ #
42
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
43
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
44
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
45
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
46
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
47
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
48
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
49
+ # OTHER DEALINGS IN THE SOFTWARE.
50
+ module ResponseAttachment
51
+ UTF8_ENCODING = Encoding.find('UTF-8')
52
+ ISO88591_ENCODING = Encoding.find('ISO-8859-1')
53
+ BINARY_ENCODING = Encoding.find('BINARY')
54
+
55
+ module ResponseMethods
56
+ # Set the Content-Disposition to "attachment" with the specified filename,
57
+ # instructing the user agents to prompt to save.
58
+ def attachment(filename = nil, disposition='attachment')
59
+ if filename
60
+ param_filename = File.basename(filename)
61
+ encoding = param_filename.encoding
62
+
63
+ needs_encoding = param_filename.gsub!(/[^ 0-9a-zA-Z!\#$&\+\.\^_`\|~]+/, '-')
64
+ params = "; filename=#{param_filename.inspect}"
65
+
66
+ if needs_encoding && (encoding == UTF8_ENCODING || encoding == ISO88591_ENCODING)
67
+ # File name contains non attr-char characters from RFC 5987 Section 3.2.1
68
+
69
+ encoded_filename = File.basename(filename).force_encoding(BINARY_ENCODING)
70
+ # Similar regexp as above, but treat each byte separately, and encode
71
+ # space characters, since those aren't allowed in attr-char
72
+ encoded_filename.gsub!(/[^0-9a-zA-Z!\#$&\+\.\^_`\|~]/) do |c|
73
+ "%%%X" % c.ord
74
+ end
75
+
76
+ encoded_params = "; filename*=#{encoding.to_s}''#{encoded_filename}"
77
+ end
78
+
79
+ unless @headers[RodaResponseHeaders::CONTENT_TYPE]
80
+ ext = File.extname(filename)
81
+ if !ext.empty? && (content_type = Rack::Mime.mime_type(ext, nil))
82
+ @headers[RodaResponseHeaders::CONTENT_TYPE] = content_type
83
+ end
84
+ end
85
+ end
86
+
87
+ @headers[RodaResponseHeaders::CONTENT_DISPOSITION] = "#{disposition}#{params}#{encoded_params}"
88
+ end
89
+ end
90
+ end
91
+
92
+ register_plugin(:response_attachment, ResponseAttachment)
93
+ end
94
+ end
@@ -0,0 +1,127 @@
1
+ # frozen-string-literal: true
2
+
3
+ begin
4
+ require 'rack/files'
5
+ rescue LoadError
6
+ require 'rack/file'
7
+ end
8
+
9
+ #
10
+ class Roda
11
+ module RodaPlugins
12
+ # The send_file plugin adds a send_file method, used for
13
+ # returning the contents of a file as the body of a request.
14
+ # It also loads the response_attachment plugin to set the
15
+ # Content-Disposition and Content-Type based on the file's
16
+ # extension.
17
+ #
18
+ # senf_file will serve the file with the given path from the file system:
19
+ #
20
+ # send_file 'path/to/file.txt'
21
+ #
22
+ # Options:
23
+ #
24
+ # :disposition :: Set the Content-Disposition to the given disposition.
25
+ # :filename :: Set the Content-Disposition to attachment (unless :disposition is set),
26
+ # and set the filename parameter to the value.
27
+ # :last_modified :: Explicitly set the Last-Modified header to the given value, and
28
+ # return a not modified response if there has not been modified since
29
+ # the previous request. This option requires the caching plugin.
30
+ # :status :: Override the status for the response.
31
+ # :type :: Set the Content-Type to use for this response.
32
+ #
33
+ # == License
34
+ #
35
+ # The implementation was originally taken from Sinatra,
36
+ # which is also released under the MIT License:
37
+ #
38
+ # Copyright (c) 2007, 2008, 2009 Blake Mizerany
39
+ # Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
40
+ #
41
+ # Permission is hereby granted, free of charge, to any person
42
+ # obtaining a copy of this software and associated documentation
43
+ # files (the "Software"), to deal in the Software without
44
+ # restriction, including without limitation the rights to use,
45
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
46
+ # copies of the Software, and to permit persons to whom the
47
+ # Software is furnished to do so, subject to the following
48
+ # conditions:
49
+ #
50
+ # The above copyright notice and this permission notice shall be
51
+ # included in all copies or substantial portions of the Software.
52
+ #
53
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
54
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
55
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
56
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
57
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
58
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
59
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
60
+ # OTHER DEALINGS IN THE SOFTWARE.
61
+ module SendFile
62
+ RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
63
+
64
+ # Depend on the status_303 plugin.
65
+ def self.load_dependencies(app)
66
+ app.plugin :response_attachment
67
+ end
68
+
69
+ module InstanceMethods
70
+ # Use the contents of the file at +path+ as the response body. See plugin documentation for options.
71
+ def send_file(path, opts = OPTS)
72
+ r = @_request
73
+ res = @_response
74
+ headers = res.headers
75
+ if (type = opts[:type]) || !headers[RodaResponseHeaders::CONTENT_TYPE]
76
+ type_str = type.to_s
77
+
78
+ if type_str.include?('/')
79
+ type = type_str
80
+ else
81
+ if type
82
+ type = ".#{type}" unless type_str.start_with?(".")
83
+ else
84
+ type = ::File.extname(path)
85
+ end
86
+
87
+ type &&= Rack::Mime.mime_type(type, nil)
88
+ type ||= 'application/octet-stream'
89
+ end
90
+
91
+ headers[RodaResponseHeaders::CONTENT_TYPE] = type
92
+ end
93
+
94
+ disposition = opts[:disposition]
95
+ filename = opts[:filename]
96
+ if disposition || filename
97
+ disposition ||= 'attachment'
98
+ filename = path if filename.nil?
99
+ res.attachment(filename, disposition)
100
+ end
101
+
102
+ if lm = opts[:last_modified]
103
+ r.last_modified(lm)
104
+ end
105
+
106
+ file = RACK_FILES.new nil
107
+ s, h, b = if Rack.release > '2'
108
+ file.serving(r, path)
109
+ else
110
+ file.path = path
111
+ file.serving(env)
112
+ end
113
+
114
+ res.status = opts[:status] || s
115
+ headers.delete(RodaResponseHeaders::CONTENT_LENGTH)
116
+ headers.replace(h.merge!(headers))
117
+ r.halt res.finish_with_body(b)
118
+ rescue Errno::ENOENT
119
+ response.status = 404
120
+ r.halt
121
+ end
122
+ end
123
+ end
124
+
125
+ register_plugin(:send_file, SendFile)
126
+ end
127
+ end
@@ -1,12 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  require 'rack/mime'
4
- begin
5
- require 'rack/files'
6
- rescue LoadError
7
- require 'rack/file'
8
- end
9
-
10
4
 
11
5
  #
12
6
  class Roda
@@ -91,20 +85,7 @@ class Roda
91
85
  #
92
86
  # === send_file
93
87
  #
94
- # This will serve the file with the given path from the file system:
95
- #
96
- # send_file 'path/to/file.txt'
97
- #
98
- # Options:
99
- #
100
- # :disposition :: Set the Content-Disposition to the given disposition.
101
- # :filename :: Set the Content-Disposition to attachment (unless :disposition is set),
102
- # and set the filename parameter to the value.
103
- # :last_modified :: Explicitly set the Last-Modified header to the given value, and
104
- # return a not modified response if there has not been modified since
105
- # the previous request. This option requires the caching plugin.
106
- # :status :: Override the status for the response.
107
- # :type :: Set the Content-Type to use for this response.
88
+ # See send_file plugin documentation for details.
108
89
  #
109
90
  # == Response Methods Added
110
91
  #
@@ -166,15 +147,7 @@ class Roda
166
147
  #
167
148
  # === attachment
168
149
  #
169
- # When called with no filename, +attachment+ just sets the Content-Disposition
170
- # to attachment. When called with a filename, this sets the Content-Disposition
171
- # to attachment with the appropriate filename parameter, and if the filename
172
- # extension is recognized, this also sets the Content-Type to the appropriate
173
- # MIME type if not already set.
174
- #
175
- # attachment # set Content-Disposition to 'attachment'
176
- # attachment 'a.csv' # set Content-Disposition to 'attachment;filename="a.csv"',
177
- # # also set Content-Type to 'text/csv'
150
+ # See response_attachment plugin for details.
178
151
  #
179
152
  # === status predicates
180
153
  #
@@ -219,15 +192,10 @@ class Roda
219
192
  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
220
193
  # OTHER DEALINGS IN THE SOFTWARE.
221
194
  module SinatraHelpers
222
- UTF8_ENCODING = Encoding.find('UTF-8')
223
- ISO88591_ENCODING = Encoding.find('ISO-8859-1')
224
- BINARY_ENCODING = Encoding.find('BINARY')
225
-
226
- RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
227
-
228
195
  # Depend on the status_303 plugin.
229
196
  def self.load_dependencies(app, _opts = nil)
230
197
  app.plugin :status_303
198
+ app.plugin :send_file
231
199
  end
232
200
 
233
201
  # Add delegate methods to the route block scope
@@ -323,40 +291,9 @@ class Roda
323
291
  super(path, status)
324
292
  end
325
293
 
326
- # Use the contents of the file at +path+ as the response body. See plugin documentation for options.
294
+ # Backwards compatibility for callers of r.send_file.
327
295
  def send_file(path, opts = OPTS)
328
- res = response
329
- headers = res.headers
330
- if opts[:type] || !headers[RodaResponseHeaders::CONTENT_TYPE]
331
- res.content_type(opts[:type] || ::File.extname(path), :default => 'application/octet-stream')
332
- end
333
-
334
- disposition = opts[:disposition]
335
- filename = opts[:filename]
336
- if disposition || filename
337
- disposition ||= 'attachment'
338
- filename = path if filename.nil?
339
- res.attachment(filename, disposition)
340
- end
341
-
342
- if lm = opts[:last_modified]
343
- last_modified(lm)
344
- end
345
-
346
- file = RACK_FILES.new nil
347
- s, h, b = if Rack.release > '2'
348
- file.serving(self, path)
349
- else
350
- file.path = path
351
- file.serving(@env)
352
- end
353
-
354
- res.status = opts[:status] || s
355
- headers.delete(RodaResponseHeaders::CONTENT_LENGTH)
356
- headers.replace(h.merge!(headers))
357
- halt res.finish_with_body(b)
358
- rescue Errno::ENOENT
359
- not_found
296
+ scope.send_file(path, opts)
360
297
  end
361
298
 
362
299
  # Generates the absolute URI for a given path in the app.
@@ -438,39 +375,6 @@ class Roda
438
375
  @headers[RodaResponseHeaders::CONTENT_TYPE] = mime_type
439
376
  end
440
377
 
441
- # Set the Content-Disposition to "attachment" with the specified filename,
442
- # instructing the user agents to prompt to save.
443
- def attachment(filename = nil, disposition='attachment')
444
- if filename
445
- param_filename = File.basename(filename)
446
- encoding = param_filename.encoding
447
-
448
- needs_encoding = param_filename.gsub!(/[^ 0-9a-zA-Z!\#$&\+\.\^_`\|~]+/, '-')
449
- params = "; filename=#{param_filename.inspect}"
450
-
451
- if needs_encoding && (encoding == UTF8_ENCODING || encoding == ISO88591_ENCODING)
452
- # File name contains non attr-char characters from RFC 5987 Section 3.2.1
453
-
454
- encoded_filename = File.basename(filename).force_encoding(BINARY_ENCODING)
455
- # Similar regexp as above, but treat each byte separately, and encode
456
- # space characters, since those aren't allowed in attr-char
457
- encoded_filename.gsub!(/[^0-9a-zA-Z!\#$&\+\.\^_`\|~]/) do |c|
458
- "%%%X" % c.ord
459
- end
460
-
461
- encoded_params = "; filename*=#{encoding.to_s}''#{encoded_filename}"
462
- end
463
-
464
- unless @headers[RodaResponseHeaders::CONTENT_TYPE]
465
- ext = File.extname(filename)
466
- unless ext.empty?
467
- content_type(ext)
468
- end
469
- end
470
- end
471
- @headers[RodaResponseHeaders::CONTENT_DISPOSITION] = "#{disposition}#{params}#{encoded_params}"
472
- end
473
-
474
378
  # Whether or not the status is set to 1xx. Returns nil if status not yet set.
475
379
  def informational?
476
380
  @status.between?(100, 199) if @status
@@ -521,7 +425,7 @@ class Roda
521
425
  [:logger, :back].each do |meth|
522
426
  define_method(meth){@_request.public_send(meth)}
523
427
  end
524
- [:redirect, :uri, :url, :to, :send_file, :error, :not_found].each do |meth|
428
+ [:redirect, :uri, :url, :to, :error, :not_found].each do |meth|
525
429
  define_method(meth){|*v, &block| @_request.public_send(meth, *v, &block)}
526
430
  end
527
431
 
data/lib/roda/version.rb CHANGED
@@ -4,7 +4,7 @@ class Roda
4
4
  RodaMajorVersion = 3
5
5
 
6
6
  # The minor version of Roda, updated for new feature releases of Roda.
7
- RodaMinorVersion = 101
7
+ RodaMinorVersion = 102
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roda
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.101.0
4
+ version: 3.102.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
@@ -278,6 +278,7 @@ files:
278
278
  - lib/roda/plugins/render_locals.rb
279
279
  - lib/roda/plugins/request_aref.rb
280
280
  - lib/roda/plugins/request_headers.rb
281
+ - lib/roda/plugins/response_attachment.rb
281
282
  - lib/roda/plugins/response_content_type.rb
282
283
  - lib/roda/plugins/response_request.rb
283
284
  - lib/roda/plugins/route_block_args.rb
@@ -286,6 +287,7 @@ files:
286
287
  - lib/roda/plugins/run_handler.rb
287
288
  - lib/roda/plugins/run_require_slash.rb
288
289
  - lib/roda/plugins/sec_fetch_site_csrf.rb
290
+ - lib/roda/plugins/send_file.rb
289
291
  - lib/roda/plugins/sessions.rb
290
292
  - lib/roda/plugins/shared_vars.rb
291
293
  - lib/roda/plugins/sinatra_helpers.rb