lib/roda/plugins/public.rb in roda-3.32.0 vs lib/roda/plugins/public.rb in roda-3.33.0

- old
+ new

@@ -40,20 +40,23 @@ # Use options given to setup a Rack::File instance for serving files. Options: # :default_mime :: The default mime type to use if the mime type is not recognized. # :gzip :: Whether to serve already gzipped files with a .gz extension for clients # supporting gzipped transfer encoding. + # :brotli :: Whether to serve already brotli-compressed files with a .br extension + # for clients supporting brotli transfer encoding. # :headers :: A hash of headers to use for statically served files # :root :: Use this option for the root of the public directory (default: "public") def self.configure(app, opts={}) if opts[:root] app.opts[:public_root] = app.expand_path(opts[:root]) elsif !app.opts[:public_root] app.opts[:public_root] = app.expand_path("public") end app.opts[:public_server] = ::Rack::File.new(app.opts[:public_root], opts[:headers]||{}, opts[:default_mime] || 'text/plain') app.opts[:public_gzip] = opts[:gzip] + app.opts[:public_brotli] = opts[:brotli] end module RequestMethods # Serve files from the public directory if the file exists and this is a GET request. def public @@ -63,28 +66,13 @@ roda_opts = roda_class.opts server = roda_opts[:public_server] path = ::File.join(server.root, *public_path_segments(path)) - if roda_opts[:public_gzip] && env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/ - gzip_path = path + '.gz' + public_serve_compressed(server, path, '.br', 'br') if roda_opts[:public_brotli] + public_serve_compressed(server, path, '.gz', 'gzip') if roda_opts[:public_gzip] - if public_file_readable?(gzip_path) - res = public_serve(server, gzip_path) - headers = res[1] - - unless res[0] == 304 - if mime_type = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain') - headers['Content-Type'] = mime_type - end - headers['Content-Encoding'] = 'gzip' - end - - halt res - end - end - if public_file_readable?(path) halt public_serve(server, path) end end end @@ -109,9 +97,29 @@ ::File.file?(path) && ::File.readable?(path) rescue SystemCallError # :nocov: false # :nocov: + end + + def public_serve_compressed(server, path, suffix, encoding) + if env['HTTP_ACCEPT_ENCODING'] =~ /\b#{encoding}\b/ + compressed_path = path + suffix + + if public_file_readable?(compressed_path) + res = public_serve(server, compressed_path) + headers = res[1] + + unless res[0] == 304 + if mime_type = ::Rack::Mime.mime_type(::File.extname(path), 'text/plain') + headers['Content-Type'] = mime_type + end + headers['Content-Encoding'] = encoding + end + + halt res + end + end end if ::Rack.release > '2' # Serve the given path using the given Rack::File server. def public_serve(server, path)